4

我有一个build_modules.json文件,其中包含 WebPack 应该需要的有关模块的信息,例如:

[
    'module.superman',
    'module.superwoman',
    'module.spiderman',
    'module.wolverine'
]

因此,我只需要一次将所有这些模块编译为单个包:

var _modules = require('./build_modules.json');

_modules.forEach(function(_module){
    require('./modules/' + _module);
});

一切都很好,但是如果我在./modules/文件夹中有一些其他文件而不是列出的文件build_modules.json,由于 WebPack 核心机制,所有这些文件都包含在捆绑包中,但是,它们不是必需的,并且永远不会在当前构建中使用。我需要从 bundle 中强制排除那些多余的文件,因为在实践中,我的./modules/文件夹包含 200 多个不同的模块,并且只有其中的模块才build_modules.json应该包含在当前 bundle 中。

也许我可以用一些插件来做到这一点,或者可以在webpack.config.js文件内部构建所需模块的列表并使用 node.js 要求它们,然后将所有这些东西作为预编译上下文放入 WebPack?

4

2 回答 2

1

我遇到了类似的问题。Webpack 不允许创建动态需求。在执行代码之前,它需要所有模块。但是您可以require.context根据一些regexp规则使用加载必要的模块。你可以在这里阅读更多内容:webpack 文档

您可以命名要以某种特定方式加载的模块,例如。module.*并使用require.context("./modules/", false, /^module\..+$/). module.然后在代码执行之前需要所有以开头的模块。

我记得我为此苦苦挣扎了几个小时,这对我来说是最好的解决方案。

于 2017-08-23T17:05:34.483 回答
1

如果您只需要执行您的模块

您需要entry在 webpack 配置中设置属性。此属性接受数组作为要包含在包中的文件的值。

// webpack.config.js
const 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
  },
};

如果您需要从模块中导出某些内容

不幸的是,webpack 作为数组的条目对您没有帮助,因为它只会导出数组中的最后一个文件。

我没有听说过这样的插件可以组合 certan 文件并将其用作入口点。但是您可以自己创建这样的文件。

// webpack.config.js
const fs = require('fs');
const path = require('path');

// saving tmp file location
const pathToCreatedFile = path.resolve(__dirname, './path/to/created/file');
// implement fn to get relative path to modules from tmp file
const getModulePath = module => path.relative(pathToCreatedFile, path.resolve(
  __dirname,
  './relative/path/to/modules/directory',
  module,
));

// read json
const fileContent = fs.readFileSync('./path/to/your.json');
// prepare modules for tmp file
const 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 any
const importsString = entries.map(({ name, relpath }) => `import * as ${name} from '${relpath}';`).join('\n');
// here generate exports from tmp file. It contain of all imports
const exportsString = `export {${entries.map(({name}) => name).join(',\n')}};`;
// and here just concatenate imports ad exports
const 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 fs
fs.writeFileSync(pathToCreatedFile, content);

module.exports = {
  // and here use saved tmp file path as entry point
  entry: pathToCreatedFile,
};

导入构建的捆绑包后,它将返回带有模块的普通对象。您可以使用Object.values或类似方法将您的依赖项作为数组。

还有另一种方法,您可以格式化exportString以导出导入数组。

我使用import * as name from ...格式向您展示了更常见的创建文件的方法。如果您没有任何默认导出或只有默认导出,最好分别使用export * from ...export {default as name} from ...格式化。

于 2017-11-17T09:23:43.133 回答