目录
一、ES Modules 特性
二、ES Modules 导出
三、ES Modules 浏览器环境 Polyfill
四、ES Modules in Node.js - 支持情况
五、 ES Modules in Node.js - 与 CommonJS 交互
六、ES Modules in Node.js - 与 CommonJS 的差异
七、ES Modules in Node.js - 新版本进一步支持
八、 ES Modules in Node.js - Babel 兼容方案
一、ES Modules 特性
- 特性1:EMS 自动采用严格模式,忽略 ‘use strict’
<script type="module">
console.log(this)
</script>
- 特性2:每个 ES module 都是运行在单独的私有作用域中
<script type="module">
var foo = 100
console.log(foo) //100
</script>
<script type="module">
console.log(foo) //找不到
</script>
- 特性3:ESM 是通过 CORS 的方式请求外部 JS 模块的
<script type="module" src="https://unpkg/jquery@3.4.1/dist/jquery.min.js"></script>
- 特性4,:ESM 的 script 标签会延迟执行脚本
二、ES Modules 导出
- import 是载入模块
import { name, hello, Person } from './module.js' console.log(name, hello, Person) import { name } from './module.js' //不能省略 .js import { name } from './module.js' //不能省略 ./ import { name } from '04-import//module.js' import { } from './module.js' //只是导出模块,并不会提取成员 import './module.js' import * as mod from './module.js' //导出所有成员 import('./module.js').then(function (modile) { //动态导入模块 console.log(modile) }) import { name, age, default as title } from './module.js' //导出默认成员 import title, { name, age } from './module.js'
- export 是导出模块
//index.js export { default as button } from './button.js' export { Avatar } from './avatar.js' //button.js export var BUtton = 'Button Component' export default Button //avatar.js export var Avatar = 'Avatar Component'
- 案例如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>ES Module 导出与导入</title> </head> <body> <script type="module" src="app.js"></script> </body> </html>
//module.js var name = 'foo module' function hello () { console.log('hello') } class Person {} export { name, hello, Person } //注意:这个导出的成员并不是字面量对象,{ } 是导出固定的语法
//app.js import { name, hello, Person } from './module.js' // 导出也不是结构对象,是固定的一种语法 console.log(name, hello, Person) // 导出的成员是只读的成员
三、ES Modules 浏览器环境 Polyfill
- ES Modules 是2014年出来的,目前很多浏览器不支持此功能,需要引入 js文件,引入链接如下,也可 npm 安装
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ES Module 浏览器环境 Polyfill</title>
</head>
<body>
<!-- nomodule 表示支持 polyfill的浏览器不去加载,解决二次执行的问题 ,测试阶段使用,生产阶段不可以用,因为原理在运行阶段动态解析脚本,效率非常差,要用的话在项目里预先编译-->
<script nomodule src="https://unpkg/promise-polyfill@8.1.3/dist/polyfill.min.js"></script>
<script nomodule src="https://unpkg/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
<script nomodule src="https://unpkg/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
<script type="module">
import { foo } from './module.js'
console.log(foo)
</script>
</body>
</html>
四、ES Modules in Node.js - 支持情况
命令行输入:node --experimental-modules esm.mjs
// 第一,将文件的扩展名由 .js 改为 .mjs;
// 第二,启动时需要额外添加 `--experimental-modules` 参数;
import { foo, bar } from './module.mjs'
console.log(foo, bar)
// 此时我们也可以通过 esm 加载内置模块了
import fs from 'fs'
fs.writeFileSync('./foo.txt', 'es module working')
// 也可以直接提取模块内的成员,内置模块兼容了 ESM 的提取成员方式
import { writeFileSync } from 'fs'
writeFileSync('./bar.txt', 'es module working')
// // 对于第三方的 NPM 模块也可以通过 esm 加载
import _ from 'lodash'
_.camelCase('ES Module')
// 不支持,因为第三方模块都是导出默认成员
import { camelCase } from 'lodash'
console.log(camelCase('ES Module'))
五、 ES Modules in Node.js - 与 CommonJS 交互
- ES Modules中可以导入 CommonJS 模块
- CommonJS 中不能导入 ES Modules 模块
- CommonJS 始终只会导出一个默认成员
- 注意 import 不是解构导出对象
六、ES Modules in Node.js - 与 CommonJS 的差异
- 在 CommonJS 下可以正常输出
//cjs.js // 加载模块函数 console.log(require) // 模块对象 console.log(module) // 导出对象别名 console.log(exports) // 当前文件的绝对路径 console.log(__filename) // 当前文件所在目录 console.log(__dirname)
- 在 ES Module 下需要引用路径才能正常输出内容
// ESM 中没有模块全局成员了 // require, module, exports 自然是通过 import 和 export 代替 // __filename 和 __dirname 通过 import 对象的 meta 属性获取 // const currentUrl = import.meta.url // console.log(currentUrl) // 通过 url 模块的 fileURLToPath 方法转换为路径 import { fileURLToPath } from 'url' import { dirname } from 'path' const __filename = fileURLToPath(import.meta.url) const __dirname = dirname(__filename) console.log(__filename) console.log(__dirname)
七、ES Modules in Node.js - 新版本进一步支持
- 在 package.json 将 type 类型 设置为 module,就可以使用 ES Module 模块,此时就不需要修改文件扩展名为 .mjs 了
//package.json { "type": "module" }
八、 ES Modules in Node.js - Babel 兼容方案
- 安装 babel 插件和预设插件 yarn add @babel/node @babel/core @babel/preset-env --dev
- yarn babel-node index.js --presets=@babel/preset-env
- 如果觉得配置麻烦,可以新建一个 .babelrc文件进行配置
{ "presets": [ "@babel/preset-env" ] }
- yarn babel-node index.js
- yarn remove @babel/preset-env
- yarn add @babel/plugin-transform-modules-commonjs --dev
{ "plugins": [ "@babel/plugin-transform-modules-commonjs" ] }
- yarn babel-node index.js
更多推荐
ES Modules【浏览器端的模块开发规范】
发布评论