Node.js 在 8.5 版本过后,开始以实验特性支持 ESM
experimental-modules
参数,该参数表示启用 Node.js 的实验特性node --experimental-modules index.mjs
// ./module.mjs export const foo = 'hello' export const bar = 'world'
// ./index.mjs import { foo, bar } from './module.mjs' console.log(foo, bar) // import fs from 'fs' // fs.writeFileSync('./foo.txt', 'es module working') // 内置模块兼容了 ESM 的提取成员方式 import { writeFileSync } from 'fs' writeFileSync('./bar.txt', 'es module ') // import _ from 'lodash' // console.log(_.camelCase('ES Module')) // 不支持,因为第三方模块都是导出默认成员 // import { camelCase } from 'lodash' // console.log(camelCase('ES Module'))
ES Moudule 中可以导入 CommonJS 模块
CommonJS 中不能导入 ES Modules 模块
CommonJS 始终只会导出一个默认成员
注意 import 不是解构导出对象
// ./commonjs.js module.exports = { foo: 'commonjs exports value' } // 也可以使用 module.exports 别名 exports 导出 exports.foo = 'commonjs exports value' // 不能在 CommonJS 模块中通过 require 载入 ES Module const mod = require('./es-module.mjs') console.log(mod)
// ./es-module.mjs // ES Moudule 中可以导入 CommonJS 模块 import mod from './commonjs.js' console.log(mod) // 不能直接提取成员,注意 import 不是解构导出对象 import { foo } from './commonjs.js' console.log(foo) // export const foo = 'es module export value'
```JavaScript // ./cjs.js // 加载模块函数 console.log(require) // 模块对象 console.log(module) // 导出对象别名 console.log(exports) // 当前文件的绝对路径 console.log(__filename) // 当前文件所在目录 console.log(__dirname) ``` ```JavaScript // ESM 中没有 CommonJS 中的那些模块全局成员 // console.log(require) // console.log(module) // console.log(exports) // 文件 url 地址 console.log(import.meta.url) // file:///C:/Users/%E9%87%91%E8%AF%81%E5%BC%95%E6%93%8E/Desktop/es-module-in-node/03-differences/esm.mjs // 将文件 url 转换成路径 import { fileURLToPath } from 'url' import { dirname } from 'path' const __filename = fileURLToPath(import.meta.url) console.log(__filename) // C:\Users\金证引擎\Desktop\es-module-in-node\03-differences\esm.mjs const __dirname = dirname(__filename) console.log(__dirname) // C:\Users\金证引擎\Desktop\es-module-in-node\03-differences ```
新版的 node 无需再讲 js 扩展名改成 mjs,只需在 package.json 中 配置 type: module
即能按照 ES Module 的形式去工作,如果还想使用 Common.js ,只需将扩展名修改为 cjs
创建 package.json
// code package.json { "type": "module" }
// ./module.js export const foo = 'hello' export const bar = 'world'
// ./index.js // nvm 切换 node 版本, nvm use 12.10.0 import { foo, bar } from './module.js' console.log(foo, bar)
// ./index.js // nvm 切换 node 版本, nvm use 12.10.0 import { foo, bar } from './module.js' console.log(foo, bar)
// ./index.js // 需文件名修改为 .cjs const path = require('path') console.log(path.join(__dirname, 'foo')) // ReferenceError: require is not defined
安装插件
yarn init -y yarn add @babel/node @babel/core @babel/preset-env --dev
执行命令
yarn babel-node index.js --presets=@babel/preset-env
配置 .babelrc
文件,以上命令简化成:yarn babel-node index.js
{ "presets": ["@babel/preset-env"] }
preset 是 babel 插件的集合
使用单个插件
先移除 @babel/preset-env: yarn remove @babel/preset-env yarn add @babel/plugin-transform-modules-commonjs --dev
修改 .babelrc 文件
{ "plugins": [ "@babel/plugin-transform-modules-commonjs" ] }