持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
前置知识:ESM、CommonJS、UMD等模块化知识
在以前的node中,模块化主要使用的CommonJS.而在浏览器中,我们常常使用ESM.这两种模块化本质上有很多区别,这就导致同一个包用在不同的环境中需要修改代码,当然UMD也是解决了这个问题,但是他不在本文的讨论范围之中。
node的模块化
在node中,我们一般会这样写
//引入模块
const moduleA = require('xxx')
//导出模块
module.exports = 'xxxx'
这种就属于CommonJS,CommonJS有如下特点
- 按文件隔离。 所有代码都运行在模块作用域,不会污染全局作用域。
- 缓存性。 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
- 顺序加载。 模块加载的顺序,按照其在代码中出现的顺序。
其实,在我看来,CommonJS更像时浏览器最初没有模块的时候,但是加上了文件隔离,以避免污染。比如在jquery时代,我们会这样引入js
<script src="jquery1.1.8.min.js"><script>
<script src="jquery-xxx.js"><script>
<script src="main.js"><script>
先引入jquery,再引入那些jquery插件,最后才是我们自己的代码
ESM
ESM全名ECMAScript Module,其实就是我们现在用的最多的模块化。
//引入模块
import moduleA from 'xxx'
//导出模块
export.default 'xxxx'
这就是ESM,同时他还有export,exports 这些关键字
//导出模块
export const a = 'xxx'
//引入模块
import {a} from './a'
ESM最大的好处是可以静态分析去做treeShake优化。
node中使用
首先你需要确定你的node版本比较新,通过在命令行里输入node -v确定。笔者的版本是14.18,个人建议版本至少大于12.x
- 更改文件名后缀,将
.js改为.mjs package.json["type"]字段改为module- 执行node文件时加入参数
--input-type,例如node index.js --input-type=module
注意事项
-
使用ESM后,有些模块的引入的方式变了。 如果你不确定这个包是ESM还是CommonJS,可以这样试一下
import * as A from 'AA' -
__dirname不存在了
在node的ESM中并不存在这个常量,你需要这样处理一下
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename)