Reputation: 8397
Considering this Webpack 3.8.1
config.
// common
module.exports = {
context: path.resolve(__dirname, './src'),
entry: [
'whatwg-fetch',
'./index'
],
output: {
path: path.resolve(__dirname, 'build/assets'),
publicPath: '/assets/',
filename: 'main.js'
},
plugins: [
new CleanWebpackPlugin(['build']),
],
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
}, {
test: /\.(scss|css)$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'sass-loader'
}],
}, {
test: /\.(png|jpg|gif|woff2|woff)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}]
}
};
//prod
module.exports = merge(common, {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new UglifyJSPlugin()
],
devtool: 'none'
});
and this Babel 6.26.0
config
{
"presets": [
[
"env",
{
"modules": false,
"targets": {
"browsers": [
">1%"
]
}
}
], [
"react"
]
],
"plugins": [
"transform-class-properties",
"transform-export-extensions",
"transform-object-rest-spread",
"react-hot-loader/babel"
]
}
I was expecting that tree shaking alongside with dead code elimination of UglifyJS
should work in a way that enables me to write named imports from index.es.js
modules, for example Material-UI-Icons
and unused ones get removed from the bundle.
import {Menu} from 'material-ui-icons';
This library does indeed reexport ES6 modules defined in package.json as "module": "index.es.js"
.
Yet my bundle size increased by 0.5MB after importing single icon. When I changed it to
import Menu from 'material-ui-icons/Menu;
bundle size got reduced again with only this icon imported.
Is there something wrong in my configuration, or do I missunderstand how tree shaking works and does not apply to this scenario?
Upvotes: 6
Views: 4576
Reputation: 8397
So after some additional digging, I found the cause / temporary solution / solution. Basically, because ES Modules
can have side-effects, Webpack
nor UglifyJS
can safely (per specification) remove unused re-exports typically found in index.es.js
or similar "module"
entry point.
For now, there are some ways around it. Either you can manually import only necessary modules, or you can use babel-plugin-direct-import.
Good news is that Webpack 4
adds support for pure modules thru the side-effects
flag. When library author marks it as pure, tree shaking and minification will work as expected. I also recommend to read this nice summary about ESM specification support in NodeJS.
For now I would recommend to manually work thru your bundle using this wonderfull visualizer and decide how to handle each large dependency on its own.
Upvotes: 5