为什么 webpack 4 包含单个命名导入的整个文件?

why does webpack 4 include the whole file for single named import?

给定以下两个文件:

//a.js
export const X = /*#__PURE__*/ "X";

const a = function () {
  return "About a!";
};
a.foo = function () {
  return "foo";
};
export default a;

//main.js
import { X } from "./a";
import { Y } from "./b";

console.log(X, Y);

我已经添加了

但 运行 webpack -p 仍将整个 a.js 文件包含在捆绑包中。汇总仅包括来自 a.js (demo)

X

删除 a.foo 定义 "fixes" 问题,但不是演示存储库之外的解决方案。 我已经多次阅读 tree-shaking 文档页面,阅读了 [关于 webpack 问题跟踪器上关于 tree shaking 的无数问题,我仍然无法弄清楚以下内容:

您还可以查看 sandbox repository 以查看完整的 webpack 配置和相应的 next.js/react 问题(请参阅 pages/index.jsx),这导致我遇到了这个特定问题。

我的猜测:export default 会影响 tree shaking。 参见:https://medium.com/@bluepnume/javascript-tree-shaking-like-a-pro-7bf96e139eb7#43e1

尽量不要删除 default

提出后issue on webpack's issue tracker ~sokra提供了答案:

Seems like a single compression pass in terser is not enough to compress this code.

默认遍数为 1,但一旦提高到 3,a.js 不再完全内联。这就是如何以更长的构建时间为代价来实现的。

const TerserWebpackPlugin = require("terser-webpack-plugin");

/** @type {import("webpack").Configuration} */
module.exports = {
    optimization: {
        minimizer: [
            new TerserWebpackPlugin({
                terserOptions: {
                    compress: {
                        passes: 3
                    }
                }
            })
        ]
    }
}