我正在构建一个仅在浏览器中使用的 UMD 库。但是,它依赖于另一个 UMD 库/模块/bundle .js 文件,其中包含 Nodejs 模块的 require 语句。这些语句并不总是运行,但仅当该子库检测到它在 NodeJS 中运行时才运行。对于上下文,所需的 Nodejs 模块是
os
、http
和 https
,但它们都是动态需要的。
我的
rollup.config.js
已经在使用 @rollup/plugin-node-resolve
、@rollup/plugin-commonjs
和 @rollup/plugin-typescript
。但在构建时会触发一些警告。
(!) Missing shims for Node.js built-ins
Creating a browser bundle that depends on "os", "http" and "https". You might need to include https://github.com/FredKSchott/rollup-plugin-polyfill-node
(!) Missing global variable names
https://rollupjs.org/guide/en/#outputglobals
Use "output.globals" to specify browser global variable names corresponding to external modules:
os (guessing "require$$0")
http (guessing "require$$1")
https (guessing "require$$2")
生成的捆绑文件:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('os'), require('http'), require('https')) :
typeof define === 'function' && define.amd ? define(['exports', 'os', 'http', 'https'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.ns_ = global.ns_ || {}, global.ns_.Bundle = {}), global.require$$0, global.require$$1, global.require$$2));
})(this, (function (exports, require$$0, require$$1, require$$2) { 'use strict';
// ...
// Pseudo-code
if(node) {
const os = require$$0;
//...
}
捆绑器已将我的
require('os')
语句替换为 require$$0
,因此它不会像我预期的那样“有条件地”调用 require 语句。它们已被预先调用(悬挂)。有什么方法可以让 Rollup 不进行提升吗?
警告中非常清楚地指出,
os
、http
和https
模块包含在浏览器捆绑包中,并且 Rollup 无法确定这些模块的正确全局变量名称。
您可以在 Rollup 配置中使用建议的
output.globals
选项为这些模块指定正确的全局变量名称。
类似:
export default {
output: {
globals: {
os: 'os',
http: 'http',
https: 'https',
},
},
// other options
};
您还可以使用
@rollup/plugin-polyfill-node
(通过将其按原样包含在 Rollup 配置中)自动包含这些内置 Node.js 模块的 polyfill。
请告诉我这是否有效。
不知道是bug还是什么,但是直接使用
require
就会出现这个问题。当直接使用 require
时,commonjs
不认为它是动态的。显然它无法在项目的任何地方找到源代码。因此出于某种原因将其吊起。
为了避免这个问题。您需要包装
require
方法并使用 ignoreDynamicRequires
插件的 commonjs
选项。
以下代码
// rollup.config.js
const { defineConfig } = require("rollup");
const commonjs = require("@rollup/plugin-commonjs");
module.exports = [
defineConfig({
input: "index.js",
context: this,
output: [
{
name: "rollup-dynamic-require",
file: `output.js`,
sourcemap: "inline",
format: "umd",
},
],
plugins: [
commonjs({
ignoreDynamicRequires: true, // this is the option for dynamic imports.
}),
],
}),
];
//index.js
const dynamicRequire = function (module) {
return require(module);
};
(function rollupDynamicRequire() {
let required;
for (const element of [0, 1, 2]) {
if (element === 0) {
required = dynamicRequire("http");
} else if (element === 1) {
required = dynamicRequire("https");
} else if (element === 2) {
required = dynamicRequire("os");
}
console.log(required.globalAgent.protocol);
}
})();
//输出.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global["rollup-dynamic-require"] = factory());
})(this, (function () { 'use strict';
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var rollupDynamicRequire = {};
var hasRequiredRollupDynamicRequire;
function requireRollupDynamicRequire () {
if (hasRequiredRollupDynamicRequire) return rollupDynamicRequire;
hasRequiredRollupDynamicRequire = 1;
const dynamicRequire = function (module) {
return require(module);
};
(function rollupDynamicRequire() {
let required;
for (const element of [0, 1, 2]) {
if (element === 0) {
required = dynamicRequire("http");
} else if (element === 1) {
required = dynamicRequire("https");
} else if (element === 2) {
required = dynamicRequire("os");
}
console.log(required.globalAgent.protocol);
}
})();
return rollupDynamicRequire;
}
var rollupDynamicRequireExports = requireRollupDynamicRequire();
var index = /*@__PURE__*/getDefaultExportFromCjs(rollupDynamicRequireExports);
return index;
}));