Having a lot of trouble trying to set up a common UI library.
I've set up a yarn workspace which looks like this:
/monorepo
/common-16.13
/react-app-16.8.
/another-app-16.13
I then import common-16.13 into react-app-16.8 and use one of the components like this:
/react-app/home.js
import {SharedComponent} from "common"
However when I run the application I get this error:
react.development.js?80c6:1465 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
Inside common I have:
/src/components/SharedComponent.jsx:
import React from 'react';
import { Box } from 'material-ui/core';
export const ShareComponent = ()=> <Box>SharedComponent</Box>;
/src/components/index.js:
export { SharedComponen t} from 'SharedComponent';
/src/index.js:
export {SharedComponent } from './components';
package.json:
{
"name": "#libs/common",
"main": "dist/index.js",
"scripts" {
"build": "webpack"
}
}
/common/webpack.config.json:
const webpack = require('webpack');
module.exports = env => {
// Each key value generate a page specific bundle
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(ROOT_PATH, 'dist'),
publicPath: '/',
filename: 'index.js',
library: '#libs/common',
libraryTarget: 'umd'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'happypack/loader?id=jsx',
exclude: /node_modules/
}
]
},
// Automatically resolve below extensions
// Enable users to leave off the extensions when importing
resolve: {
symlinks: false,
extensions: ['*', '.js', '.jsx', '.css', '.scss']
},
plugins: [
new HappyPack({
id: 'css',
threadPool: happyThreadPool,
loaders: [
'cache-loader',
'style-loader',
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: true
}
},
'css-loader',
'sass-loader'
]
}),
new HappyPack({
id: 'jsx',
threadPool: happyThreadPool,
loaders: [
'cache-loader',
{
loader: 'babel-loader'
}
]
})
]
}
So I bundle common. Then in my react-app I yarn install #lib/common. Then I import SharedComponent into my react app:
/react-app/src/index.js:
import { SharedComponent } from '#libs/common';
/react-app/webpack.config.js:
{
// Each key value generate a page specific bundle
entry: {
index: './src/index.jsx',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel-loader'
},
]
},
// Automatically resolve below extensions
// Enable users to leave off the extensions when importing
resolve: {
extensions: ['*', '.js', '.jsx', '.css', 'scss'],
alias: {
react: path.resolve('./node_modules/react'),
}
},
output: {
path: path.resolve(ROOT_PATH, 'dist'),
publicPath: '/',
filename: '[name].bundle.js',
chunkFilename: '[id].bundle.js'
},
};
It bundles fine but when I run the application I run into the error above. I can't tell if it's related to how i'm exporting my common components, but it it seems right. I read I should have a react alias in my app, which I do. I'm using yarn workspaces and not sure if that's related somehow.
Run the following command:
yarn why react
If the result shows that you have multiple versions of react:
Remove all local installations
Install a single version of React in the root workspace instead
this is probably a bug coming from yarn
issue:
https://github.com/yarnpkg/yarn/issues/8540
I did a workaround by:
exporting my common package into a new private github repo
create access token
https://docs.github.com/en/free-pro-team#latest/github/authenticating-to-github/creating-a-personal-access-token
in my package.json dependencies I added:
"common": "git+https://{accessToken}:x-oauth-basic#github.com/{user}/{repo}.git",
It happened to me when when migrating existing project to mono repo.
It was caused because I copied the lock files into the packages folders.
I've solved it by deleting any node_modules and any lock(yarn.lock and package-lock) from any package folder and then running yarn install on root directory.
Related
I'm working on an outlook addin I have an express server running. I am setting webpack because I need to transpile js to es5 to make it work in Outlook Desktop. Here is the simplified project structure.
/public
/javascripts
ssoAuth.js
/addin
/commmands
commands.js
commands.html
/server
/bin
/helpers
app.js
The public folder is set as a static folder in my express server
app.use(express.static(path.join(__dirname, '../public'),
My problem is in commands.js I import ssoAuth.js with es6 module import with relative path :
import getGraphAccessToken from "/javascripts/ssoAuthES6.js";
It works fine when I run node ./server/app.js and load my outlook addin, but when I want to use Webpack to bundle, the import is not working, I get :
ERROR in ./addin/commands/commands.js
Module not found: Error: Can't resolve '/javascripts/ssoAuth.js'
I can't figure out how to configure webpack to allow the imports from the public folder.
Here are my webpack config files :
webpack.config.js :
const config = {
devtool: "source-map",
entry: {
polyfill: "#babel/polyfill",
commands: "./addin/commands/commands.js"
},
resolve: {
extensions: [".ts", ".tsx", ".html", ".js"]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
},
{
test: /\.html$/,
exclude: /node_modules/,
use: "html-loader"
},
{
test: /\.(png|jpg|jpeg|gif)$/,
use: "file-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
filename: "commands.html",
template: "./addin/commands/commands.html",
chunks: ["polyfill", "commands"]
})
]};
webpack.server.config.js :
return ({
entry: {
server: './server/bin/www',
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
module: {
rules: [
{
// Transpiles ES6-8 into ES5
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
},
plugins: [
new CopyWebpackPlugin([
{
to: "./public",
from: "./public"
}
])
]})
Can you help figure this out ? Is there a better folder structure that I should use to make it work ?
Thanks
You're using an absolute path
import getGraphAccessToken from "/javascripts/ssoAuthES6.js";
// ^ this will look in your topmost directory on your OS
The relative path, from commands.js, would be:
import getGraphAccessToken from "../../javascripts/ssoAuthES6.js";
Alternatively, you can set Webpack to look for modules from your root directory by adding the following to your webpack configuration:
{
// ...
resolve: {
modules: [path.resolve(__dirname, "src"), "node_modules"],
},
// ...
}
Then you can import from your project's root directory from anywhere, like so:
import getGraphAccessToken from "javascripts/ssoAuthES6.js";
Some other points:
Since you're setting the extensions: [".ts", ".tsx", ".html", ".js"], you don't need to provide file extensions for those imports
You specify .ts and .tsx in your webpack config, but you are using .js files. Consider removing the Typescript extensions
If you are using Typescript, you will need to update import paths in your tsconfig.json
You can consider import path aliases in both Webpack and Typescript to be more explicit that your imports are coming from your project root. Instructions here
I have babel loader in the library. Still after I add the library to the react application while yarn serve, I get the above error.
This is the webpack.dev.config.js (required in the webpack.config.js) in library-
//webpack.dev.config.js
const babelRCPath = require('#appfabric/infra-scripts').getConfigPath('babel', 'plugin');
const babelRCGenerator = require(babelRCPath);
const babelRC = babelRCGenerator([]);
module.exports = {
{
BaseModule: `${process.cwd()}/src/BaseModule`,
BaseObject: `${process.cwd()}/src/BaseObject`,
BaseWidget: `${process.cwd()}/src/widgets/BaseWidget`,
HOCWidget: `${process.cwd()}/src/widgets/HOCWidget`,
PortalWidget: `${process.cwd()}/src/widgets/PortalWidget`,
BaseActivator: `${process.cwd()}/src/application/BaseActivator`,
CorePlugin: `${process.cwd()}/src/application/CorePlugin`,
BaseAppDelegate: `${process.cwd()}/src/application/appdelegates/BaseAppDelegate`,
EmbeddedAppDelegate: `${process.cwd()}/src/default/appdelegates/embedded/EmbeddedAppDelegate`,
ActionType: `${process.cwd()}/src/application/appdelegates/actions/ActionType`,
types: `${process.cwd()}/src/application/appdelegates/actions/types`,
CommandActionType: `${process.cwd()}/src/application/appdelegates/actions/CommandActionType`,
CommandForResponseActionType: `${process.cwd()}/src/application/appdelegates/actions/CommandForResponseActionType`,
PluginRegistryService: `${process.cwd()}/src/default/PluginRegistryService`,
},
mode: 'development',
externals: [
'dcl',
'react',
'react-dom',
'prop-types',
'pubsub',
'semver',
'#appfabric/ui-profiler',
].map(
// Add this regex to each entry to ensure we don't miss any imports like 'web-shell-core/...`
(value) => new RegExp(`^(${value})((\\\\|/|!).+)?$`),
),
output: {
path: `${process.cwd()}/build/dist`,
filename: '[name].js',
library: 'web-shell-core',
libraryTarget: 'umd',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: babelRC,
},
},
],
},
};
This is the webpack.config.js
const developmentConfig = require('./webpack.dev.config.js');
module.exports = merge(developmentConfig, {
mode: 'production',
output: {
filename: '[name].min.js',
chunkFilename: '[name].min.js',
},
});
First I add a new file Secure.jsx(having the tags) in the library. I do npm install --save <path-to-library> on my application. After I do yarn install. Then I can see the new file Secure.jsx in the node modules in the application. When I try to run the application, I get the error.
Please let me know what am I missing and also which side(library / application) I have to add the code.
You can view my full config here
I think you also need to add this
resolve: {
modules: [
path.resolve('./node_modules')
]
},
Then import like this
import "jquery/dist/jquery.min.js";
import "bootstrap/dist/js/bootstrap.min.js";
I'm super new to webpack and I do not seem to find a way to bundle JS files as I did with Gulp in a very easy way. I've been searching a bit but didn't find any straight answer to it.
Right now I'm creating two minified files by using in my package.json file, but I would love to have a single one instead:
"scripts": {
"stand-alone": "concurrently 'webpack --config=webpack.config.js src/whatever.vue demos/build.min.js --output-library=whatever1' 'webpack --config=webpack.config.js src/whatever2.js demos/mixin.min.js --output-library=whatever2'",
},
Then my webpack.config.js looks like this:
const webpack = require('webpack');
module.exports = {
resolve: {
alias: {
'vue$': 'vue/dist/vue.js'
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
scss: 'vue-style-loader!css-loader!sass-loader',
js: 'babel-loader'
}
}
},
{
test: /\.js$/,
use: {
loader: 'babel-loader',
}
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: false,
}
})
],
};
I believe you are looking for entry points.
In your webpack.config.js module exports object:
Define the entry property:
entry: {
app: ['./path/to/file.js', './path/to/file2.js'],
},
Define the output property:
output: {
path: '/path/to/assets', // ex. '../../wwwroot/dist'
filename: '[name].js', // Substitutes [name] with the entry name, results in app.js
publicPath: '/'
},
Change your script to:
"scripts": {
"stand-alone": "webpack --config=webpack.config.js",
},
If you are using Vue + Webpack, I recommend that you take a look to vue-cli and generate a project using the webpack template. It is more advanced, but you can see the documentation and get an idea of what you are missing.
Run the following:
npm install -g vue-cli // install vue cli globally
vue init webpack my-project // create a sample project
If you want to generate multiple output files, you can have more than one entry point like so:
entry: {
app: ['./path/to/file.js', './path/to/file2.js'],
mixins: './path/to/mixins.js',
vendors: ['./path/to/vendor.js', './path/to/vendor2.js']
},
This will write to disk ./path/to/assets/app.js, ./path/to/assets/mixins.js, /path/to/assets/vendors.js.
I use vue.js and vue-cli to create a project.
vue init webpack my-project
I am trying to create a component using http://photo-sphere-viewer.js.org/, thus I installed it using
npm install --save photo-sphere-viewer
Then it was downloaded in node_modules and appears in the package.json under dependencies as
"photo-sphere-viewer": "^3.2.3",
And I tried to import in a component, VR-Pano.vue, inside the script tag using
import PhotoSphereViewer from 'photo-sphere-viewer';
And
var PhotoSphereViewer = require('photo-sphere-viewer');
But when I run npm run dev
This dependency was not found:
photo-sphere-viewer in ./~/babel-loader/lib!./~/vue-loader/lib/selector.js?type=script&index=0!./src/components/VR-Pano.vue
I tried:
npm cache clean && npm update -g
Did some researches on webpack, but didn't really know what's going on as I am not too familiar with webpack. I was expecting it to be a simple process, but I suspect something isn't setup properly for my webpack or I did something very stupid.
Here is my webpack.base.conf.js
var path = require('path')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
entry: {
app: './src/main.js'
},
// target: 'electron-main',
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'#': resolve('src')
}
},
module: {
rules: [
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('[path][name].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
I took this debugging opportunity to learn more about npm and webpack.
It looks like the creators of photo-sphere-viewer did not specify where their "main" file was, the file that gets returned when you import or require. I think by default npm looks for index.js at the project root. But a lot of times, package creators put their distribution files under a dist or lib directory. The photo-sphere people did this, but did not specify the location in their package.json. The solution is to add
"main":"./dist/photo-sphere-viewer.min.js"
to the photo-sphere-viewer package.json file. Make sure to add a trailing comma if you're not putting it at the very end. Also i would recommend filing an issue on their Github, this seems like a bug..
Alternatively, you can also do
import PhotoSphereViewer from 'photo-sphere-viewer/dist/photo-sphere-viewer.min.js';
What is the current behavior?
It seems that some parts of director router constructor function are removed causing an unexpected error.
NOTE: This issue was not present in Webpack version 1.14.0.
Reproduction
https://github.com/marcalexiei/director-webpack-issue
Instructions in the readme.
There are two branches:
"master" where the issue can be reproduced.
"web-pack-1-14-0" has the previous version and has no errors.
What is the expected behavior?
No errors are generated and router init is a function.
Configuration file
module.exports = {
entry: {
// app's entry point
app: './src/app.js',
},
output: {
publicPath: '/public/',
path: path.join(__dirname, 'public'),
pathinfo: true,
filename: '[name].bundle.js',
},
resolve: {
modules: [
path.join(__dirname, './') , // frontend-app
'node_modules'
],
extensions: ['.js'],
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
],
},
};
System specs
Chrome 55.0.2883.95
Safari 10.0.3
Node 6.3.1
Webpack 2.2.1
MacOS 10.12.3
TLDR: Add
resolve: {
mainFields: ['browserify', 'browser', 'module', 'main']
}
to your config.
Explanation:
In webpack1 (https://webpack.github.io/docs/configuration.html#resolve-packagemains), the default value for that field was:
["webpack", "browser", "web", "browserify", ["jam", "main"], "main"]
However, in webpack2 (https://webpack.js.org/configuration/resolve/#resolve-mainfields) the default value is:
["browser", "module", "main"]
Note that a few items are missing in webpack2 default values. In particular, browserify is not present.
This are the builds exported by director:
"browserify": "./build/director",
"main": "./lib/director",
./build/director is the browser compatible build, ./lib/director is the node one. You have to tell webpack2 to use ./build/director, hence the "browserify" entry in your config.