在使用node_modules进行死代码消除工作时,Webpack树是否会抖动?

时间:2017-11-17 11:13:49

标签: webpack ecmascript-6 material-ui uglifyjs tree-shaking

考虑这个Webpack 3.8.1配置。

// 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'
});

和此Babel 6.26.0配置

{
  "presets": [
    [
      "env",
      {
        "modules": false,
        "targets": {
          "browsers": [
            ">1%"
          ]
        }
      }
    ], [
      "react"
    ]
  ],
  "plugins": [
    "transform-class-properties",
    "transform-export-extensions",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}

我期待与UglifyJS的死代码消除一起摇动的树应该以一种方式工作,使我能够从index.es.js模块编写命名导入,例如Material-UI-Icons和未使用的模块从捆绑中移除。

import {Menu} from 'material-ui-icons';

该库确实将package.json中定义的ES6模块重新导出为"module": "index.es.js"

导入单个图标后,我的捆绑包大小增加了0.5MB。当我把它改成

import Menu from 'material-ui-icons/Menu;
只有导入了这个图标,

捆绑尺寸再次缩小。

我的配置中有什么问题,或者我是否错过了解树震动的方式并且不适用于这种情况?

1 个答案:

答案 0 :(得分:1)

因此,经过一些额外的挖掘,我找到了原因/临时解决方案/解决方案。基本上,由于ES Modules可能会产生副作用,WebpackUglifyJS可以安全地(按规范)删除通常在index.es.js或类似"module"中找到的未使用的转口入口点。

目前,有一些方法可以解决这个问题。您可以手动只导入必要的模块,也可以使用babel-plugin-direct-import

好消息是Webpack 4通过side-effects标志添加了support for pure modules。当图书馆作者将其标记为纯粹时,树木抖动和缩小将按预期工作。我还建议阅读this nice summary关于NodeJS中的ESM规范支持。

现在我建议您使用this wonderfull visualizer手动处理您的软件包,并决定如何自己处理每个大型依赖项。