Webpack 4无法通过TreeShaking优化Lodash?

9

我希望能够从由webpack生成的捆绑包中,摇掉未使用的lodash库和multiply函数。

我有两个主要文件app.jsmath.js

它包含以下代码-

app.js

import map from "lodash/map";

import { sum } from "./math";

console.log("");

console.log(`2 + 3 = ${sum(2, 3)}`);

map([1, 2, 3], x => {
    console.log(x);
});

math.js

export const sum = (a, b) => a + b;
export const multiply = (m, n) => m * n;

webpack.config.js

const path = require("path");
const webpack = require("webpack");
const UglifyJSPlugin = require("uglifyjs-webpack-plugin");
const Jarvis = require("webpack-jarvis");

let plugins = [new Jarvis()];

if (process.env.NODE_ENV === "production") plugins.push(new UglifyJSPlugin());

const config = {
    entry: "./app.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: "babel-loader"
            }
        ]
    },
    plugins
};

module.exports = config;

我的npm脚本看起来像这样 -
"scripts": {
    "dev": "webpack --optimize-minimize --mode development",
    "dev:watch": "webpack --watch --optimize-minimize --mode development",
    "prod": "webpack -p --optimize-minimize --mode production",
    "prod:watch": "webpack -p --watch --optimize-minimize --mode production",
    "start": "npm run prod",
    "clean": "rm -rf dist"
  }

完整代码可在https://github.com/deadcoder0904/webpack-treeshake中找到。
我尝试使用UglifyJSPlugin,但在生成的捆绑包中仍然显示了我的未使用的math.js中的multiply函数。此外,通过npm run prod生成的production捆绑包仍然很大,大小为20kB,其中包含了很多不必要的lodash内容。
2个回答

11

我找到了答案

为了在使用树摇晃(tree shaking)时使用lodash,我们首先应该安装lodash-es并且移除lodash的依赖。

同时,lodash-es不应该被首先转码(transpiled),所以我们将我们的.babelrc文件设置如下 -

{
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ]
  ]
}
注意,将modules设置为false会使其不进行转译。
现在打包后的文件大小为16.2kB5.79kB gzip 由于运行lodash本身需要一些代码,因此仍然会使用来自lodash模块的部分代码;除此之外,./math.js中的multiply函数不会被添加到结果包中。
我还需要lodash-webpack-plugin来使它正常工作。
Tree shaking有效。
我创建了一些基本的存储库来解决所述问题 - https://github.com/deadcoder0904/webpack-exam https://github.com/deadcoder0904/webpack-treeshake

当我尝试使用服务器端渲染启动Express时,出现了“意外的令牌导入”错误。 - Tomasz Mularczyk
@Tomasz,这是因为你需要使用类似于babel的工具将其转换为require,否则请使用require - deadcoder0904
我发现了一篇有趣的文章,介绍如何通过babel或typescript进行配置:https://medium.com/@martin_hotell/tree-shake-lodash-with-webpack-jest-and-typescript-2734fa13b5cd - Braulio
1
@Braulio,那篇文章的内容现在已经不再相关了(请参见2017年8月的更新),那篇文章是在lodash纯模块和webpack 4之前发布的。 - Salami

0

在@deadcoder0904的答案基础上,以下是如何在webpack 4中使用babel-loader(而不是使用.babelrc):

...
        {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
                options: {
                    plugins: ['lodash'],
                    presets: [['env', { modules: false }]]
                }
            }
        },

注意:我无法在不显式从 'lodash-es' 导入的情况下使其工作(即使我在我的 tsconfig 中将 lodash-es 指向 lodash)(我正在使用 TypeScript)。如果有人能够在不使用特殊的 import { map } from 'lodash-es'; 而是使用 import { map } from 'lodash'; 就能使其正常工作,那就太好了!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接