【问题标题】:Does Webpack tree shaking with dead code elimination work on node_modules?带有死代码消除的 Webpack 树抖动是否适用于 node_modules?
【发布时间】:2018-05-01 03:44:36
【问题描述】:

考虑到这个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"
  ]
}

我期望 tree-shaking 和 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;

仅导入此图标后,束大小再次减小。

我的配置有什么问题,还是我误解了 tree shaking 的工作原理并且不适用于这种情况?

【问题讨论】:

  • 对于它的价值,您正在使用的包的文档明确指出摇树应该使用它:github.com/callemall/material-ui/tree/v1-beta/packages/…
  • 您是在生产模式还是开发模式下测量捆绑包大小?
  • 经过仔细检查后,我开始相信它不适用于我的整个项目。捆绑包大小在生产模式下使用发布的配置进行测量。当我禁用缩小时,捆绑包中有“未使用的和谐......”cmets,所以我假设这个过程的至少一部分有效。
  • 我不确定 Webpack 3 如何支持module。见2ality.com/2017/06/pkg-esnext.html模块仅限于 Node.js 当前支持的内容。尝试导入material-ui-icons/index.es 看看会发生什么。
  • import {Menu} from 'material-ui-icons/index.es'; 将包大小增加到 + 0.5 MB。

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


【解决方案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 手动处理您的捆绑包,并决定如何自行处理每个大型依赖项。

【讨论】:

    猜你喜欢
    • 2021-04-20
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 2017-07-01
    • 1970-01-01
    • 2019-02-17
    相关资源
    最近更新 更多