I did a slider on mobx and bundle it using webpack 3. I excluded mobx from slider's bundle using "externals". Then I published it as package, created a mobx-sandbox and installed the slider there.
In result I'm getting an error because package can't import mobx.
But I expecting that slider will find mobx because I imported it on sandbox page.
I also receiving in console:
[mobx] Warning: there are multiple mobx instances active.
This might lead to unexpected results.
What am I missing?
slider's webpack.config:
var path = require('path');
var webpack = require('webpack');
module.exports = {
node: {
fs: "empty" // https://github.com/josephsavona/valuable/issues/9
},
devtool: 'source-map',
entry: {
bundle: [ "./src/index.js" ]
},
output: {
path: path.join(__dirname, "lib"),
filename: "index.js"
},
externals: {
'react': {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom'
},
'mobx': {
root: 'mobx',
commonjs2: 'mobx',
commonjs: 'mobx',
amd: 'mobx'
},
'mobx-react': {
root: 'mobx-react',
commonjs2: 'mobx-react',
commonjs: 'mobx-react',
amd: 'mobx-react'
}
},
stats: {
colors: true,
reasons: true
},
resolve: {
extensions: ['.js']
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /\/node_modules\//,
loader: 'babel-loader',
query: {
cacheDirectory: true
}
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
};
slider's .babelrc
{
"presets": ["es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy"]
}
slider repository:
https://github.com/andiwilflly/rslider
sandbox repository:
https://github.com/SkunSHD/rslider-test-sandbox
The problem was with absence of umd's imports in bundle.
This line in output helped to import modules in bundle properly:
webpack.config:
module.exports = {
... ,
output: {
... ,
libraryTarget: 'umd'
}
}
Related
I've making a library and tried to use built package on example code by doing this
import { createMiddleware, useActionListener } from "../../../../lib";
It occurs an error Invalid hook call. at
useActionListener("SUB", (action) => {
//...
});
So I tried to publish a package and changed like this
import { createMiddleware, useActionListener } from "myLibraryName";
And it works like charm.
I have no idea why calling built package direct occurs an error. Any ideas?
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'lib'),
filename: 'index.js',
libraryTarget: 'umd',
library: 'reactActionListener',
globalObject: 'this',
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
redux: {
root: 'Redux',
commonjs2: 'redux',
commonjs: 'redux',
amd: 'redux',
},
},
resolve: {
extensions: ['.ts', '.js', '.json', '.tsx', '.jsx'],
alias: {
// Needed when library is linked via `npm link` to app
react: path.resolve('./node_modules/react'),
},
},
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
module: {
rules: [
{
test: /\.(js|ts|tsx|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
};
I'm trying to create a library of reusable react components for our internal use.
Webpack is bundling the output - which should be a single file. But it's actually putting out the bundle.js that I'd expect plus a file called [some_hash].worker.js.
I'm not sure how to force webpack to include that "worker" file with the single bundle that I'm asking it for.
The webpack.config:
const path = require('path');
const webpack = require('webpack');
const DIST_PATH = path.resolve(__dirname, "../dist");
const SRC_PATH = path.resolve(__dirname, "../src");
const APP_PATH = path.resolve(__dirname, "../src/index.js");
const BASE_PATH = path.resolve(__dirname);
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = ({ appPath = APP_PATH, distPath = DIST_PATH }) => ({
context: BASE_PATH,
devServer: {
contentBase: distPath,
compress: true,
port: 9000,
historyApiFallback: true
},
resolve: {
modules: ['node_modules', SRC_PATH],
alias: {
'react': path.resolve(__dirname, '../node_modules/react'),
'react-dom': path.resolve(__dirname, '../node_modules/react-dom'),
}
},
externals: {
// Don't bundle react or react-dom
react: {
commonjs: "react",
commonjs2: "react",
amd: "React",
root: "React"
},
"react-dom": {
commonjs: "react-dom",
commonjs2: "react-dom",
amd: "ReactDOM",
root: "ReactDOM"
}
},
entry: {
bundle: appPath,
},
output: {
path: distPath,
filename: 'index.js',
publicPath: '/dist/',
library: 'internal-components',
libraryTarget: 'umd',
umdNamedDefine: true
},
module: {
rules: [
{
test: /\.jsx$/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
'#babel/plugin-proposal-object-rest-spread',
'#babel/plugin-syntax-dynamic-import',
[ '#babel/plugin-proposal-decorators', { 'legacy': true } ],
[ '#babel/plugin-proposal-class-properties', { 'loose': true } ]
]
}
}
},
{
test: /\.js$/,
exclude: /(node_modules|build)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env'],
plugins: [
'#babel/plugin-proposal-object-rest-spread',
'#babel/plugin-syntax-dynamic-import',
['#babel/plugin-proposal-decorators', {'legacy': true}],
["#babel/plugin-proposal-class-properties", {'loose': true}]
]
}
}
},
...
]
},
plugins: [
new CleanWebpackPlugin(),
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
})
]
});
You might try using the worker-loader plugin with inline to handle the bundling -
rules: [
...
{
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
options: { inline: true, fallback: false }
}
}
]
That said, there are several open issues on Github surrounding using the worker as a blob, so YMMV
Actually if you are using webpack 3 and above, chunking of the bundle is automatically done for you. In the SplitChunks Plugin documentation here it is actually stated how this behaves.
So because of this you might need to scan your code and check for this conditions. Also it's good to know if you are asynchrously importing the some module? That might signal webpack to make it into a separate chunk.
I'm trying to publish a custom react component to a private repository.
I use react-loadable to load a subcomponent on demand. When running locally, everything works fine. The index.js file correctly makes a request to the chunk.js file when needed. However, when published and used from another project, the component hits a 404 error when trying to request the subcomponent chunk.
How am i supposed to split chunks and load them on demand when authoring a library? Is this even possible or am i thinking about it the wrong way?
Here's my webpack.config.js in case it's a simple matter of configuration:
module.exports = () => ({
context: __dirname,
mode: 'development',
entry: './src/index.jsx',
output: {
path: path.join(__dirname, './dist'),
filename: "index.js",
library: "reactcombobox",
libraryTarget: "umd",
publicPath: path.join(__dirname, './dist'),
umdNamedDefine: true
},
plugins: [
new webpack.LoaderOptionsPlugin({ options: { context: __dirname}}),
new CleanWebpackPlugin([path.join(__dirname, './dist')], {verbose: true, allowExternal: true})
],
module: {
rules: [
{
test: /.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['#babel/preset-env', {
"targets": {
"browsers": ["last 4 Chrome versions"]
}
}],
'#babel/preset-react'
],
plugins: [
'#babel/plugin-transform-react-jsx',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-syntax-dynamic-import'
]
}
}
},
{
test: /.css$/,
use: ["style-loader","css-loader"]
}
]
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom',
}
},
resolve: {
extensions: ['*', '.js', '.jsx']
}
});
if your component no relative please split to more file and use export {a1,a2};
do not use loadable.
i'm using in my react project a library that needs to be compiled using webpack ( the library called storm-react-diagrams)
the problem is , whenever i do some changes in the library , i need to compile it using webpack , then restart the react app using npm start in order for the changes to take effect (the generated bundle.js doesn't get updated untill i use npm start ) .
How can i optomize this and just refresh the page automaticly whenever i edit the app or the library
for info :
I'm using VS code
when changing and saving a file on my react app , the page on the browser reloads and changes take effect with no problem .
unfortuanatly , this doesn't happen when i change a file in node_modules folder
webpack config file
const webpack = require("webpack");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
var path = require("path");
var plugins = [];
const production = process.env.NODE_ENV === "production";
//do we minify it all
if (production) {
console.log("creating production build");
plugins.push(
new webpack.DefinePlugin({
"process.env.NODE_ENV": '"development"'
})
);
}
/**
* #author Dylan Vorster
*/
module.exports =
//for building the umd distribution
{
entry: "./src/main.ts",
output: {
filename: "main.js",
path: __dirname + "/dist",
libraryTarget: "umd",
library: "storm-react-diagrams"
},
externals: {
react: {
root: "React",
commonjs2: "react",
commonjs: "react",
amd: "react"
},
"react-dom": {
root: "ReactDOM",
commonjs2: "react-dom",
commonjs: "react-dom",
amd: "react-dom"
},
lodash: {
commonjs: "lodash",
commonjs2: "lodash",
amd: "_",
root: "_"
}
},
plugins: plugins,
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader"
},
{
test: /\.tsx?$/,
loader: "ts-loader"
}
]
},
resolve: {
extensions: [".tsx", ".ts", ".js"]
},
devtool: production ? "source-map" : "cheap-module-source-map",
};
I've loosely followed this link to create my react components for distribution. My webpack production build is below.
However my build comes out much larger than I would expect it to considering that the individual file sizes combined are somewhere around 1/10th the size. Specifically my file sizes for the source js and less files, combined is only 1.6kb. However the build is ~10x more at 13kb.
My components are extremely simple and similar. I have a FlexTable, a FlexTableRow and a FlexTableCell file. All of them have the same signature as below but with a different style.less. In my style.less it is basically a few lines of css that say display: flex; flex: 0 etc etc. So to summarize, very minimal js and very minimal amounts of css.
So the question is, why does the production build balloon to 13kb from 1.6kb? What am I doing wrong?
my-flex-table.js
var React = require('react');
const styles = require('./my-flex-table.less')
const FlexTable = (props) => (
<section {...props} className={styles['my-flex-table'] + " " + props.customStyles}>{props.children}</section>
)
module.exports = FlexTable;
(Replace FlexTable with FlexTableRow or FlexTableCell in the above and you have my other files)
My package.json points to an index file that simply exports all 3 of these with module.exports = {FlexTable, FlexTableCell, FlexTableRow}
The webpack production script is run with:
NODE_ENV=production node_modules/webpack/bin/webpack.js --config webpack.config.prod.js
Webpack production script
var autoprefixer = require('autoprefixer');
var postcssImport = require('postcss-import');
var webpack = require('webpack');
module.exports = {
entry: './src/index.jsx',
output: {
filename: './dist/my-flex-table.js',
library: 'MyFlexTable',
libraryTarget: 'umd',
},
resolve: {
extensions: ['', '.js', '.jsx', '.less']
},
module: {
loaders: [
{ test: /.jsx?$/,
loader: 'babel',
exclude: /node_modules/,
query: {
cacheDirectory: true,
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0','react']
},
"env": {
"production": {
"presets": ["react-optimize"]
}
}
},
{ test: /.less$/, loader: 'style-loader!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader!less-loader' },
{ test: /\.(png|woff|woff2|eot|ttf|svg|jpg)$/, loader: 'url-loader?limit=100000' }
]
},
postcss: function (wp) {
return [postcssImport({
addDependencyTo: wp
}),autoprefixer];
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: {
unused: true,
dead_code: true,
drop_console: true,
warnings: false
}
})
],
externals: [
{
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react',
},
},
{
'react-dom': {
root: 'ReactDOM',
commonjs2: 'react-dom',
commonjs: 'react-dom',
amd: 'react-dom',
},
},
]
};
The webpack visualizer is a good tool to troubleshoot bundle sizes. Follow the instructions there and it might help you see what extra is getting bundled in that you might not be intending.