How can I dynamically import NPM modules without generating extra vendors~
-prefixed chunks?
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"
),
};
*/
}
This is the undesired result I'm currently getting:
dist/
lib/
moment.js
vendors~lib/
moment.js
Note that there are 2 moment.js
files!
lib/moment.js
is 16 kb and, when I examine it, contains only the ./node_modules/moment/locale
module vendors~lib/moment.js
is 938kb and, when I examine it, contains over 130 modules. So, basically, all of the moment and moment-timezone modules.The desired result:
dist/
lib/
moment.js
I would like to keep all of my NPM modules and whatever else I might want to load in a single chunk, named as I've specified, without any automatic prefixes.
I'm working on an older project that previously copy/pasted the entire minified moment and moment-timezone libraries into a JS resource named "lib/moment.js". I'd like to remove them from our codebase and generate the "lib/moment.js" file via a dynamic import. It's important to preserve the existing file name and folder structure.
The dynamic import code seemed simple enough ( webpack documentation ), but I haven't been able to find any explanation for the vendors~
prefix or how to remove it. I can see it in the examples, of course, but that prefix is, as best I can tell, never directly addressed.
If I can't get rid of the prefix and bundle everything into just the lib/moment
chunk, then I'm going to have to abandon this approach and just continue with the minified libraries stored in lib files (which is not ideal).
In short, you need to disable the defaultVendors
cache group (or vendors
prior to 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 provides a default configuration for the optimization.splitChunks
property which includes a simple "defaultVendors" rule (or "vendors" in v4 ) which splits NPM modules into a separate chunk:
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
},
According to the docs, if you do not want to use these default cache groups, then you have to explicitly set them to false
:
To disable any of the default cache groups, set them to
false
.
To disable the vendors cache group, simply set it to false
in your webpack config:
cacheGroups: {
defaultVendors: false,
},
dist/
lib/
moment.js
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.