构建 umd 产物
umd 全称为 Universal Module Definition,这种格式的 JS 文件可以运行在多个运行环境:
- 浏览器环境:基于 AMD 规范进行模块加载
- Node.js 环境:基于 CommonJS 进行模块加载
- 其他情况:将模块挂载在全局对象上。
因此我们可以通过下面的方式,将项目的构建产物指定为 umd 产物:
export default defineConfig({
buildConfig: {
format: 'umd',
},
});
umd 产物的第三方依赖处理
在 「如何处理第三方依赖」 章节中,我们知道可以通过 autoExternals
和 externals
API 来控制项目是否对第三方依赖打包。
因此在构建 umd 产物的过程中,我们也可以这样使用:
示例
package.json
{
"dependencies": {
"react": "^17"
}
}
modern.config.ts
export default defineConfig({
buildConfig: {
format: 'umd',
autoExternal: false,
externals: ['react'],
},
});
src/index.ts
import React from 'react';
console.info(React);
dist/index.js
(function (global, factory) {
if (typeof module === 'object' && typeof module.exports === 'object')
factory(exports, require('react'));
else if (typeof define === 'function' && define.amd)
define(['exports', 'react'], factory);
else if (
(global = typeof globalThis !== 'undefined' ? globalThis : global || self)
)
factory((global.index = {}), global.react);
})(this, function (exports, _react) {
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true,
});
_react = /*#__PURE__*/ _interopRequireDefault(_react);
function _interopRequireDefault(obj) {
return obj && obj.__esModule
? obj
: {
default: obj,
};
}
console.info(_react.default);
});
通过上面的例子我们知道,当使用 autoExternal
和 externals
API 后:
- 在 Node.js 环境下,可以通过
require('react')
获取 react 依赖。
- 在 浏览器环境下,可以通过
global.react
获取 react 依赖。
三方依赖的全局变量名称
然而在浏览器环境下,获取第三方依赖的时候,全局变量名称不一定与依赖名称完全相同,此时就要使用 buildConfig.umdGlobals
API。
还是使用之前的例子,当 react
依赖以 windows.React
或者 global.React
全局变量的形式存在于浏览器环境下,那么此时:
export default defineConfig({
buildConfig: {
format: 'umd',
umdGlobals: {
react: 'React',
},
},
});
src/index.ts
import React from 'react';
console.info(React);
dist/index.js
(function (global, factory) {
if (typeof module === 'object' && typeof module.exports === 'object')
factory();
else if (typeof define === 'function' && define.amd) define([], factory);
else if (
(global = typeof globalThis !== 'undefined' ? globalThis : global || self)
)
factory();
})(this, function () {
// ...
// libuild:globals:react
var require_react = __commonJS({
'libuild:globals:react'(exports, module1) {
module1.exports = Function('return this')()['React'];
},
});
// src/index.ts
var import_react = __toESM(require_react());
console.info(import_react.default);
});
此时项目就可以运行在浏览器中,并使用存在于全局对象上的 React
变量了。
更改项目的全局变量名称
当我们将下面的代码打包成 umd 产物并运行在浏览器的时候,我们可以通过 window.index
来使用该模块。
./src/index.ts
export default () => {
console.info('hello world');
};
默认情况下,以源码文件名称作为该模块在浏览器里全局变量的名称。对于上面的例子,其产物内容如下:
./dist/index.js
(function (global, factory) {
if (typeof module === 'object' && typeof module.exports === 'object')
factory(exports);
else if (typeof define === 'function' && define.amd)
define(['exports'], factory);
else if (
(global = typeof globalThis !== 'undefined' ? globalThis : global || self)
)
factory((global.index = {}));
})(this, function (exports) {
//...
});
如果需要修改它,则需要使用 buildConfig.umdModuleName
API。
当使用该 API 后:
export default defineConfig({
buildConfig: {
format: 'umd',
umdModuleName: 'myLib',
},
});
此时构建产物的内容为:
./dist/index.js
(function (global, factory) {
if (typeof module === 'object' && typeof module.exports === 'object')
factory(exports);
else if (typeof define === 'function' && define.amd)
define(['exports'], factory);
else if (
(global = typeof globalThis !== 'undefined' ? globalThis : global || self)
)
factory((global.myLib = {}));
})(this, function (exports) {
//...
});