前言
学习 Webpack/Vue2
升级 Vite/Vue3
时,发现以下不同:
-
新建的
Vitepress
项目默认创建了config.mjs
文件; -
新建的
Vite/Vue3
项目,package.json
中默认加上type: 'module'
配置; -
新建的
Vite/Vue3
项目,postcss.config.cjs
文件后缀必须是.cjs
,否则报错;
其实它们是一个问题,Node.js
对 .js
文件的模块加载方式!
分析
先理清几个概念!!!
Node.js
的模块加载方法有两种:CommonJS
和 ES Modules(ES6/ESM,接下来都用简称 ESM )
CommonJS 和 ESM 区别
功能 | CommonJS | ESM |
---|---|---|
导入/导出接口 | require() 和 exports/module.exports | import 和 export |
输出 | 值的拷贝 | 值的引用 |
动态导入 | 不支持 | 支持 |
作用域 | 全局作用域 | 局部作用域 |
加载 | 运行时加载 | 编译时输出接口 |
同步/异步 | require() 是同步加载模块 | import 命令是异步加载模块 |
循环依赖 | 程序复杂时容易崩溃 | 可处理循环依赖,因为是静态作用域 |
浏览器兼容 | 支持现代浏览器,旧版不支持 | 更适用于早期 Node.js 环境 |
Node.js 支持 | Node.js 打包 JS 代码的原始方式 | v8.5.0(2017.9.12) 开始支持 v13.2.0(2019.11.21) 开始默认支持 |
值得学习的参考链接
Node.js
指导(暂无中文官网,网上找到的其它中文版本较旧,建议直接看英文最新版):
-
NodeJS
CommonJS 和 ESM -
NodeJS CommonJS
中的 require 和 exports/module.exports 说明; -
NodeJS ESM
中的import
andexport
使用官方语法,推荐中文import 和 export; -
关于
CommonJS
和ESM
区别说明,推荐中文 《ES6 模块与 CommonJS 模块的差异》; -
关于
CommonJS
和ESM
互操作性说明; -
循环加载 《CommonJS 模块的循环加载》 和 《ES6 模块的循环加载》;
-
Javascript 静态和动态作用域;
package.json 属性 type
package.json 是对
Node.js
项目或npm
包的描述,里面包含许多元信息。如:项目名称,版本,入口文件,贡献者、依赖插件等。
type 属性值:
commonjs(默认)
:项目中的.js
文件都作为CommonJS
模块加载;module
:项目中的.js
文件都作为ESM
模块加载;
{
// 默认加载方式,不设置也是 commonjs
type: 'commonjs',
// ESM 方式加载
type: 'module',
}
也可混合使用,无论 package.json 中设置哪种 type
// 后缀为 .cjs 都将以 CommonJS 方式加载
import './legacy-file.cjs';
// 后缀为 .cjs 都将以 ESM 方式加载
import 'commonjs-package/src/index.mjs';
值得学习的参考链接
- CommonJS 模块加载 ES6 模块
- ES6 模块加载 CommonJS 模块
- 同时支持两种格式的模块
浏览器加载 ESM 模块
要加入type="module"
属性,且默认是 defer
,即 DOM
渲染完再执行。
<script type="module" src="./foo.js"></script>
<!-- 等同于 -->
<script type="module" src="./foo.js" defer></script>
最后
解答 前言 提到的3个不同点!
Vitepress
文件config.mjs
创建 Vitepress 项目时,package.json
文件中默认没有配置属性 type
而 Vite
相关项目默认支持 ESM
加载方式,所以创建了文件 .mjs
,以支持 ESM
加载;
Vite/Vue3
项目postcss.config.cjs
postcss
使用后缀 .js
报如下错。因为 Vite 官网 明确指出 postcss
配置文件暂不支持 ES6 module
,必须明确使用后缀 .cjs
也就是 CommonJS
方式加载。
ReferenceError: module is not defined in ES module scope
Vite/Vue3
项目package.json
属性type: 'module'
Vite 以 原生 ESM 方式提供源码,加载 .js
文件默认使用 ESM 方式。且注意 Vite 的 CJS Node API 构建已经被废弃,并将在 Vite 6 中移除。
PS
整理上述内容时,不同文档有如下三种叫法,其实是一个东西,请注意!
ESM
ES Modules
ES6 Module