如何将同构的 commonJS 代码与 webpack 捆绑在一起

How to bundle isomorphic commonJS code with webpack

本文关键字:webpack 在一起 代码 commonJS 同构      更新时间:2023-09-26

我有一个使用nodeJS模块格式(commonJS(的项目,也应该(部分(在浏览器中运行。

确实有非同构代码路径,其中我有条件地包含模块:

var impl;
try {
    // in node, use node-impl
   impl = require('../node-impl');
} catch (err) {
    // running in browser, use browser-impl
    impl = require('../browser-impl');
}

现在,我想使用 webpack 创建一个在浏览器中运行的捆绑包。因此,我需要将外部(特定于nodeJS(模块定义为webpack.config.js中的external模块,以便它们不会包含在捆绑包中:

external: {
    '../node-impl': true
}

我验证了"../node-impl' 代码实际上不包含在捆绑包中,但发出的代码如下所示:

/***/ },
/* 33 */
/***/ function(module, exports) {
    module.exports = ../node-impl;
/***/ },

这是语法错误的JS,浏览器将在那里抛出语法错误。

如何使用 webpack.js 正确处理这种情况?请注意,我不希望使用 webpack 来运行 nodeJS,只应该使用 webpack 创建浏览器捆绑包。

// Your actual situation: var impl; try { impl = require('../node-impl'); } catch(e) { impl = require('../browser-impl'); }

您需要将此代码段重构为:

var impl = require('../node-impl');

在此返工之后,您的代码只能在节点 js 环境中工作,这很好,因为我们将在捆绑浏览器时模拟此请求...... // webpack.browser.config.js module.exports = { resolve: { alias: { '../node-impl': '../browser-impl' } } };

Webpack - Resolve.Alias或使用package.json#browser或 https://webpack.github.io/docs/configuration.html#resolve-packagealias

我不认为这是外部配置的预期目的。根据文档,

指定不应由 webpack 解析的依赖项,但应成为生成的捆绑包的依赖项。依赖关系的类型取决于 output.libraryTarget。

所以你告诉 webpack 你的构建需要那个模块,而不是捆绑它。它省略了它,但试图要求它。

可能有几种方法可以做你想做的事情。值得一提的是,您可以轻松地让 webpack 从单个配置文件生成具有不同/共享配置的多个构建,这开辟了很多可能性。但我建议的方法是使用 DefinePlugin 定义一个表示执行上下文的布尔"常量"(例如 IN_BROWSER = true(。在require()周围的条件中检查该常量。Webpack 的解析器不是那么聪明,但它可以评估布尔变量,因此它将正确解析条件并且只需要适当的模块。(使用非布尔值,如 CONTEXT = 'browser' 对于 webpack 来说太混乱了,它会解析每个 require 语句。然后,您可以使用 Uglify 插件删除条件中的"死代码",这样它就不会使您的生产构建膨胀。

在@Hitmands的帮助下,我可以想出一个仍然不完美但符合我需求的解决方案。我引入一个虚构的nonexistingmodule并将其声明为外部;然后,我将node-impl特定模块声明为nonexistingmodule

externals: {
    'nonexistingmodule': true,
    '../node-impl': 'nonexistingmodule'
}

这样,我可以保留try/catch模式来加载特定的实现,并且它仍然可以在节点上运行。在浏览器中,nonexistingmodule加载失败,并且加载了browser-impl模块 - 正如我所希望的那样。

我是"不要重构代码以匹配工具"的忠实粉丝,所以我使用这个解决方案。