问题描述
我有以下 import mongo from "mongodb";
我想避免使用 npm,而是像这样使用 unpkg.com import mongo from "https://unpkg.com/mongodb";
。但是,当我跑步时,我得到...
...@penguin:~/...$ node --harmony test.mjs node:internal/process/esm_loader:74
internalBinding('errors').triggeruncaughtException(
^
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only file and data URLs are supported by the default ESM loader. Received protocol 'https:'
at new NodeError (node:internal/errors:328:5)
at Loader.defaultResolve [as _resolve] (node:internal/modules/esm/resolve:825:11)
at Loader.resolve (node:internal/modules/esm/loader:86:40)
at Loader.getModuleJob (node:internal/modules/esm/loader:230:28)
at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:56:40)
at link (node:internal/modules/esm/module_job:55:36) {
code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
}
因为它使用术语 default 模块加载器,我想知道是否有我可以使用的替代 ESM 加载器。
解决方法
Node 不支持通过 HTTP/HTTPS URL 加载 ES 模块,但它确实对模块加载器有实验性支持,甚至以 HTTPS 加载器为例:
https://nodejs.org/api/esm.html#esm_https_loader
// https-loader.mjs
import { get } from 'https';
export function resolve(specifier,context,defaultResolve) {
const { parentURL = null } = context;
// Normally Node.js would error on specifiers starting with 'https://',so
// this hook intercepts them and converts them into absolute URLs to be
// passed along to the later hooks below.
if (specifier.startsWith('https://')) {
return {
url: specifier
};
} else if (parentURL && parentURL.startsWith('https://')) {
return {
url: new URL(specifier,parentURL).href
};
}
// Let Node.js handle all other specifiers.
return defaultResolve(specifier,defaultResolve);
}
export function getFormat(url,defaultGetFormat) {
// This loader assumes all network-provided JavaScript is ES module code.
if (url.startsWith('https://')) {
return {
format: 'module'
};
}
// Let Node.js handle all other URLs.
return defaultGetFormat(url,defaultGetFormat);
}
export function getSource(url,defaultGetSource) {
// For JavaScript to be loaded over the network,we need to fetch and
// return it.
if (url.startsWith('https://')) {
return new Promise((resolve,reject) => {
get(url,(res) => {
let data = '';
res.on('data',(chunk) => data += chunk);
res.on('end',() => resolve({ source: data }));
}).on('error',(err) => reject(err));
});
}
// Let Node.js handle all other URLs.
return defaultGetSource(url,defaultGetSource);
}
像这样使用:
node node --experimental-loader ./https-loader.mjs ./main.mjs