Node 项目支持 ESModule
1. 通过 webpack 完成 ES Module 资源构建
-
安装 webpack 包
npm i webpack webpack-cli -D
-
创建 webpack 配置文件
webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './transESModule/index.js',
output: {
filename: 'core.js',
path: path.join(__dirname, '/dist'),
},
// 注意这里要修改为 node 以支持 Node 内置库的使用
target: 'node',
} -
添加构建指令
package.json
"scripts": {
"build": "webpack",
"dev": "webpack -w"
}, -
执行打包构建
npm run build
-
修改node引用文件
#!/usr/bin/env node
require('../dist/core') -
添加bable将高级语法进行转换支持低版本node
-
安装库
npm i -D bable-loader @bable/core @bable/preset-env @babel/plugin-transform-runtime @babel/runtime-corejs3
-
修改 webpack 配置文件
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [
[
'@babel/plugin-transform-runtime',
{
corejs: 3,
regenerator: true,
useESModules: true,
helpers: true,
},
],
],
},
},
},
],
}
}
-
2. 通过 Node 原生支持 ES Module
Node.js 从 v16 开始为 ESM 提供默认支持。 在早期版本中,需要使用 --experimental-modules
选项来激活该功能。
默认情况下,Node 不支持以 .js
扩展名结尾的内部文件的导入和导出。 可以将文件后缀设为 .mjs
,其中 ESM 始终可用,或者修改 package.json 文件使其包含 "type":"module"
。
{
...
"type": "module",
...
}
对于专门使用 ESM 的项目,选择后一种方法通常更方便。 Node 使用 type 字段来确定项目的默认模块系统。 该模块系统始终用于处理普通的 .js
文件。 当不手动设置时,CJS 是默认的模块系统,以最大限度地与现有的 Node 代码生态系统兼容。 具有 .cjs
或 .mjs
扩展名的文件将始终分别被视为 CJS 和 ESM 格式的源码。
从 ESM 导入 CommonJS 模块
可以使用常规导入语句在 ESM 文件中导入 CJS 模块:
// cjs-module.cjs
module.exports.helloWorld = () => console.log("Hello World");
// esm-module.mjs
import component from "./cjs-module.cjs";
component.helloWorld();
// 或者使用下面的方式
import { helloWorld } from "./cjs-module.cjs";
helloWorld();
从 CJS 导入 ESM 模块
当我们想在现有 CJS 代码中使用新的 ESM 模块时,事情会变得更加棘手。 我们不能在 CJS 文件中使用 import 语句。 然而动态 import() 语法确实有效,并且可以与 await 配合从而相对方便地访问模块:
// esm-module.mjs
const helloWorld = () => console.log("Hello World");
export { helloWorld };
// esm-module-2.mjs
export default = () => console.log("Hello World");
// cjs-module.cjs
const loadHelloWorld = async () => {
const { helloWorld } = await import("./esm-module.mjs");
return helloWorld;
};
const helloWorld = await loadHelloWorld();
helloWorld();
const loadHelloWorld2 = async() => {
const helloWorld2 = await import("./esm-module-2.mjs");
return helloWorld2;
};
const helloWorld2 = await loadHelloWorld2();
helloWorld2();
此结构可用于异步访问 ESM 模块的默认导出和命名导出。