WebPack require context from list in external json file
I had got similar problem. Webpack does not allow to create dynamic requires. It takes all modules before the code is executed.But you can use require.context
to load necessary modules according to some regexp
rules. You can read more here: webpack docs
You can name modules, that you want to load in some specific way, eg. module.*
and use require.context("./modules/", false, /^module\..+$/)
.Then all modules that begin with module.
will be required before the code execution.
I remember that I was struggling with that for a couple of hours and that was the best solution for me.
In case you need just to execute your modules
You need to set entry
property in webpack config. This property accepts array as value of files to include in bundle.
// webpack.config.jsconst fs = require('fs');const path = require('path');const getModulePath = module => path.resolve(__dirname, './relative/path/to/modules/directory', module);const fileContent = fs.readFileSync('./your.json');const entries = JSON.parse(fileContent).map(getModulePath);module.exports = { // all entries will be built during one build process // if you need you can split each entry to separate config file entry: { bundle1: entries, // build modules from JSON file to single bundle bundle2: [ './file1', './file2' ], // build static modules to single bundle bundle3: './sindle/file', // "classic" build all: [ ...entries, './file1', './file2', './sindle/file' ], // you can combine everything to 1 bundle },};
In case you need to export something from your modules
Unfortunately webpack's entry as array won't help you because it will export only last file in array.
I didn't heard something about such plugins that can combine certan files and use it as entry point. But you can create such file by yourself.
// webpack.config.jsconst fs = require('fs');const path = require('path');// saving tmp file locationconst pathToCreatedFile = path.resolve(__dirname, './path/to/created/file');// implement fn to get relative path to modules from tmp fileconst getModulePath = module => path.relative(pathToCreatedFile, path.resolve( __dirname, './relative/path/to/modules/directory', module,));// read jsonconst fileContent = fs.readFileSync('./path/to/your.json');// prepare modules for tmp fileconst entries = JSON.parse(fileContent) .map(item => ({ name: item.slice(7), relpath: getModulePath(item), }));// here generate import directive for each module. I used `import * as modules_name from 'path';` format// you can choose anyconst importsString = entries.map(({ name, relpath }) => `import * as ${name} from '${relpath}';`).join('\n');// here generate exports from tmp file. It contain of all importsconst exportsString = `export {${entries.map(({name}) => name).join(',\n')}};`;// and here just concatenate imports ad exportsconst content = [ entries.map(({ name, relpath }) => `import * as ${name} from '${relpath}';`).join('\n'), `export {${entries.map(({name}) => name).join(',\n')}};`,].join('\n');// and save tmp file content to fsfs.writeFileSync(pathToCreatedFile, content);module.exports = { // and here use saved tmp file path as entry point entry: pathToCreatedFile,};
After you import builded bundle it will return plain object with your modules. You can use Object.values
or similar to get your dependencies as array.
And another aproach, you can format exportString
to export array of imports.
I used import * as name from ...
format to show you more common way to create file. If you don't have any default exports or you have only default export it's better to use export * from ...
or export {default as name} from ...
formats respectively.