前端模块化之 ES modules

前言

ES modules 是原生 JavaScript 提供的模块功能,逐渐被更多的浏览器开始支持

入门篇

先了解下基础用法。

html 文件中使用 ES modules 语法执行 js

在 script 标签中 设置 type = module,浏览器就会以 ES modules 的标准去执行 script 标签中的 JavaScript 代码。默认情况下,代码是以严格模式执行的。

<script type="module">
    console.log('this is es module')
</script>

私有作用域

每一个设置 type=module 的标签内都会形成一个私有作用域。作用域之间的变量不能直接共享。

<script type="module">
    var a = 1
    console.log(a)
</script>

<script type="module">
    console.log(a)
</script>

第 1 组 script 中的代码正常输出变量 a 的值,第 2 段会报以下错误:a is not defined。

外链 JS 文件加载

ES modules 会以 CORS 方式加载外部 js 文件。提供 js 文件的服务器需要设置 CORS 后,ES modules 的 script 标签才能正常加载文件。

<script type="module" src="https://unpkg.com/jquery@3.6.0/dist/jquery.js"></script> //第一个文件服务器配置了CORS
<script type="module" src="https://abc.com/jquery@3.6.0/dist/jquery.js"></script> //第二个没有配置

结果:第 1 组 script 标签加载成功,第 2 组加载失败。

延迟执行,作用与 defer 一致。

未设置 type = module 前,会先执行完 01_demo.js 的代码。p 标签的渲染会被阻塞。
设置 type = module 后,p 标签的渲染不会被阻塞。

<script src="./01_demo.js" type="module"></script>
<p>测试</p>

导出

导出方式

// module.js - 单独导出
export var name = "foo module";
export class A {}
export function bar() {}

// 统一导出
var name = "foo module";
class A {}
function bar() {}
export { name, A, bar }

// app.js - 导入
import { name } from "./module.js";
console.log(name);

导出重命名

const age = 25;
export { age as Age };

默认模块导出,导入时也要重命名

const age = 25;
export { age as default };
export default age;

import { default as Age } from './module.js'
import Age from './module.js'
console.log(Age)

注意事项:

1.导出时,export 后面不是字面量对象。import 后面也不是对象解构。
2.export default { name, age } 是等价于导出一个对象,export { a, b, c } 则是固定用法。
3.进行导入操作时,导入的是同一份引用,是引用关系,并非值,这一点与 common.js 不一样。在导入之后,不能对导入变量进行修改,它是一个只读的关系。

导入

1.导入语句中,需要指定完整路径,不能忽略文件后缀名(但是现有第三包,或者其也是支持不写文件后缀名)。而 common js 是支持忽略文件后缀名。
2.路径必须以 / 开头。导入路径支持使用 cdn url 外链 js 文件的形式。
3.以下导入方式等价于执行导入文件中的 js 代码。

import {} from './module.js'
import './module.js'

4.将模块中所有内容一次性导入,通过对象.变量方式访问。

import * as xxx   from './module.js'

5.动态导入,import() 等价于函数调用,非函数调用形式只能置于顶层。

import('./module.js').then(module => {
   console.log(module)
})

6.默认成员和具名成员导入。

import { name, age, default as title } from './module.js'
import title, { name, age } froom './module.js'

导出导入成员

一种代码组织方式,将散落模块组织成新模块。

// components/button.js
export const Button = "Button component";

// components/radio.js
export const Radio = "Radio component";

// components/index.js
import { Button } from "./button.js";
import { Radio } from "./radio.js";
export { Button, Radio };
// app.js
import { Button, Radio } from "./component/index.js";
console.log(Button);
console.log(Radio);

Polyfill 篇

ES modules 是 ES6 推出的新语法特性,在低版本浏览器上需要通过 Polyfill 方式去解决兼容性问题.
script 添加 nomodule 设置,避免在正常浏览器出现代码执行两次的情况。nomodule 表示当前浏览器不支持 modules 的情况下加载使用。

<script nomodule src="https://unpkg.com/promise-polyfill@8.2.0/dist/polyfill.min.js"></script>
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
<script nomodule src="https://unpkg.com/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>

Node 中应用篇

背景

Node 中对 ES modules 语法特性的支持还在实验阶段。node 版本大于 8.5,脚本执行命令添加 --experimental-modules 即可运行 ES modules 代码。
Node 对 ES modules 特性支持的源码

与 CommonJS 交互

1.ES modules 中可以导入 CommonJS 模块。
2.CommonJS 中不能导入 ES modules 模块。
3.CommonJS 始终只会导出一个默认成员。
4.import 不是解构对象

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容