webpack 动态模块加载器

Posted

技术标签:

【中文标题】webpack 动态模块加载器【英文标题】:webpack dynamic module loader by require 【发布时间】:2017-08-05 10:58:24 【问题描述】:

好的,我已经搜索了高低,但无法可靠地确定 webpack 是否可以。

https://github.com/webpack/webpack/tree/master/examples/require.context 似乎表明可以将字符串传递给函数并加载模块...

但我的尝试是行不通的: 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"
    
;

server.js

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

require( 'modules/test' )();

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

modules/中的模块名为test.js

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

但结果总是一样的...... pm2 日志只是为静态需求打招呼......但对于同一模块的动态加载

错误:找不到模块“。”

我想要做的就是循环遍历模块的路径数组,然后加载......

【问题讨论】:

【参考方案1】:

我在电子环境中遇到了这个问题。我的用例是能够require 在类似 IDE 的应用程序中动态创建文件。我想使用电子require,它基本上是一个 NodeJS 通用模块加载器。经过一番反复,我找到了一个使用 webpack 的 noParse 模块配置的解决方案。

首先创建一个将被 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

在我的 webpack 配置中,module 下,指示捆绑程序不要解析此模块:


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

最后,在您想要访问原始要求的任何捆绑包中:

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

【讨论】:

这个解决方案对我来说效果很好,有几个调整: 1. 要访问,我必须使用:import nativeRequire = require('./native-require')。它抱怨该模块没有默认导出。 2. 要导出全局 require,在 native-require.js 中我必须使用:module.exports = require。这是因为 global.require 对我来说是未定义的(节点 10.13,webpack 4.29)【参考方案2】:

有点晚了....但是...由于您要捆绑到target: 'node',因此有一种解决方法可以解决动态需求模块,并绕过“包含所有可能模块的效果”.

解法出自:

Using dynamic require on node targets WITHOUT resolve or bundle the target module · Issue #4175 · webpack/webpack

引自该评论:

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

捆绑到:

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

【讨论】:

【参考方案3】:

您不能将变量用作require 的参数。 Webpack 需要在编译时知道要捆绑哪些文件。由于它不进行程序流分析,因此它无法知道您传递给函数的内容。在这种情况下,这可能很明显,但这可能会使用用户输入来决定需要哪个模块,并且 webpack 不可能知道在编译时要包含哪些模块,因此 webpack 不允许这样做。

您发布的示例有点不同。您可以将require 与串联字符串一起使用。例如:

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

webpack 需要在包中包含哪些模块?变量moduleName 可以是任何东西,因此在编译时不知道确切的模块。相反,它包含可能匹配上述表达式的 all 模块。假设目录结构如下:

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

所有这些test.js 文件都将包含在捆绑包中,因为moduleName 可能是one 或类似two/subdir 的嵌套内容。

更多详情请参阅官方文档的require with expression。

你不能循环遍历一个数组并导入数组的每个模块,除了上述通过连接一个字符串的例外,但这具有包含所有可能模块的效果,通常应该避免。

【讨论】:

如果 Webpack 文档中清楚地解释了这一点。 非常感谢,感谢您澄清这一点,尤其是对根本原因的详细描述。您对我应该如何加载我的文件以按照一般做法进行显示有什么建议吗?我对 React 编程和任何严肃的编程都很陌生,所以大致了解哪种设计模式适合会很好,所以我可以进一步研究它们。谢谢。 有没有办法让 webpack 捆绑 package.json 中的每个模块? (当然,除非需要其中之一,否则它不会全部加载到客户端浏览器上) 附加文档webpack.js.org/api/module-methods/… 基本上起始路径不能是动态的!!例如这仍然有效:require('./src/' + moduleName );。请阅读随附的 require with expression 文档。

以上是关于webpack 动态模块加载器的主要内容,如果未能解决你的问题,请参考以下文章

使用 Typescript 使用 Webpack 动态加载模块

webpack中的加载器

React Webpack - 错误:模块不是加载器(必须具有正常或俯仰功能)

1.webpack-----模块加载器兼打包工具

实现简单的 JS 模块加载器

在 Webpack 2 中使用 TypeScript 加载 SASS 模块