node.js系列-多种方案教你在node程序中同时使用CommonJS 和 ES Module 混合开发最佳实践

news2025/1/17 23:07:44

前情提要

我们平时使用的npm 第三方包一般基于这两种规范开发的,很容易遇到一个项目里既有 CommonJS 又有 ES Module 的情况,那么我们应该如何解决这种CommonJS 和 ES Module 混合开发的问题呢?

CommonJS是什么?

  • 2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。这标志"Javascript模块化编程"正式诞生。在服务器端,需要有模块,与操作系统和其他应用程序互动。
  • CommonJS 是为了提供一个类似Python,Ruby和Java标准库,让开发者可以使用CommonJS API编写应用程序,可以运行在不同的JavaScript解释器和不同的主机环境中。
  • NodeJS,webpack 我们通常会以CommonJS的形式来书写。

CommonJS可以开发以下程序:

(1)、服务器端JavaScript应用程序
(2)、命令行工具
(3)、图形界面应用程序
(4)、混合应用程序(如,Titanium或Adobe AIR)

代码形式

通俗大白话,特点就是: 使用require关键词来引入依赖,举个例子:

const path = require('path')
const AutoLoad = require('@fastify/autoload')

以及 module.exports

module.exports = async function (fastify, opts) {
  fastify.get('/', async function (request, reply) {
    return 'this is an example'
  })
}

ES module是什么?

ES Modules(ESM)是用于处理模块的 ECMAScript 标准。 虽然 Node.js 长期使用 CommonJS 标准,但浏览器从未有过模块系统。 每个主要决策(如模块系统)必须首先由 ECMAScript 标准化,然后由浏览器实施。

ES modules(ESM) 是 JavaScript 官方的标准化模块系统。

ES 模块是如何运作的

当使用模块来开发的时候,会建立一个模块模块依赖图。不同依赖之间联系来自于你使用的任何 import 语句。

区别

  • CommonJS 按需加载,可以动态加载、条件加载、循环加载
  • ESM 静态加载,方便解析依赖,优化运行效率。 import() 目前也可以动态加载
  • CommonJS 模块输出值的拷贝,ESM输出值的引用。
  • CommonJS 运行时加载,ESM编译时输出接口。
  • CommonJS 模块的require()同步加载,ESM的import异步加载,有独立模块依赖解析阶段。
  • ESM的import会提升,变量const只读。

区别举例

在CommonJS中我们可以直接使用__dirname,就像下面这样:

fastify.register(AutoLoad, {
    dir: path.join(__dirname, 'plugins'),
    options: Object.assign({}, opts)
  })

但是在ESM中不再支持,我们需要改为

import {dirname} from 'path';
import { fileURLToPath } from 'url';

function getDirname(url) {
  const __filename = fileURLToPath(url);
  return dirname(__filename);
}

解决方案

方案1:按照 ES Module 规范,指定 “type”

单独指定某些文件使用 CommonJS 模块,或者ES Module 模块

  • 正常情况下,我们不做配置的话,项目默认是 CommonJS 规范
  • 在 package.json 文件中指定 “type”:“module” 后,就会按照 ES Module 规范
  • 强制的指定文件后缀为 .cjs后,此文件会遵守CommonJS 规范


ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'test/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
ReferenceError: 在 ES 模块范围中没有定义要求,您可以使用 import 代替
这个文件被视为 ES 模块,因为它有一个’。Js 的文件扩展名和‘ test/package.json’包含“ type”: “ module”。若要将其视为 CommonJS 脚本,请将其重命名为使用’。Cjs 的文件扩展名。

“type”:"module"情况下,如何解决这个报错呢?

我们可以单独给某个文件设置后缀名来使用CommonJS 脚本,强制的指定文件后缀为 .cjs

方案2:按照CommonJS 规范,不做任何配置情况下

指定需要使用ES Module 的文件的后缀名为 .mjs,那么这个文件会被强制指定使用 ES Module 规范

方案3:使用 Babel 完美配置 CommonJS 和 ES Module 随心使用(这个目前有更新的配置方案,等我忙完了写到方案4,方案3也可以用哦)

安装依赖

npm install --save-dev babel-cli babel-preset-env babel-register babel-preset-stage-0 
npm install --save babel-polyfill # babel转码时不能识别一些全局对象的API,例如Object.assign,使用它可以解决这个问题
  • babel-polyfill babel转码时不能识别一些全局对象的API
  • babel-preset-stage-0 es阶段性提案语法 stage-0 包含stage1,2,3
  • babel-register 钩子,在程序入口文件引入即可实现转码

在根目录新建 .babelrc

{
    "presets": [
      "env",
      "stage-0"
    ]
  }

配置命令入口,在根目录新建 main.js

require('babel-polyfill');
require('babel-register');
require('./app.js'); // 引入您的项目的启动文件

配置命令行

package.json中加入

"scripts": {
    "start": "node main.js",
  },

启动项目

npm start

大功告成,接下来项目内写任何类型都不会有问题

方案4:等我忙完了,继续补充,确实有更好的方式,可以使用更少的依赖

  • 今天就写到这里啦~
  • 小伙伴们,( ̄ω ̄( ̄ω ̄〃 ( ̄ω ̄〃)ゝ我们明天再见啦~~
  • 大家要天天开心哦

欢迎大家指出文章需要改正之处~
学无止境,合作共赢

在这里插入图片描述

欢迎路过的小哥哥小姐姐们提出更好的意见哇~~

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

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

相关文章

C++学习笔记总结练习--容器

容器 1 简介 新标准库的容器壁使用原始的数组实现的数据结构要快很多。经过了精心的优化。 确定使用哪种容器 除非有明确的理由,否则使用vector随机元素访问vector或deque容器中间插入或者插入元素list、forward_list头尾插入元素,使用deque可以在输入…

RelativeSource有四种类型

Self FindAncestor TemplatedParent PreviousData a.Self Self用于绑定源和绑定目标相同的场景中。对象的一个属性与同一对象的另一个属性绑定。 例如&#xff0c;让我们取一个高度和宽度相同的椭圆。在XAML文件中添加下面给出的代码。宽度属性与高度属性相对绑定。 <G…

Stephen Wolfram:“足够大的网络肯定能做任何事!”

“Surely a Network That’s Big Enough Can Do Anything!” “足够大的网络肯定能做任何事&#xff01;” The capabilities of something like ChatGPT seem so impressive that one might imagine that if one could just “keep going” and train larger and larger neura…

【Kubernetes】Kubernetes的部署

kubernetes 一、Kubernetes 的安装部署1. 常见的安装部署方式1.1 Minikube1.2 Kubeadm1.3 二进制安装部署 2. K8S 部署 二进制与高可用的区别2.1 二进制部署2.2 kubeadm 部署 二、Kubernetes 的部署过程1. 二进制部署1.1 服务器相关设置以及架构1.2 操作系统初始化配置1.3 部署…

【前端|Javascript第1篇】一文搞懂Javascript的基本语法

欢迎来到JavaScript的奇妙世界&#xff01;作为前端开发的基石&#xff0c;JavaScript为网页增色不少&#xff0c;赋予了静态页面活力与交互性。如果你是一名前端小白&#xff0c;对编程一无所知&#xff0c;或者只是听说过JavaScript却从未涉足过&#xff0c;那么你来对了地方…

《探索文心千帆大模型平台: 代码编写从此变得轻松》

文章目录 前言一、初识文心千帆1.1 功能丰富1.2 注册登录 二、内置第三方大模型2.1 ERNIE-Bot模型2.2 ERNIE-Bot-turbo模型2.3 BLOOMZ-7B模型2.4 Llama模型全家桶2.5 在线体验2.5.1 代码编写能力简单提问复杂提问报错解决添加注释 2.5.2 逻辑判断先有鸡还是先有蛋&#xff1f;鸡…

CTF-MISC:BUUCTF练习汇总(26-31题)

CTF-MISC&#xff1a;BUUCTF练习汇总 26、后门查杀27、webshell后门28、来首歌吧29、荷兰宽带数据泄露30、面具下的flag31、九连环 26、后门查杀 解题思路&#xff1a;题干可知webshell的密码为flag&#xff0c;且下载的文件为网站源码&#xff0c;人工查找不太现实&#xff0…

【框架篇】Spring MVC 介绍及使用(详细教程)

Spring MVC 介绍 1&#xff0c;MVC 设计模式 MVC&#xff08;Model-View-Controller&#xff09;是一种常见的软件设计模式&#xff0c;用于将应用程序的逻辑分离成三个独立的组件&#xff1a; 模型&#xff08;Model&#xff09;&#xff1a;模型是应用程序的数据和业务逻辑…

微信小程序iconfont真机渲染失败

解决方法&#xff1a; 1.将下载的.woff文件在transfonter转为base64&#xff0c; 2.打开网站&#xff0c;导入文件&#xff0c;开启base64按钮&#xff0c;下载转换后的文件 3. 在下载解压后的文件夹中找到stylesheet.css&#xff0c;并复制其中的base64 4. 修改index.wxss文…

proj库配置与使用(window11,vs2019,x64)

前置安装依赖 1.SQLite3 安装 亲测 (97条消息) SQLite3源码下载与编译&#xff08;开发环境&#xff1a;Win10VS2022&#xff09;_sqlite3 下载_林夕07的博客-CSDN博客 2.TIFF 亲测 (97条消息) Win11下基于cmake-3.26.3 完美编译 TIFF-4.5.0源码_tiff 编译_GIS子枫的博客-C…

免费的ssl证书

免费的SSL证书对于保证网站的安全性和信任度来说是非常重要的。虽然有些人可能会认为&#xff0c;免费的SSL证书可能不如付费的证书有效&#xff0c;但事实并非如此。 首先&#xff0c;免费的SSL证书同样能够为网站提供加密与解密的功能。这意味着所有的数据将会在传输过程中被…

【雷达通信】非相干多视处理(CSA)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

[JAVA基础]自动拆装箱NPE问题

1.自动拆装箱场景 自动装箱 当把字面量转换成包装类的时候会自动装箱 比如&#xff1a; Integer a 1; Integer b 1; 自动拆箱 当你对包装类的对象进行运算&#xff08;如加法、减法等&#xff09;时&#xff0c;Java会自动进行拆箱操作。拆箱是将包装类型的对象转换为相应的基…

JavaScript 面向对象

一、对象 1.新建一个对象 // An object literal with two key-value pairs let spaceship {Fuel Type: diesel,color: silver }; We separate each key-value pair in an object literal with a comma (,) Keys are strings, but when we have a key that does not have any…

真人AI写真的制作方法-文生图换脸

AI写真最近火起来了&#xff0c;特别是某款现象级相机的出现&#xff0c;只需要上传自己的照片&#xff0c;就能生成漂亮的写真照&#xff0c;这一产品再次带火了AI绘画。今天我就来分享一个使用Stable Diffusion WebUI制作真人AI写真的方法&#xff0c;不用训练&#xff0c;快…

专家论道: 唐贤香云纱塑造中国非遗国际品牌

自“香云纱染整技艺”入选第二批国家级非物质文化遗产以来&#xff0c;被誉为纺织界“软黄金”的香云纱&#xff0c;重新焕发青春&#xff0c;频频登上时尚舞台&#xff0c;以不一样的面貌展示在世人面前&#xff0c;成为服装设计师、消费者青睐的材质。而随着北京卫视播出的《…

【JAVA】 javaSE中的数组|数组的概念使用

数组的概念 什么是Java中的数组 数组&#xff1a;可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。在java中&#xff0c;包含6个整形类型元素的数组&#xff0c;可以看做是酒店中连续的6个房间. 1. 数组中存放的元素其类型相同 2. 数组的空间是连在一起的 3…

MySQL系统数据库及常用工具指令介绍

文章目录 1.系统数据库2.常用工具2.1 -e指令2.2 mysqladmin指令2.3 mysqlbinlog指令2.4 mysqlshow指令2.5 mysqldump指令 数据备份2.6 mysqlimport/source 指令 数据导入 3.指令小结 1.系统数据库 2.常用工具 2.1 -e指令 不用登陆mysql直接执行脚本命令 mysql -h192.168.200.…

一 关于idea如何在svn进行项目下载并运行成功

安装svn客户端 如图 安装时请选择该选项&#xff08;Will be installed on local hard drive&#xff09;并选择自己想要安装的目录路径 如图 svn安装成功 如图 注意 安装完成后&#xff0c;使用svn进行一次checkout的项目导出完成以上五步时&…

量化:numpy基础

文章目录 ndarray创建array创建顺序数组改变数据类型nan筛选元素去重重塑 ndarray numpy最重要的一个特点是其N维数组对象ndarry&#xff0c;它是一系列同类型数据的集合 创建array ndarry的创建方式如下&#xff1a; numpy.array(object, dtype None, copy True, order …