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

前情提要

我们平时使用的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.mzph.cn/news/19580.shtml

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

相关文章

MySQL主从复制原理以及实操

一、MySQL主从复制原理: 1、MySQL将数据变化记录到二进制日志中; 2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中; 3、Slave将中继日志中的事件在做一次,将数据变化,反应到自身(Slave)的数…

c++ / python / java / PHP / SQL / Ruby / Objective-C / JavaScript 发展史

c发展史 C是由丹尼斯里奇和肯汤普森在1970年代早期开发的C语言的扩展。C最初被称为“C with Classes”,是在1980年代初期由比雅尼斯特劳斯特鲁普开发的。 1983年,斯特劳斯特鲁普将C with Classes重新命名为C。在1985年,C编译器的第一个版本被…

【Linux】常用的基本指令

👦个人主页:Weraphael ✍🏻作者简介:目前正在学习c和算法 ✈️专栏:Linux 🐋 希望大家多多支持,咱一起进步!😁 如果文章有啥瑕疵,希望大佬指点一二 如果文章对…

C# Microsoft消息队列服务器的使用 MSMQ

先安装消息队列服务器 private static readonly string path ".\\Private$\\myQueue";private void Create(){if (!MessageQueue.Exists(path)){MessageQueue.Create(path);}}private void Send(){Stopwatch stopwatch new Stopwatch();stopwatch.Start();Message…

RxJava 复刻简版之二,调用流程分析之案例实现

接上篇:https://blog.csdn.net/da_ma_dai/article/details/131878516 代码节点:https://gitee.com/bobidali/lite-rx-java/commit/05199792ce75a80147c822336b46837f09229e46 java 类型转换 kt 类型: Any Object泛型: 协变: …

web基础与http

一,dns与域名 网络基于tcp/ip协议进行通信和连接的,其中主机以ip地址做固定的地址标识,用以区分用户和计算机。ip地址是由32位二进制数组成,不方便记忆。为了方便记忆,采用了域名。但是网络通信的唯一标识是ip地址&…

K8s的详细介绍

1.编写yaml文件的方式 2.yaml里面的内容介绍 Pod实现机制:(1)共享网络(2)共享存储 共享网络:通过Pause容器,把其他业务容器加入到Pause容器里面,让所有业务容器在同一个名称空间中,…

【Spring Cloud 三】Eureka服务注册与服务发现

系列文章目录 【Spring Cloud一】微服务基本知识 Eureka服务注册与服务发现 系列文章目录前言一、什么是Eureka?二、为什么要有服务注册发现中心?三、Eureka的特性四、搭建Eureka单机版4.1Eureka服务端项目代码pom文件配置文件启动类启动项目查看效果 E…

海量小文件传输慢的原因以及对应的优化方案

在日常工作中,我们经常遇到需要传输一些小文件的情况,但是当小文件的数量很多的时候,为什么小文件传输的速度就会变得很慢呢?为什么复制许多较小的文件时,小文件传输效率就会降低呢?针对这些问题&#xff0…

Mybatis插件

文章目录 1. 如何自定义插件1.1 创建接口Interceptor的实现类1.2 配置拦截器1.3 运行程序 2. 插件原理2.1 解析过程2.2 创建代理对象2.2.1 Executor2.2.2 StatementHandler2.2. 3ParameterHandler2.2.4 ResultSetHandler 2.3 执行流程2.4 多拦截器的执行顺序 3. PageHelper3.1 …

聊天系统登录后端实现

定义返回的数据格式 # Restful API from flask import jsonifyclass HttpCode(object):# 响应正常ok 200# 没有登陆错误unloginerror 401# 没有权限错误permissionerror 403# 客户端参数错误paramserror 400# 服务器错误servererror 500def _restful_result(code, messa…

Matlab Optimization Toolbox中的遗传算法工具包(GA)

matlab optimization 中使用了GA求解器 默认的是小于等于 找到GA 工具包 找到 APP选择 Optimization Tool 选择Solver ga - Genetic Algorithm 应用GA solver 定义适应度函数(Fitness function)与问题约束(Constraints) example one 优化函数 sin(x) 2 * cos(x)极其重要的…

windows10 设置代理

场景:同一个办公室,只有A的电脑有权限访问网站 http://10.129.129.129:5601, 那办公室其他B,C同学想访问 http://10.129.129.129:5601,需要怎么处理? A 同学电脑安装代理软件: 1. 下载wproxy IMFirewall, …

iMX6ULL驱动开发 | 让imx6ull开发板支持usb接口FC游戏手柄

手边有一闲置的linux开发板iMX6ULL一直在吃灰,不用来搞点事情,总觉得对不住它。业余打发时间就玩起来吧,总比刷某音强。从某多多上8块儿大洋买来一个usb接口的游戏手柄,让开发板支持以下它,后续就可以接着在上面玩童年…

信息学奥赛一本通——1258:【例9.2】数字金字塔

文章目录 题目【题目描述】【输入】【输出】【输入样例】【输出样例】 AC代码 题目 【题目描述】 观察下面的数字金字塔。写一个程序查找从最高点到底部任意处结束的路径,使路径经过数字的和最大。每一步可以从当前点走到左下方的点也可以到达右下方的点。 在上面…

VS2019编译安装OpenMesh8.0

文章目录 一、简介二、相关准备三、编译安装四、举个栗子参考资料一、简介 多边形网格一直以来就是交互式3D图形应用程序中最合适的几何表示,它们足够灵活,可以近似任意形状,并且可以通过当前的图形硬件有效地处理,即使在今天的低成本电脑上也是如此。OpenMesh便是其中一种…

Java-很深我只知其一-泛型

Java-很深我只知其一-泛型 目录 泛型历史 泛型类/泛型接口 泛型方法 泛型属性 泛型约束 泛型历史 JAVA 泛型(generics)是 JDK 5 中引入的一个新特性, 允许程序员在编程时指定类型参数,使编译器可以在编译代码时检测到非法的类型。泛型的…

相交链表 LeetCode热题100

题目 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 题目数据 保证 整个链式结构中不存在环。 思路 使用两个指针x,y同时遍历两个链表A和B。 当两个链表有相交节点时&am…

小研究 - 主动式微服务细粒度弹性缩放算法研究(四)

微服务架构已成为云数据中心的基本服务架构。但目前关于微服务系统弹性缩放的研究大多是基于服务或实例级别的水平缩放,忽略了能够充分利用单台服务器资源的细粒度垂直缩放,从而导致资源浪费。为此,本文设计了主动式微服务细粒度弹性缩放算法…

Centos安装libwebcam库运行 uvcdynctrl 命令

Centos 软件包仓库中没有 libwebcam 库,因此需要下载源文件手动编译 源文件地址:https://github.com/lucasrangit/libwebcam 解压后进入项目文件夹 mkdir build cd build cmake .. make make install 如果使用uvcdynctrl提示找不到库,则 vi…