Node.js中CommonJS和ECMAScript有什么区别()
一、CommonJS 与 ECMAScript 1、概念说明
- CommonJS 与 ECMAScript 都是编写 JS 的标准。
- ECMAScript 标准让不同浏览器上执行相同 js 代码能得到相同结果,是现有 js语言 的通用标准。
- CommonJS 标准让相同 js 代码在 Node.js 环境下运行得到相同结果,只是 Node.js 下的标准。
.js
、.mjs
、.cjs
。.mjs
:此类文件只用能 ECMAScript 标准解析执行;.cjs
:此类文件只用能 CommonJS 标准解析执行;.js
: 根据具体情况决定,采用什么标准来执行:
- 情况1:如果
.js
没有其他特殊说明,默认使用 CommonJS 标准解析执行; - 情况2:
package.json
文件中 type 属性值为缺省值 或 等于commonjs
,那么采用 CommonJS 标准解析执行.js
文件;如果 type 属性等于module
,那么采用 ECMAScript 标准解析执行.js
文件。 - 情况3:命令行中有flag ,
--input-type=module
表示采用 ECMAScript 标准解析执行.js
文件;--input-type=commonjs
表示采用 CommonJS 标准解析执行.js
文件。
node --input-type=module --eval "import { sep } from 'path'; console.log(sep); "echo "import { sep } from 'path'; console.log(sep); " | node --input-type=module
- 情况1:如果
require
只能导入 CommonJS 标准文件;import
支持两种标准的文件导入。
一个js文件
被看做一个 模块
,譬如下面 circle.js
就是一个模块,导出两个方法。// circle.js
const { PI } = Math;
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;
2、导入模块 在另一个 js文件中使用
circle.js
模块的方法,实现代码重用。// foo.js
const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);
三、ECMAScript 标准的简单示例 1、写个模块
// addTwo.mjs
function addTwo(num) {
return num + 2;
}export { addTwo };
2、导入模块
// app.mjs
import { addTwo } from './addTwo.mjs';
// Prints: 6
console.log(addTwo(4));
四、导入模块的方式 1、require require 只能被用来加载 CommonJS 模块。
/home/ry/projects/foo.js
文件加载其它模块的方式如下:// foo.js
const circle1 = require('./circle.js');
const circle2 = require('../circle.js');
const circle3 = require('/home/marco/circle.js');
const circle4 = require('circle');
const circle5 = require('./some-library');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);
寻找导入模块的方法说明:
./circle.js
:在foo.js
所在文件夹下,去寻找加载circle.js
../circle.js
:在foo.js
所在文件夹的上一层文件夹,去寻找加载circle.js
/home/marco/circle.js
: 按照这个绝对路径,去寻找加载circle.js
circle
:先从 Node.js 内置模块去寻找加载,没有再去node_modules
文件夹下寻找circle
模块,且会一直向上一层文件夹寻找,如下
/home/ry/projects/node_modules/circle.js /home/ry/node_modules/circle.js /home/node_modules/circle.js /node_modules/circle.js
./some-library
:先从项目根目录寻找package.json
,再去foo.js
所在文件夹下,寻找两个index模块,没有就返回Error: Cannot find module 'some-library'
// 1、package.json 寻找如下内容 { "name" : "some-library", "main" : "./lib/some-library.js" }// 2、查找是否有 index.js 模块 ./some-library/index.js// 3、查找是否有 index.node 模块 ./some-library/index.node
CommonJS 模块
和ECMAScript 模块
都可以用import
来导入,三种使用方式
// 相对路径 import { sep } from './startup.js' import { sep } from './config.mjs'// 绝对路径 import { sep } from '/home/project/startup.js' import { sep } from '/home/project/startup.mjs'// 模块名,寻找模块的方式与require一样 import { sep } from 'some-package'
import.meta.url
:表示模块的绝对URL
// 通过模块绝对url,来读取相对路径的文件 import { readFileSync } from 'fs'; const buffer = readFileSync(new URL('./data.proto', import.meta.url));
// CommonJS 动态导入
import('/modules/my-module.js')
.then((module) => {
// Do something with the module.
});
// ECMAScript 动态导入
import('/modules/my-module.mjs')
.then((module) => {
// Do something with the module.
});
五、示例:选择解析标准 如果 Node.js 项目根目录有
my-app.js
和 package.json
两个文件,那么终端启动项目 node my-app.js
,各个模块会以什么标准被导入?// /home/project/my-app.js
// my-app.js 会以 ES 标准导入,因为同文件夹 package.json 中的 type 属性所致。// 如果startup目录下没有 package.json,那么使用上一层目录中package.json的设置
// 即 用 ES 标准导入init.js
import './startup/init.js';
// 根据 ./node_modules/commonjs-package/package.json 中type属性值
// 缺省 就用 commonjs 标准,否则就按照属性值标准。
import 'commonjs-package';
// 根据 ./node_modules/commonjs-package/package.json 中type属性值
// 缺省 就用 commonjs 标准,否则就按照属性值标准。
import './node_modules/commonjs-package/index.js';
// /home/project/package.json
{
"type": "module",
}
六、其他补充 1、其他文件
- 如果模块没有被找到,系统会尝试其他后缀的文件,分别为:
.js
,.json
, and finally.node
.
- 第一次调用
require('foo')
后,模块对象会被缓存,后面再调用require('foo')
只会返回被缓存的对象,不会重复加载。
- 内置模块优先级最高。使用
require('http')
时,就算有相同的js模块名http.js
也会被忽略,而使用内置模块 http,当然,可以用require('node:http')
方式,让代码更易于理解。
(function(exports, require, module, __filename, __dirname) {
// 实际模块代码,在这里
});
5、ECMAscript 标准中使用
require
【Node.js中CommonJS和ECMAScript有什么区别()】创建 example.mjs
文件,此后缀文件是 ECMAscript 标准,所以无法直接使用 require,但可以用Node.js 的内置模块 Module
来实现 require。// example.mjs
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
// sibling-module.js is a CommonJS module.
const siblingModule = require('./sibling-module');
七、参考文档
- Node.js中CommonJS和ECMAScript有什么区别?
推荐阅读
- 热闹中的孤独
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募
- 2020-04-07vue中Axios的封装和API接口的管理