commonjs vs ES module in Node.js

news2024/11/24 16:04:45

nodejs.png
在现代软件开发中,模块将软件代码组织成独立的块,这些块共同构成了更大、更复杂的应用程序。

在浏览器 JavaScript 生态系统中,JavaScript 模块的使用依赖于importexport语句;这些语句分别加载和导出 EMCAScript 模块(或 ES 模块)。

ES 模块格式是打包 JavaScript 代码以供重用的官方标准格式,大多数现代 Web 浏览器都原生支持这些模块。
然而,Node.js 默认支持 CommonJS 模块格式。 CommonJS 模块使用require()加载,变量和函数使用module.exports 从 CommonJS 模块导出。

随着 JavaScript 模块系统的标准化,ES 模块格式在 Node.js v8.5.0 中被引入。作为一个实验模块,—experimental-modules 标志是在 Node.js 环境中成功运行 ES 模块所必需的。

但是,从 13.2.0 版本开始,Node.js 已经稳定支持 ES 模块。

本文不会过多地介绍这两种模块格式的用法,而是介绍 CommonJS 与 ES 模块的比较以及为什么你可能想要使用其中一种。

比较 CommonJS 模块和 ES 模块语法

默认情况下,Node.js 将 JavaScript 代码视为 CommonJS 模块。正因为如此,CommonJS 模块的特点是模块导入的require() 语句和模块导出的module.exports 语句。

例如,这是一个导出两个函数的 CommonJS 模块:

// util.js
module.exports.add = function(a, b) {
  return a + b;
} 

module.exports.subtract = function(a, b) {
  return a - b;
} 

我们还可以使用require() 将公共函数导入到另一个 Node.js 脚本中,就像我们在这里所做的那样:

const { add, subtract } = require('./util');

console.log(add(5, 5)); // 10
console.log(subtract(10, 5)); // 5

如果你正在寻找关于 CommonJS 模块的更深入的教程,请阅读其他相关文章。

另一方面,库作者也可以通过将文件扩展名从.js 更改为.mjs 来简单地在 Node.js 包中启用 ES 模块。
例如,这是一个简单的 ES 模块(带有 .mjs 扩展名)导出两个函数供公共使用:

// util.mjs
export function add(a, b) {
  return a + b;
}

export function subtract(a, b) {
  return a - b;
}

然后我们可以使用import 语句导入这两个函数:

// app.mjs
import { add, subtract } from './util.mjs';

console.log(add(5, 5)); // 10
console.log(subtract(10, 5)); // 5

在项目中启用 ES 模块的另一种方法是在最近的package.json 文件(与你正在制作的包相同的文件夹)中添加一个"type": "module"字段:

{
  "name": "my-library",
  "version": "1.0.0",
  "type": "module",
  // ...
}

有了这个包含,Node.js 将该包内的所有文件都视为 ES 模块,你不必将文件更改为.mjs 扩展名。

或者,你可以安装并设置一个像 Babel 这样的转译器来将你的 ES 模块语法编译成 CommonJS 语法。 React 和 Vue 等项目支持 ES 模块,因为它们在后台使用 Babel 来编译代码。

在 Node.js 中使用 ES 模块和 CommonJS 模块的优缺点

ES 模块是 JavaScript 的标准,而 CommonJS 是 Node.js 中的默认
ES 模块格式的创建是为了标准化 JavaScript 模块系统。它已成为封装 JavaScript 代码以供重用的标准格式。

另一方面,CommonJS 模块系统内置于 Node.js 中。在 Node.js 中引入 ES 模块之前,CommonJS 是 Node.js 模块的标准。因此,有大量使用 CommonJS 编写的 Node.js 库和模块。

对于浏览器支持,所有主流浏览器都支持 ES 模块语法,你可以在 React 和 Vue.js 等框架中使用import/export。这些框架使用像 Babel 这样的转译器将import/export语法编译为require(),旧的 Node.js 版本原生支持。

除了作为 JavaScript 模块的标准之外,ES 模块语法与require() 相比也更具可读性。由于语法相同,主要在客户端编写 JavaScript 的 Web 开发人员在使用 Node.js 模块时不会有任何问题。

Node.js 对 ES 模块的支持

⚠️ 提醒:旧的 Node.js 版本不支持 ES 模块

虽然 ES 模块已经成为 JavaScript 中的标准模块格式,但开发人员应该考虑到旧版本的 Node.js 缺乏支持(特别是 Node.js v9 及以下版本)。

换句话说,使用 ES 模块会使应用程序与仅支持 CommonJS 模块(即require()语法)的早期版本的 Node.js 不兼容。

但是有了新的条件导出,我们可以构建双模式库。这些库由较新的 ES 模块组成,但它们也向后兼容旧 Node.js 版本支持的 CommonJS 模块格式。

换句话说,我们可以构建一个同时支持importrequire()的库,从而解决不兼容的问题。

考虑以下 Node.js 项目:

my-node-library
├── lib/
│   ├── browser-lib.js (iife 格式)
│   ├── module-a.js  (commonjs 格式)
│   ├── module-a.mjs  (es6 module 格式)
│   └── private/
│       ├── module-b.js
│       └── module-b.mjs
├── package.json
└── …

package.json 中,我们可以使用exports字段以两种不同的模块格式导出公共模块(module-a),同时限制对私有模块(module-b)的访问:

// package.json
{
  "name": "my-library",         
  "exports": {
    ".": {
      "browser": {
        "default": "./lib/browser-module.js"
      }
    },
    "module-a": {
      "import": "./lib/module-a.mjs" 
      "require": "./lib/module-a.js"
    }
  }
}

通过提供有关我们的my-library 包的以下信息,我们现在可以在任何支持它的地方使用它,如下所示:

// CommonJS 
const moduleA = require('my-library/module-a')

// ES6 Module
import moduleA from 'my-library/module-a'

// 这里不会生效
const moduleA = require('my-library/lib/module-a')
import moduleA from 'my-awesome-lib/lib/public-module-a'
const moduleB = require('my-library/private/module-b')
import moduleB from 'my-library/private/module-b'

由于exports中的路径,我们可以在不指定绝对路径的情况下import(和require())我们的公共模块。

通过包含.js.mjs的路径,我们可以解决不兼容的问题;我们可以为浏览器和 Node.js 等不同环境映射包模块,同时限制对私有模块的访问。

较新的 Node.js 版本完全支持 ES 模块

在大多数较低的 Node.js 版本中,ES 模块被标记为实验性的。这意味着该模块缺少一些功能并且落后于--experimental-modules标志。较新版本的 Node.js 确实对 ES 模块提供了稳定的支持。

然而,重要的是要记住,对于 Node.js 将模块视为 ES 模块,必须发生以下情况之一:模块的文件扩展名必须从 .js(对于 CommonJS)转换为.mjs(对于 ES 模块)或者我们必须在最近的package.json文件中设置一个{"type": "module"}字段。

在这种情况下,该包中的所有代码都将被视为 ES 模块,并且应该使用import/export语句而不是require()

CommonJS 提供模块导入的灵活性

在 ES 模块中,只能在文件开头调用import语句。在其他任何地方调用它会自动将表达式移动到文件开头,甚至可能引发错误。

另一方面,将require()作为函数,在运行时进行解析。因此,可以在代码的任何位置调用require(。你可以使用它从if语句、条件循环和函数中有条件地或动态地加载模块。

例如,你可以在条件语句中调require(),如下所示:

if(user.length > 0){
  const userDetails = require('./userDetails.js');
  // Do something ..
}

在这里,我们仅在用户存在时才加载名为 userDetails 的模块。

CommonJS 加载模块是同步的,ES 模块是异步的

使用require()的限制之一是它会同步加载模块。这意味着模块被一个接一个地加载和处理。

正如你可能已经猜到的那样,这可能会给包含数百个模块的大型应用程序带来一些性能问题。在这种情况下, import的性能可能优于require()基于其异步行为。

然而,对于使用几个模块的小规模应用程序来说,require()的同步特性可能不是什么大问题。

结语:CommonJS 还是 ES 模块?

对于仍在使用旧版本 Node.js 的开发人员来说,使用新的 ES 模块是不切实际的。

由于粗略的支持,将现有项目转换为 ES 模块会使应用程序与仅支持 CommonJS 模块(即require()语法)的早期版本的 Node.js 不兼容。

因此,将你的项目迁移到使用 ES 模块可能不是特别有益。

作为初学者,了解 ES 模块可能是有益和方便的,因为它们正在成为用 JavaScript 为客户端(浏览器)和服务器端(Node.js)定义模块的标准格式。

对于新的 Node.js 项目,ES 模块提供了 CommonJS 的替代方案。 ES 模块格式确实提供了一种编写同构 JavaScript 的更简单途径,它可以在浏览器或服务器上运行。

总之,EMCAScript 模块是 JavaScript 的未来 🎉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/185211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java SSM (springboot+mybatis)美食菜谱分享平台系统设计和实现以及论文报告

Java SSM (springbootmybatis)美食菜谱分享平台系统设计和实现以及论文报告 博主介绍:5年java开发经验,专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收…

DNS的解析,查询,调度原理是什么?什么是DNS劫持,污染?如何监控?

DNS的核心工作就是将域名翻译成计算机IP地址, 它是基于UDP协议实现的,本文将具体阐述DNS相关的概念,解析,调度原理(负载均衡和区域调度)等DNS相关的所有知识点DNS简介域名系统并不像电话号码通讯录那么简单&#xff0c…

LeetCode 91. 解码方法 120. 三角形最小路径和 97. 交错字符串 131. 分割回文串 132. 分割回文串 II

🌈🌈😄😄 欢迎来到茶色岛岛屿,本文带来的是LeetCode 91. 解码方法 120. 三角形最小路径和 97. 交错字符串 131. 分割回文串 132. 分割回文串 II 🌲🌲🐴🐴 91. 解码方法…

意图识别和文本分类(六)

一、分类的目的和分类的方法 目标 能够说出项目中进行文本的目的能够说出意图识别的方法能够说出常见的分类的方法 1.1 文本分类的目的 回顾之前的流程,我们可以发现文本分类的目的就是为了进行意图识别 在当前我们的项目的下,我们只有两种意图需要被…

算法刷题打卡第75天:合并两个链表

合并两个链表 难度:中等 给你两个链表 list1 和 list2 ,它们包含的元素分别为 n 个和 m 个。 请你将 list1 中下标从 a 到 b 的全部节点都删除,并将 list2 接在被删除节点的位置。 下图中蓝色边和节点展示了操作后的结果: 请你…

php debug yasd手记

yasd 调试器 v0.2.5 版本发布,支持 PHP8 以及在 IDE 中使用调试 - 知乎 GitHub - swoole/yasd: Yet Another Swoole Debugger 安装 yasd 在编译安装之前你需要安装boost库。 macOS: brew install boostUbuntu: apt-get install libboos…

Python编程 装饰器

作者简介:一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭:低头赶路,敬事如仪 个人主页:b网络豆的主页​​​​​​ 目录 前言 一.函数 1.装饰器引入 (1)时间模块 封装函数&am…

软件测试简历没有邀约,为什么?8类细节通通告诉你(附赠高薪简历)

求职不顺,没有邀约,大概率是你的简历出现了问题。本篇文章列出高薪简历应该注意的细节,合计36处,涉及简历的八大组成部分。现在就讲。一、简历样式要求(3点要求)1、简历格式,推荐使用PDF格式的简…

shopee、lazada跨境电商产品定位和快速获取流量来源是什么?

曹哥首先说的是产品的定位的思路 当确定好具体的经营类目后,就需要去给店铺的商品进行架构分类,一般分为3类,分为爆款,引流款,利润款 关于爆款主要指那些流量高,转化率高,销量高,但…

51单片机学习笔记-9蜂鸣器

9 蜂鸣器 [toc] 注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。 注:工程及代码文件放在了本人的Github仓库。 9.1 蜂鸣器简介 蜂鸣器 是一种将电信号转换为声音信号的器件,常用来产生…

Hystrix工作步骤说明以及服务监控hystrixDashboard

目录 一、步骤说明和流程解析 二、服务监控hystrixDashboard 官网:How it Works Netflix/Hystrix Wiki GitHub 一、步骤说明和流程解析 1 创建 HystrixCommand(用在依赖的服务返回单个操作结果的时候) 或 HystrixObserableCommand&am…

threadLocal的分享

问题描述:1、书城首页的书明明是广告解锁的,但是没有free标识,经过多次接口请求得出结论,相同的请求参数,有时会展示出free标识,有时不会展示free标识问题分析:1、长时间分析也没有得出结论&…

Linux用户及用户组知识总结

✅作者简介:热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:Java案例分…

SAP 供应商创建默认字段(屏幕格式)后台配置总结

供应商创建默认字段(屏幕格式)后台配置总结 供应商创建时默认字段(屏幕格式的配置在好几个地方的配置来控制。 一 、定义与采购组织特定的屏幕格式 (事务代码: OMFK) IMG路径为如下图: 在这里…

commons-beanutils的三种利用原理构造与POC

写在前面 commons-beanutils 是 Apache 提供的一个用于操作 JAVA bean 的工具包。里面提供了各种各样的工具类,让我们可以很方便的对bean对象的属性进行各种操作。其中比较常使用的有 MethodUtils/ConstructorUtils/PropertyUtils/BeanUtils/ConvertUtils等。 分析…

Python-文件、eval函数

1.文件的概念和作用1.1文件的概念和作用计算机的文件,就是存储在某种长期储存设备上的一段数据长期存储设备包括:硬盘、U盘、移动硬盘、光盘......文件的作用将数据长期保存下来,在需要的时候使用CPU内存 硬盘1.2文件的存储方式在计算机中&am…

机器视觉_HALCON_HDevelop用户指南_3.用HDevelop采集图像

文章目录三、用HDevelop采集/获取图像3.1. 从文件中读取图像3.2. 查看图像3.3. 图像采集助手3.3.1. 从文件或文件夹中获取图像3.3.2. 通过图像获取接口获取图像3.3.3. 修改生成的代码三、用HDevelop采集/获取图像 本章节标题的英文是Image Acquisition,直译是图像采…

微信小程序跳转页面三种方式

wx.navigateTo 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。 wx.navigateBack 关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面…

搜索入门技能树

搜索地址 以下哪个网址不能用来搜索: https://so.csdn.net/so/searchhttps://so.csdn.net/waphttps://devbit.csdn.net/searchhttps://dev.csdn.net/ 搜索频道 以下哪个不属于搜索频道: 全站博客下载图片 技能树 在搜索结果页展示的技能树模块中&am…

51单片机学习笔记-2数码管显示

2 数码管显示 [toc] 注:笔记主要参考B站江科大自化协教学视频“51单片机入门教程-2020版 程序全程纯手打 从零开始入门”。 注:工程及代码文件放在了本人的Github仓库。 2.1 静态数码管显示 2.1.1 原理介绍   LED数码管:数码管是一种简单…