前端模块化输出
type
status
date
slug
summary
tags
category
icon
password
Blocking
Blocked by
top
URL
Sub-item
Parent item
模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。
ㅤ | 无模块化 | CommonJS规范 | AMD规范 | CMD规范 | ES6模块化 |
适用 | ㅤ | 服务端 | 浏览器端 | 浏览器端 | 浏览器端 |
加载方式 | ㅤ | 同步加载 | 异步加载、模块开始加载所有依赖 | 按需加载 | 异步加载 |
实现库 | ㅤ | ㅤ | requireJs | seajs | ㅤ |
来源 | ㅤ | 前端社区 | 前端社区 | 前端社区 | 官方 |
是否需要bebal编译 | 否 | 否 | 否 | 否 | 是 |
无模块化
将所有JS文件都放在一块,代码执行顺序就按照文件的顺序执行。
缺点
- 污染全局作用域。 因为每一个模块都是暴露在全局的,简单的使用,会导致全局变量命名冲突,当然,我们也可以使用命名空间的方式来解决。
- 对于大型项目,各种js很多,开发人员必须手动解决模块和代码库的依赖关系,后期维护成本较高。
- 依赖关系不明显,不利于维护。 比如main.js需要使用jquery,但是,从上面的文件中,我们是看不出来的,如果jquery忘记了,那么就会报错。
CommonJS
核心思想
- 通过 require 方法来同步加载所要依赖的其他模块,
- 通过 module.exports 来导出需要暴露的接口
特点
- 同步加载
CommonJS
模块通常是同步加载的,这意味着模块在被require
时会立即加载和执行。这在服务器端是可行的,因为文件通常都是本地的,但在浏览器中可能会导致性能问题。
- 模块导出
- 每个
CommonJS
模块都有一个module
对象,该对象有一个exports
属性。模块可以通过添加属性到exports
对象或者直接将module.exports
赋值为一个值(如函数、对象或类)来导出内容。
- 模块导入
- 使用
require
函数来导入其他模块。require
函数接受一个模块标识符(通常是文件路径)作为参数,并返回该模块导出的内容。
- 模块作用域
CommonJS
模块中的变量、函数等默认都是私有的,除非它们被明确地导出。
缺点
- CommonJS 是同步加载模块的,只有加载完成,才能执行后面的操作。
- 由于 CommonJS 是同步加载模块的,在服务器端,文件都是保存在硬盘上,所以同步加载没有问题,但是对于浏览器端,需要将文件从服务器端请求过来,那么同步加载就不适用了,所以,CommonJS是不适用于浏览器端的。
例子
整体加载fs模块(即加载fs的所有方法),生成一个对象(_fs),然后再从这个对象上面读取 3 个方法。这种加载称为“运行时加载”,因为只有运行时才能得到这个对象,导致完全没办法在编译时做“静态优化”。
ES Module
- 静态结构
ESM
的导入和导出语句是静态的,正常情况下它们必须出现在模块的顶层作用域,并且不能被条件语句或函数包围。
- 导出和导入语法
ESM
使用export
关键字来导出模块的公共接口,使用import
关键字来导入其他模块的导出。
- 异步和按需加载
ESM
支持异步模块加载,允许按需动态导入模块。
- 模块解析
ESM
的模块解析遵循URL
的规则,可以使用相对路径、绝对路径或URL
。
- 浏览器和
Node.js
支持 ESM
在现代浏览器中得到了原生支持,无需编译或打包。Node.js
从版本12
开始提供了对ESM
的实验性支持,并在后续版本中逐步完善。
common.js 和 es6 中模块引入的区别?
CommonJS 是一种模块规范,最初被应用于 Nodejs,成为 Nodejs 的模块规范。
在 ES6 出来之前,前端也实现了一套相同的模块规范 (例如: AMD),用来对前端模块进行管理。自 ES6 起,引入了一套新的 ES6 Module 规范,在语言标准的层面上实现了模块功能,有望成为浏览器和服务器通用的模块解决方案。但目前浏览器对 ES6 Module 兼容还不太好,我们平时在 Webpack 中使用的 export 和 import,会经过 Babel 转换为 CommonJS 规范。
- CommonJS 是运行时加载,ES6 模块是静态加载。所以前者支持动态导入。后者可以做静态分析,做tree-sharking。
- CommonJs 是同步加载模块,因为用于服务端,文件都在本地。而后者是异步导入,因为用于浏览器。同步加载:所谓同步加载就是加载资源或者模块的过程会阻塞后续代码的执行;异步加载:不会阻塞后续代码的执行;
- CommonJS 是值拷贝(深拷贝),就算导出的值变了,原本的值也不会改变,如果想要更新,必须重新导入一次。ES6 采用值引用(浅拷贝),导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化。
- CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
- CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined
参考
前端模块化详解(完整版)
Updated Aug 13, 2021
`What is 全面ESM` 🤩
Updated Dec 30, 2023