Reputation: 413
Normally, with static requires or imports (CommonJS/ES imports), webpack can require any module from /node_modules/, for example:
var vendorModule = require('vendor-module');
But I want to dynamically load a module from /node_modules/ like:
var vendorModuleId = 'vendor-module';
...
var vendorModule = require(vendorModuleId);
This doesn't work because webpack can't determine the dependency at compile time and it's obviously insane to include all of /node_modules/ in the bundle just in case we might want to dynamically load some vendor module.
I'm looking for a way to trick webpack into resolving these modules dynamically. Preferably by telling webpack which modules in /node_modules/ should be included in the bundle via the webpack config file.
Some people say the ContextReplacementPlugin can be useful for these situations, but I can't understand how.
Anybody have any idea how to accomplish this? Thanks in advance!
Upvotes: 8
Views: 4220
Reputation: 14943
Webpack now supports dynamic loading, example:
// js
const _ = await import(/* webpackChunkName: "lodash" */ 'lodash')
// webpack.config.js
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
That snippet is assuming you also have the Syntax Dynamic Import Babel Plugin.
Upvotes: 1
Reputation: 24985
You can reference a module path dynamically using dynamic loading:
// module.js
export default {
init: () => console.log('module.init'),
};
// index.js
const id = 'module';
import(`./${id}.js`).then(obj => obj.default.init());
Upvotes: 0
Reputation: 2570
You can make a file for import and export needed modules via loaders.
npm install exports-loader imports-loader --save-dev
In webpack.config.js
:
// config needed vendor modules
var vendorModules = [
'one', 'two', 'three', 'vendor-module'
];
...
module.exports = {
...
loaders: [{ // Add loader
include: require.resolve('./vendors.js'),
loader: 'imports-loader?' + vendorsModules.map(function(module, index) {
return 'dep' + index + '=' + module;
}).join(',') + '!exports-loader?' + vendorsModules.map(function(module, index) {
return module + '=dep' + index;
}).join(',')
},...]
...
}
In module where you need to require vendor:
// import * as vendorsModules from './vendors';
var vendorsModules = require('./vendors');
var vendorModuleId = 'vendor-module';
...
var vendorModule = vendorsModules[vendorModuleId];
console.log('module', vendorModule);
It will adds configured vendors to your bundle. If you need to lazy load these modules, you need to do more complex modules factory using require.resolve
and promise-like interface for getting needed module.
Upvotes: 3