在 Node.js 中使用原生的 ES 模块
来源:互联网 发布:摄像头监控无网络视频 编辑:程序博客网 时间:2024/05/19 06:38
本文译自:Using ES modules natively in Node.js,原作者是 Dr. Axel Rauschmayer,圈内称之为"德国阮一峰"。
Node.js 从 8.5.0 开始原生支持 ES 模块,不过还需要通过命令行参数控制。这还得感谢 Bradley Farias 对这个新特性的贡献。
本文就给大家详细讲讲这个特性。
举个栗子
文件结构:
esm-demo/
lib.mjs
main.mjs
lib.mjs
:
exportfunctionadd(x, y) {
return x + y;
}
main.mjs
:
import {add} from'./lib.mjs';
console.log('Result: '+add(2, 3));
运行示例:
$ node --experimental-modules main.mjs
Result: 5
注意注意!
ES 的模块名称:
所有的模块名称都是 URL —— 这对 Node.js 来说引入了新的东西;
文件:最好使用相对的带
.mjs
后缀的路径来引用 ES 模块,这样可以保证对浏览器的兼容。如果不包含后缀名,则模块搜索方式与 CJS 保持一致。如果同时找到了.mjs
和.js
的文件,则使用.mjs
文件;例如:
../util/tools.mjs
类库模块:直接使用模块名,省略扩展名是最佳方式。这能与现阶段类库模块发布的方式保持最好的兼容;
例如:
lodash
如何让
node_modules
里的模块在浏览器里工作还有待研究(不使用 bundler 工具)。一种可选方案是引入类 RequireJS 的配置方式,将裸路径转换到真实路径上。就目前而言,裸路径的模块在浏览器是中是用不了的;
ES 模块的特性:
无法动态引入模块;但是很快就会引入动态操作符
import()
来实现;像
__dirname
和__filename
和这样的元变量将不再提供,有一个新的提案引入将会给 ES 模块提供类似的方式——Domenic Denicola 提出import.meta
。
console.log(import.meta.url);
与 CJS 模块的互操作性
ES 模块可以
import
CJS 模块,但是引入的模块只包含一个default
export——即module.exports
的值。已经开始计划让 CJS 模块输出具名 export(通过在文件开始加编译指令的方式),不过可能实现需要花一些时间。如果你想帮忙,看这里。
import fs1 from'fs';
console.log(Object.keys(fs1).length);// 86
import* as fs2 from'fs';
console.log(Object.keys(fs2));// ['default']
在 ES 模块中不能调用 require()
,主要是因为:
路径解析在两种规范中是很不一样的:ESM 不支持
NODE_PATH
和require.extensions
;它的模块标识符永远都是 URL,这会造成小小的区别;为了与浏览器保持最大的兼容性,ES 模块总是异步加载的。这种异步加载的方式与 CJS 通过
require()
同步加载的方式无法很好的在一起工作;同步模块的禁用同样也给在 ES 模块中使用顶级
await
关上了大门(一个目前正在考虑的特性);
CJS 无法 require()
ES 模块。原因与上一条提到的类似,同步加载异步的模块各种问题啊。不过也许可以通过 import()
来加载 ES 模块。
在老版本的 Node.js 上使用 ES 模块
好吧,如果你想在老的 Node.js 的使用 ES 模块,可以看看 John-David Dalton 的 @std/esm
。
小贴士:只要不使用 unlockables 特性,就可以保证与原生的 ES Module 完全兼容。
FAQ
什么时候可以不借助命令配置就可以使用 ES 模块?
目前的计划是,在 Node.js 10 LTS 版本中可以直接支持 ES 模块;
.mjs
在浏览器中可以工作么?
可以的,只需要提供正确的 Media Type( text/javascript
或者 application/javascript
)即可。.mjs
标准化和周边工具的升级正在进行中。
文件扩展名 .mjs
是 ES 模块所必须的么?
是的,对于 Node.js 来说是这样的。浏览器不在乎文件扩展名,只关心 Media Type。
为什么 Node.js 需要 .mjs
?
Node.js 本可以检查一个文件是 CJS 模块还是 ES 模块。在选择添加扩展名这个方案之前也讨论过多个其他方案。可以阅读本博的另外一篇了解。每种方案都有其优势和缺点。在我看来,.mjs
是正确的选择。
- 在 Node.js 中使用原生的 ES 模块
- 在 Cocos2d-js 中使用 Node.js 模块
- 在 Cocos2d-js 中使用 Node.js 模块
- 在 Cocos2d-js 中使用 Node.js 模块
- electron 使用原生node 模块
- 在Node.js使用mysql模块时遇到的坑
- node.js中express模块使用的疑难问题解决
- OpenGL ES 在 Android 中对 GLU 的原生支持
- 【Node.js基础篇】(二)Node模块的使用
- 在Express中使用html (Node.js)
- 在node中使用protobuf.js
- 在sublim 中 使用 node.js
- 在 Node.js 中使用C++
- 在node.js 中使用async await
- node.js中npm安装的模块在哪个目录下
- node.js 在使用child_process 模块时候,调试端口占用的问题解决方案(EADDRINUSE)
- Node中url模块的使用
- node.js中util模块
- 【Android】让Python在Android系统上飞一会儿
- Jmeter-Http接口测试过程及问题总结
- 谈谈HTTP协议中的短轮询、长轮询、长连接和短连接
- VIDE支持微信和支付宝小程序开发
- 一道题
- 在 Node.js 中使用原生的 ES 模块
- 创建学生成绩顺序表---
- Docker讲解
- 树莓派的硬件解码播放神器——Omxplayer
- 使用 styled-components 加速 React 开发
- Chrome 61 里的新玩意!
- Matlab 知识点总结
- ANSI Common Lisp译本笔记4
- Java数据结构与算法之数据结构-逻辑结构-集合(八)------Java集合类总结