Webpack 5 无法导入 UMD 模块
Webpack 5 cannot import UMD module
我最近升级到 Webpack 5,但在导入 UMD 模块时遇到了一些问题。
特别是,我正在尝试导入 Leaflet。 Leaflet 似乎导出了一个由 rollup.js 创建的 UMD 模块,它看起来像这样:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.L = {})));
}(this, (function (exports) { 'use strict';
[...]
})));
如你所见,它首先尝试使用 CommonJS(如果定义了 exports
和 module
),然后它尝试使用 AMD(如果定义了 define
),否则它会尝试通过从模块上下文中引用 this
来将自己置于全局范围内。
Webpack(没有任何加载器)编译成这样:
(function (global, factory) {
typeof exports === 'object' && "object" !== 'undefined' ? factory(exports) :
typeof define === 'function' && __webpack_require__.amdO ? define(['exports'], factory) :
(factory((global.L = {})));
}(undefined, (function (exports) { 'use strict';
[...]
})));
具体来说,它做了什么:
- 将
typeof module
替换为"object"
- 将
define.amd
替换为__webpack_require__.amd0
- 将
this
替换为undefined
在构建过程中,webpack 给我一个警告:export 'default' (imported as 'L') was not found in 'leaflet' (possible exports: )
。当我在浏览器中打开已编译的包时,出现错误 Uncaught TypeError: Cannot set property 'L' of undefined
.
发生的是 CommonJS 失败(因为 exports
未定义),AMD 失败(因为 define
未定义)最后设置全局也失败,因为 this
是替换为 undefined
.
根据the Webpack docs,Webpack 应该普遍支持导入 CommonJS 和 AMD 模块,但在这种情况下似乎两者都不起作用。
我该怎么做才能解决这个问题?
我缩小了问题范围,发现问题是由我以某种方式使用 imports-loader
引起的。
在更新之前,我使用 imports-loader
添加我的依赖项未导入的任何需要的传递依赖项,特别是 CSS 文件。配置看起来像这样:
{ module: { rules: [ {
test: /\/node_modules\/leaflet\/.*\.js$/,
loader: "imports-loader?asdf=leaflet/dist/leaflet.css"
} ] } }
升级之后webpack不再接受loader的字符串语法,imports-loader也改了语法,所以我改成:
{ module: { rules: [ {
test: /\/node_modules\/leaflet\/.*\.js$/,
loader: "imports-loader",
options: {
imports: "default leaflet/dist/leaflet.css asdf"
}
} ] } }
这似乎可以完成工作并正确包含必要的 CSS 文件。然而,当我发现这部分配置是问题的原因时,我深入研究了 documentation of imports-loader
。原来我使用的配置现在生成了以下代码行:
import asdf from "leaflet/dist/leaflet.css";
(我本可以使用 "side-effects leaflet/dist/leaflet.css"
来获得相同的结果,而不必使用 asdf
作为伪造的导入名称)。虽然这正确导入了 CSS 文件,但它可能导致 webpack 认为此文件是正确的 ES 模块,从而禁用了对 CommonJS/AMD/UMD 模块的支持。我将 imports-loader 的配置更改为以下内容:
{ module: { rules: [ {
test: /\/node_modules\/leaflet\/.*\.js$/,
loader: "imports-loader",
options: {
imports: "pure leaflet/dist/leaflet.css",
type: "commonjs"
}
} ] } }
根据文档,这会创建以下代码行:
require("leaflet/dist/leaflet.css");
进行此更改后,似乎没有问题。
有趣的是,似乎 webpack 实际上检测了整个 UMD 块,而不仅仅是提供 exports
和 define
变量,所以它现在将 Leaflet 代码编译成这样:
(function (global, factory) {
true ? factory(exports) :
0;
}(this, (function (exports) { 'use strict';
[...]
})));
我最近升级到 Webpack 5,但在导入 UMD 模块时遇到了一些问题。
特别是,我正在尝试导入 Leaflet。 Leaflet 似乎导出了一个由 rollup.js 创建的 UMD 模块,它看起来像这样:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.L = {})));
}(this, (function (exports) { 'use strict';
[...]
})));
如你所见,它首先尝试使用 CommonJS(如果定义了 exports
和 module
),然后它尝试使用 AMD(如果定义了 define
),否则它会尝试通过从模块上下文中引用 this
来将自己置于全局范围内。
Webpack(没有任何加载器)编译成这样:
(function (global, factory) {
typeof exports === 'object' && "object" !== 'undefined' ? factory(exports) :
typeof define === 'function' && __webpack_require__.amdO ? define(['exports'], factory) :
(factory((global.L = {})));
}(undefined, (function (exports) { 'use strict';
[...]
})));
具体来说,它做了什么:
- 将
typeof module
替换为"object"
- 将
define.amd
替换为__webpack_require__.amd0
- 将
this
替换为undefined
在构建过程中,webpack 给我一个警告:export 'default' (imported as 'L') was not found in 'leaflet' (possible exports: )
。当我在浏览器中打开已编译的包时,出现错误 Uncaught TypeError: Cannot set property 'L' of undefined
.
发生的是 CommonJS 失败(因为 exports
未定义),AMD 失败(因为 define
未定义)最后设置全局也失败,因为 this
是替换为 undefined
.
根据the Webpack docs,Webpack 应该普遍支持导入 CommonJS 和 AMD 模块,但在这种情况下似乎两者都不起作用。
我该怎么做才能解决这个问题?
我缩小了问题范围,发现问题是由我以某种方式使用 imports-loader
引起的。
在更新之前,我使用 imports-loader
添加我的依赖项未导入的任何需要的传递依赖项,特别是 CSS 文件。配置看起来像这样:
{ module: { rules: [ {
test: /\/node_modules\/leaflet\/.*\.js$/,
loader: "imports-loader?asdf=leaflet/dist/leaflet.css"
} ] } }
升级之后webpack不再接受loader的字符串语法,imports-loader也改了语法,所以我改成:
{ module: { rules: [ {
test: /\/node_modules\/leaflet\/.*\.js$/,
loader: "imports-loader",
options: {
imports: "default leaflet/dist/leaflet.css asdf"
}
} ] } }
这似乎可以完成工作并正确包含必要的 CSS 文件。然而,当我发现这部分配置是问题的原因时,我深入研究了 documentation of imports-loader
。原来我使用的配置现在生成了以下代码行:
import asdf from "leaflet/dist/leaflet.css";
(我本可以使用 "side-effects leaflet/dist/leaflet.css"
来获得相同的结果,而不必使用 asdf
作为伪造的导入名称)。虽然这正确导入了 CSS 文件,但它可能导致 webpack 认为此文件是正确的 ES 模块,从而禁用了对 CommonJS/AMD/UMD 模块的支持。我将 imports-loader 的配置更改为以下内容:
{ module: { rules: [ {
test: /\/node_modules\/leaflet\/.*\.js$/,
loader: "imports-loader",
options: {
imports: "pure leaflet/dist/leaflet.css",
type: "commonjs"
}
} ] } }
根据文档,这会创建以下代码行:
require("leaflet/dist/leaflet.css");
进行此更改后,似乎没有问题。
有趣的是,似乎 webpack 实际上检测了整个 UMD 块,而不仅仅是提供 exports
和 define
变量,所以它现在将 Leaflet 代码编译成这样:
(function (global, factory) {
true ? factory(exports) :
0;
}(this, (function (exports) { 'use strict';
[...]
})));