- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章混乱是进步的阶梯 — ESM规范的崛起【上】由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
。
前端发展到如今,社区生态已经非常丰富.
在无数开源大神的努力下,很多前端开发的痛点(比如「静态类型检查」、「浏览器兼容性」)早已有了事实上的标准解决方案(比如TS、babel).
然而,在这繁荣之下,有一个日常开发不易感知的问题:
你可曾遇到过莫名其妙的bug,在多方搜资源,反复验证,耗费数个小时终于发现:
原来是某个包导出的是CJS,而项目使用ESM导致.
比如这个例子:记一次打包压缩报错[1] 。
如果你觉得这是个很容易发现的问题,再考虑结合上node_modules的层层依赖呢?
这个问题,揭开了模块化规范间斗争与博弈的冰山一角.
作为现代前端工程化的基石,模块化规范有太多值得深究的内容.
我会花几篇文章来讲解模块化规范。本文是第一篇,会围绕模块化规范的演进展开.
。
如果问十年前的前端最头疼的是什么?一定是浏览器兼容性.
随着babel等编译工具出现,兼容性逐渐被工程化方案解决(ES6+编译为ES5).
不仅是「兼容性」问题,DSL(如JSX、VUE的模版语法)、代码压缩、代码静态检查(TS)等日常开发的刚需都能在工程化方案中找到解决办法.
如果将当今繁荣的前端工程化生态比喻为一座大厦,那大厦的地基一定是「模块化规范」.
现代JS代码都是基于「模块化规范」组织起来,让我们从下往上来看看这座大厦:
规范的实现依赖于宿主环境,比如浏览器环境实现了EcmaScript Module(后文简称ESM)规范.
Node v12之前支持CommonJS(后文简称CJS)规范,12之后同时支持CJS与ESM.
在「宿主环境」之上,是基于模块化规范实现的「工具集」,比如webpack、vite、VScode生态.
再往上,基于「工具集」提供的API,可以实现各种工程化工具。比如:
再往上,就是开发者自己编写的业务代码.
开发者只需要在工具集中配置好工具,就能为业务代码提供服务。比如:
在VScode(工具集)中配置eslint(工具),就能在开发时获得相应提示 。
在webpack(工具集)中配置babel loader(工具),就能在开发时使用ES6+语法 。
可见,理想状态下,在开发者视角是不需要关注底层的「模块化规范」实现的.
。
然而,事物是动态发展的,模块化规范也不是一蹴而就的,让我们回到09年.
美国程序员「Ryan Dahl」创造了node.js项目,将JS用于服务端开发.
node.js使用CJS[2]标准作为模块化规范.
有了服务端模块规范(CJS),很自然的,JS开发者们想为客户端(主要是浏览器)提供一种模块化规范.
然而CJS是为服务端设计的.
在服务端,IO操作通常能迅速完成,所以CJS规范定义的:
这个流程是作为一个整体同步执行的.
然而在浏览器环境,「模块加载」(即数据请求)通常很耗时。有人曾作出一个形象的比喻:
如果一个CPU周期花费1秒完成,那么文件的网络请求需要花费4年.
显然浏览器端需要一种「支持异步」的模块化规范.
AMD(Asynchronous Module Definition 异步模块定义)规范,就是这样需求背景下的产物.
然而这些社区提出的规范终究只是为了解决一时的需求,随着历史的发展,新的模块化规范不断涌入、消亡.
直到ESM规范被提出.
ESM规范是ES标准的模块化规范,他的早期讨论可以追溯到2009年.
你可以在这里看到ESM规范的历史es-module-history[3] 。
ESM将模块规范分为三个阶段:
其中「模块加载」由宿主环境提供的loader完成(比如在浏览器环境,loader的行为由HTML规范[4]定义).
「模块实例化」与「模块执行」由ESM规范定义执行流程.
区别于CJS规范的同步执行,ESM规范将流程拆解为3个独立阶段.
「模块加载」同步、异步与否由宿主环境决定.
支持不同宿主环境,抹平多端差异、能力比其他规范都强大(后文会介绍)、再加上血统纯正(ES官方提出), 。
使得ESM规范一统前端「看似」指日可待.
然而,此时社区已经有大量基于CJS规范产出的开源包、组件,他们无法立刻切换到ESM规范.
所以,JS生态的现状是:会处于、并将长期处于CJS规范的库与ESM规范的库共存的状态.
但是最终,ESM规范一定会成为主导,毕竟他的优点太多(同样,后文会介绍).
。
当前模块化规范的混乱,对开源大佬们来说,就是机会.
为了让开发者将更多精力放在业务,而不是模块规范的适配上.
很多开源「工具集」都试图抹平模块化差异,比如:
一些「工具集」利用模块化规范的不同与其他竞品形成差异化竞争,比如:
其中,在浏览器环境中,Node的一些核心库(如events、stream、path...)会被打包成浏览器支持的版本.
依赖于大部分现代浏览器原生支持ESM规范,省去了打包的过程,使其编译速度大大提升.
严格支持ESM规范,并提供更好的静态分析,使rollup一度提供性能更优异的treeShaking能力.
成为更多库打包工具的首选.
与webpack这样的的大而全方案形成差异竞争.
。
可以看到,由于底层宿主环境对模块化规范支持的割裂,需要上层工具集来抹平模块规范的差异.
设想一个同时使用了webpack、babel、TS的项目.
这3个工具集都对多种模块规范有兼容处理。比如:
单独使用babel时,对于如下代码:
会被babel编译为:
ESM的「默认导出」会被编译为包含default属性的对象.
你可以打开babel playground[5]试试 。
当多个「工具集」在同一个项目中,为了各自目的做着同一件事(抹平模块化规范差异), 。
一旦工具链中某个插件配置有一丝丝不符合预期,或者引入了一个不符合预期的包,那么艰难的debug就此开始了...... 。
曙光即使当前有诸多不便,历史的进程是无法阻止的,那些被历史巨轮甩下并碾碎的模块化规范,会逐渐消失在开发者的视野中.
而赢家注定会通吃.
为什么ESM注定会成为最大赢家?他有什么无法比拟的优势?我们会在下篇文章揭晓.
。
[1]记一次打包压缩报错
https://cloud.tencent.com/developer/article/1650627 。
[2]CJS
http://wiki.commonjs.org/wiki/Modules/1.1 。
[3]es-module-history
https://gist.github.com/jkrems/769a8cd8806f7f57903b641c74b5f08a 。
[4]HTML规范
https://html.spec.whatwg.org/#fetch-a-module-script-tree 。
[5]babel playground
https://babeljs.io/repl 。
原文地址:https://mp.weixin.qq.com/s/eR_wx_WF18v-OKV2EkUiGA 。
最后此篇关于混乱是进步的阶梯 — ESM规范的崛起【上】的文章就讲到这里了,如果你想了解更多关于混乱是进步的阶梯 — ESM规范的崛起【上】的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
第一年+ 我已经使用 esm 和 std/esm 包编写了我所有的代码,我能够无缝地使用 cjs 的依赖包,没有问题,而不需要 babel。 在 nodejs V14 中,混合的 esm/cjs 支持
我在 plunker 中有以下代码... // Thing.js export class Thing{ constructor(){ console.log("This thing is
我尝试使用 --experimental-modules 标志在 Node.js v8.7.0 中使用此语法导入 ESM 模块: import { check, validationResult }
所以我正在使用包 esm 和 module-alias,但似乎 esm 没有注册模块别名的路径。 这是我加载服务器文件的方式: nodemon -r esm ./src/index.js 8081 这
我想将 typescript react 应用程序作为组件捆绑到 ES 模块或 UMD 中。但是生成的 ES 包会产生一个无效的模块 js。 在 bundle 上它给了我这个提示。但我找不到任何解决方
我很好奇 ESM 的 tree-shaking/死代码消除是如何工作的。我在各种 Node.js 项目中使用 Typescript,并开始导出自己的 ESM 包 (tsc --module es201
我正在构建一个 webpack 应用程序,我有兴趣在整个应用程序中使用 ESM,这意味着使用 ESM 导入构建 webpack.config 文件。 我现在可以使用 Babel,但这是在 npm 添加
我想我已经阅读了 SO 上的每个线程以及互联网上的每个相关页面,一切都有一些问题 我想: 使用 webpack 捆绑我的 web 应用程序 在我的源 js 中使用 ES 模块并将它们转换为更广泛的浏览
我即将在 SMPP 上工作。我对从计算机系统到移动站的消息如何传递有基本的了解,我已经阅读了有关消息如何从 ESME 到 SMSC 再到移动站的信息。但实际上我无法理解。我的意思是,这些 (ESME
我有以下示例运行,而 JS 在其上没有捆绑器。 // index.js ;(async () => { const mod = await import('/index.json') cons
在阅读 webpack 文档中有关 tree shaking 的内容时,我遇到了这句话: In a 100% ESM module world, identifying side effects is
在阅读 webpack 文档中有关 tree shaking 的内容时,我遇到了这句话: In a 100% ESM module world, identifying side effects is
我正在开发一个 SMS 网关,我在考虑我应该在其中实现的功能。因此,我查看了一些 SMS 网关(SMSNOW、SMS studio 和 Ozeki)作为示例。 我几乎完成了实现,但我遇到了几乎所有 S
我正在尝试在 ESM 模块上使用 tone.js。 (我可以在带有 bundler 的“commonjs”中毫无问题地使用它) 在我的html中 和 tests.js: import * as To
我正在尝试获取 Esri ArcGis's NPM package与 SvelteKit 一起工作。 根据链接文档,@arcgis/core 应该是 ESM。但是,当我尝试将其导入 SvelteKit
我有以下组件: App.js import React from "react"; import { Slider } from "./Slider"; function App() { retu
当浏览器现在支持原生 ESM 时,为什么开发人员仍然需要使用像 rollup 和 webpack 这样的模块捆绑器 最佳答案 你不需要模块打包器——开发人员甚至在模块和 Webpack 存在之前就能够
我一直在尝试解决这个问题一个星期,但似乎无法真正找到问题所在。 我关注了this tutorial但我没有自己的项目结构(见下图) 在 esm.js 中: require = require("esm
我的设置 Node v14.16.0 我有一个测试文件,其中包含一个用 ESM 模块 (import) 编写的简单测试。 在 package.json我有一个脚本(遵循Jest documentati
我有一个组件库,它将发布到 npm 以供 razzle 应用程序使用。我想要对最佳实践发表意见的主要问题是,这些包应该用 cjs 还是 esm 构建,每个的缺点是什么? 我可以只构建到 cjs 吗?
我是一名优秀的程序员,十分优秀!