简体   繁体   English

webpack 动态模块加载器按要求

[英]webpack dynamic module loader by require

OK, i have searched high and low but cannot reliably deterrmine if this is or is not possible with webpack.好的,我已经搜索了高低,但无法可靠地确定 webpack 是否可行。

https://github.com/webpack/webpack/tree/master/examples/require.context Appears to indicate that one can pass a string to a function and it load a module... https://github.com/webpack/webpack/tree/master/examples/require.context似乎表明可以将字符串传递给函数并加载模块...

But my attempt is just not working: webpack.config.js但我的尝试不起作用:webpack.config.js

'use strict';
let webpack     = require('webpack'),
    jsonLoader  = require("json-loader"),
    path        = require("path"),
    fs          = require('fs'),
    nodeModules = {};

fs.readdirSync('node_modules')
    .filter(function(x) {
        return ['.bin'].indexOf(x) === -1;
    })
    .forEach(function(mod) {
        nodeModules[mod] = 'commonjs ' + mod;
    });


let PATHS = {
    app: __dirname + '/src'
};

module.exports = {
    context: PATHS.app,
    entry: {
        app: PATHS.app+'/server.js'
    },
    target: 'node',
    output: {
        path: PATHS.app,
        filename: '../build/server.js'
    },
    externals: nodeModules,
    performance: {
        hints: "warning"
    },
    plugins: [
        jsonLoader
    ],
    resolve: {
        modules: [
            './node_modules',
            path.resolve(__dirname),
            path.resolve(__dirname + "/src"),
            path.resolve('./config')
        ]
    },
    node: {
        fs: "empty"
    }
};

The server.js服务器.js

let _ = require('lodash');
let modules = [ "modules/test" ];

require( 'modules/test' )();

_.map( modules, function( module ){
    require( module );
});

The module in modules/ named test.js modules/ 中的模块名为 test.js

module.exports = () => {
    console.log('hello world');
};

But the result is always the same... the pm2 logs just say hello world for the static require... but for the dynamic load of the same module但结果总是一样的...... pm2 日志只是说 hello world 静态需求......但对于同一模块的动态加载

Error: Cannot find module "."错误:找不到模块“。”

All i want to be able to do is loop through an array of paths to modules and load then...我想要做的就是循环遍历模块的路径数组,然后加载...

You cannot use a variable as argument to require .您不能使用变量作为require参数。 Webpack needs to know what files to bundle at compile time. Webpack 需要知道在编译时捆绑哪些文件。 As it does no program flow analysis, it can't know what you pass to the function.由于它不进行程序流分析,因此无法知道您传递给函数的内容。 In that case it might be obvious, but this could go as far as using user input to decide what module to require, and there is no way webpack can possibly know which modules to include at compile time, so webpack does not allow it.在那种情况下它可能很明显,但是这可能会使用用户输入来决定需要哪个模块,并且 webpack 不可能知道在编译时包含哪些模块,因此 webpack 不允许这样做。

The example you posted is a bit different.您发布的示例有点不同。 You could use require with a concatenated string.您可以将require与连接字符串一起使用。 For example:例如:

require(`./src/${moduleName}/test`);

Which modules does webpack need to include in the bundle? webpack 需要在 bundle 中包含哪些模块? The variable moduleName could be anything, so the exact module is not known at compile time.变量moduleName可以是任何东西,因此在编译时不知道确切的模块。 Instead it includes all modules that could possibly match the above expression.相反,它包括可能与上述表达式匹配的所有模块。 Assuming the following directory structure:假设目录结构如下:

src
├─ one
│   └─ test.js
├─ two
│   ├─ subdir
│   │   └─ test.js
│   └─ test.js
└─ three
    └─ test.js

All of these test.js files will be included in the bundle, because moduleName could be one or something nested like two/subdir .所有这些test.js文件都将包含在包中,因为moduleName可以是one或嵌套的东西,例如two/subdir

For more details see require with expression of the official docs.更多详细信息请参见官方文档中的require 和表达式

You cannot loop through an array and import every module of the array, with the above exception by concatenating a string, but that has the effect of including all possible modules and should generally be avoided.您不能循环遍历数组并导入数组的每个模块,上述例外情况是通过连接字符串,但这会导致包含所有可能的模块,通常应该避免。

I ran into this problem in an electron environment.我在电子环境中遇到了这个问题。 My use case was being able to require dynamically created files in an IDE like application.我的用例能够在像应用程序这样的 IDE 中require动态创建的文件。 I wanted to use the electron require , which is basically a NodeJS Common module loader.我想使用电子require ,它基本上是一个 NodeJS 通用模块加载器。 After some back and forth I landed on a solution that uses webpack's noParse module configuration.经过一番反复之后,我找到了一个使用 webpack 的noParse模块配置的解决方案。

First create a module that that will be ignored by webpack's parser:首先创建一个将被 webpack 解析器忽略的模块:

// file: native-require.js
// webpack replaces calls to `require()` from within a bundle. This module
// is not parsed by webpack and exports the real `require`
// NOTE: since the module is unparsed, do not use es6 exports
module.exports = require

In my webpack config, under module , instruct the bundler not to parse this module:在我的 webpack 配置中,在module下,指示 bundler 不要解析这个模块:

{
  module: {
    noParse: /\/native-require.js$/,
  }
}

Lastly, in any bundle where you want to access the original require:最后,在您想要访问原始需求的任何包中:

import nativeRequire from './native-require'
const someModule = nativeRequire('/some/module.js') // dynamic imports

A bit late....but... since you are bundling to target: 'node' , there is a workaround to dynamic requiring modules, and bypassing the "the effect of including all possible modules" .有点晚了......但是......因为你捆绑到target: 'node' ,有一个动态需要模块的解决方法,并绕过“包括所有可能模块的影响”

The solution is lifted from:解决方案来自:

Using dynamic require on node targets WITHOUT resolve or bundle the target module · Issue #4175 · webpack/webpack 在不解析或捆绑目标模块的情况下对节点目标使用动态 require · 问题 #4175 · webpack/webpack

Quoted from that comment:引自那条评论:

const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
const foo = requireFunc(moduleName);

Bundles to:捆绑到:

const requireFunc = true ? require : require;
const foo = requireFunc(moduleName);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM