如何在没有供应商拆分的情况下加载动态块

How to load dynamic chunk without vendors splitting

快速总结

如何在不生成额外的 vendors~ 前缀块的情况下动态导入 NPM 模块?

详情

设置

webpack.config.js

const path = require("path");

module.exports = [{
    mode: "development",
    entry: path.resolve(__dirname, "js/index.js"),
}];

index.js

__webpack_public_path__ = "dist/";

loadMoment();

function loadMoment() {
    return require.ensure(
        "moment-timezone",
        require => {
            console.log("moment loaded");
            window.MY_GLOBAL = {
                moment: require("moment-timezone"),
            };
        },
        () => {},
        "lib/moment",
    );

    /*
    // Working on an existing project with an older version of ESLint, so the preferred import()
    // trips up the linter. Using the older require.ensure to avoid linter errors, but I tested
    // with async/await and import() and I get the same result.
    window.MY_GLOBAL = {
        moment: await import(
            /* webpackChunkName: "lib/moment" * /
            "moment-timezone"
        ),
    };
    */
}

结果

这是我目前得到的不想要的结果:

dist/
  lib/
    moment.js
  vendors~lib/
    moment.js

请注意,有 2 个 moment.js 个文件!

想要的结果:

dist/
  lib/
    moment.js

我想将我所有的 NPM 模块以及我可能想要加载的任何其他内容保存在一个块中,按照我指定的方式命名,没有任何自动前缀。

更多背景

我正在处理一个旧项目,该项目之前 copy/pasted 将整个缩小的时刻和时刻时区库放入名为“lib/moment.js”的 JS 资源中。我想从我们的代码库中删除它们并通过动态导入生成“lib/moment.js”文件。保留现有的文件名和文件夹结构很重要。

动态导入代码看起来很简单 (webpack documentation),但我没能找到任何关于 vendors~ 前缀或如何删除它的解释。当然,我可以在示例中看到它,但据我所知,该前缀从未直接提到过。

如果我不能摆脱前缀并将所有内容捆绑到 lib/moment 块中,那么我将不得不放弃这种方法并继续使用存储在 lib 文件中的缩小库(这并不理想)。

TL;DR

简而言之,你需要禁用 defaultVendors 缓存组(或 vendors 之前的 webpack 5):

webpack.config.js

const path = require("path");

module.exports = [{
    mode: "development",
    entry: path.resolve(__dirname, "js/index.js"),

    // ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
    optimization: {
      splitChunks: {
        cacheGroups: {
            defaultVendors: false,
            // prior to webpack 5:
            //vendors: false,
        },
      },
    },
    // ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲
}];

现在怎么办?

Webpack 提供了一个 default configuration for the optimization.splitChunks property which includes a simple "defaultVendors" rule (or "vendors" in v4) 将 NPM 模块拆分成一个单独的块:

cacheGroups: {
    defaultVendors: {
        test: /[\/]node_modules[\/]/,
        priority: -10,
        reuseExistingChunk: true,
    },
},

根据文档,如果您不想使用这些默认缓存组,则 you have to explicitly set them to false:

To disable any of the default cache groups, set them to false.

要禁用供应商缓存组,只需在您的 webpack 配置中将其设置为 false

cacheGroups: {
    defaultVendors: false,
},

结果

dist/
  lib/
    moment.js