使用 webpack 在运行时动态要求 JS 文件
Require JS files dynamically on runtime using webpack
我正在尝试将库从 grunt/requirejs 移植到 webpack 并偶然发现了一个问题,这可能会破坏这项工作。
我尝试移植的库有一个函数,可以加载和评估多个模块——基于我们从配置文件中获取的文件名——到我们的应用程序中。代码看起来像这样(咖啡):
loadModules = (arrayOfFilePaths) ->
new Promise (resolve) ->
require arrayOfFilePaths, (ms...) ->
for module in ms
module ModuleAPI
resolve()
这里的 require
需要在运行时调用并且表现得像 requireJS 一样。 Webpack 似乎只关心 "build-process".
中发生的事情
这是 webpack 根本不关心的事情吗?如果是这样,我还可以使用 requireJS 吗?在运行时动态加载资产有什么好的解决方案?
编辑:loadModule 可以加载在这个库的构建时不存在的模块。它们将由实现我的库的应用程序提供。
有一个名为 context
(http://webpack.github.io/docs/context.html) 的概念,它允许创建动态需求。
也可以定义代码拆分点:http://webpack.github.io/docs/code-splitting.html
function loadInContext(filename) {
return new Promise(function(resolve){
require(['./'+filename], resolve);
})
}
function loadModules(namesInContext){
return Promise.all(namesInContext.map(loadInContext));
}
并像下面这样使用它:
loadModules(arrayOfFiles).then(function(){
modules.forEach(function(module){
module(moduleAPI);
})
});
但它可能不是您所需要的 - 您将有很多块而不是一个包含所有必需模块的包,并且它可能不是最佳的..
最好在配置文件中定义模块要求,并将其包含到您的构建中:
// modulesConfig.js
module.exports = [
require(...),
....
]
// run.js
require('modulesConfig').forEach(function(module){
module(moduleAPI);
})
所以我发现我要求在运行时加载一些文件,这些文件只能在“app-compile-time”上可用,而不能在“library-compile-time”上使用 webpack 不容易实现。
我将更改机制,以便我的库不再需要这些文件,但需要传递所需的模块。有点告诉我,无论如何这会更好 API。
编辑澄清:
基本上,而不是:
// in my library
load = (path_to_file) ->
(require path_to_file).do_something()
// in my app (using the 'compiled' libary)
cool_library.load("file_that_exists_in_my_app")
我这样做:
// in my library
load = (module) ->
module.do_something()
// in my app (using the 'compiled' libary)
module = require("file_that_exists_in_my_app")
cool_library.load(module)
第一个代码在 require.js 中有效,但在 webpack 中无效。
事后看来,我觉得无论如何在运行时加载第 3 方库都是错误的。
您也可以尝试使用这样的库:https://github.com/Venryx/webpack-runtime-require
免责声明:我是它的开发者。我写它是因为我也对无法在运行时自由访问模块内容感到沮丧。 (在我的例子中,用于从控制台进行测试)
我正在尝试将库从 grunt/requirejs 移植到 webpack 并偶然发现了一个问题,这可能会破坏这项工作。
我尝试移植的库有一个函数,可以加载和评估多个模块——基于我们从配置文件中获取的文件名——到我们的应用程序中。代码看起来像这样(咖啡):
loadModules = (arrayOfFilePaths) ->
new Promise (resolve) ->
require arrayOfFilePaths, (ms...) ->
for module in ms
module ModuleAPI
resolve()
这里的 require
需要在运行时调用并且表现得像 requireJS 一样。 Webpack 似乎只关心 "build-process".
这是 webpack 根本不关心的事情吗?如果是这样,我还可以使用 requireJS 吗?在运行时动态加载资产有什么好的解决方案?
编辑:loadModule 可以加载在这个库的构建时不存在的模块。它们将由实现我的库的应用程序提供。
有一个名为 context
(http://webpack.github.io/docs/context.html) 的概念,它允许创建动态需求。
也可以定义代码拆分点:http://webpack.github.io/docs/code-splitting.html
function loadInContext(filename) {
return new Promise(function(resolve){
require(['./'+filename], resolve);
})
}
function loadModules(namesInContext){
return Promise.all(namesInContext.map(loadInContext));
}
并像下面这样使用它:
loadModules(arrayOfFiles).then(function(){
modules.forEach(function(module){
module(moduleAPI);
})
});
但它可能不是您所需要的 - 您将有很多块而不是一个包含所有必需模块的包,并且它可能不是最佳的..
最好在配置文件中定义模块要求,并将其包含到您的构建中:
// modulesConfig.js
module.exports = [
require(...),
....
]
// run.js
require('modulesConfig').forEach(function(module){
module(moduleAPI);
})
所以我发现我要求在运行时加载一些文件,这些文件只能在“app-compile-time”上可用,而不能在“library-compile-time”上使用 webpack 不容易实现。
我将更改机制,以便我的库不再需要这些文件,但需要传递所需的模块。有点告诉我,无论如何这会更好 API。
编辑澄清:
基本上,而不是:
// in my library
load = (path_to_file) ->
(require path_to_file).do_something()
// in my app (using the 'compiled' libary)
cool_library.load("file_that_exists_in_my_app")
我这样做:
// in my library
load = (module) ->
module.do_something()
// in my app (using the 'compiled' libary)
module = require("file_that_exists_in_my_app")
cool_library.load(module)
第一个代码在 require.js 中有效,但在 webpack 中无效。
事后看来,我觉得无论如何在运行时加载第 3 方库都是错误的。
您也可以尝试使用这样的库:https://github.com/Venryx/webpack-runtime-require
免责声明:我是它的开发者。我写它是因为我也对无法在运行时自由访问模块内容感到沮丧。 (在我的例子中,用于从控制台进行测试)