当前位置: 首页 > news >正文

济南建设集团网站网站群建设思路

济南建设集团网站,网站群建设思路,如何为wordpress添加音乐播放器,WordPress显示插件前言又到周五了。今日早读文章由Shopee周雨楠翻译授权分享。周雨楠#xff0c;Shopee金融事业群前端研发#xff0c;自主学习前端技术3年#xff0c;喜爱各类数字媒体技术、创意设计#xff0c;多次参与翻译工作。福利#xff1a;有两张门票#xff0c;有需要的跟情封联系… 前言又到周五了。今日早读文章由Shopee周雨楠翻译授权分享。周雨楠Shopee金融事业群前端研发自主学习前端技术3年喜爱各类数字媒体技术、创意设计多次参与翻译工作。福利有两张门票有需要的跟情封联系先到先得。正文从这开始~~两者可以进行适配但是会徒增负担。在 Node 14 版本下现存两类语法老式的 CommonJS (CJS) 的语法和新式的 ESM 语法(aka MJS)。CJS 使用 require() 和 module.exportsESM 使用 import 和 export。ESM 和 CJS 可以看作是完全不同的动物。表面上看ESM 和 CJS 很像但是他们的实现却是大相径庭。如果说一个是蜜蜂那么另一个就是杀人蜂。图中是一只黄蜂和一只蜜蜂。其中一个好比 ESM另一个好比 CJS但是我永远记不住哪个是哪个。图片来源wikimediawikimedia无论是在 ESM 中使用 CJS 还是反过来都是有可能的但这是徒增负担。以下是一些规则我会在后文中详细解释。在 ESM 代码中无法使用 require()你只能 importESM代码比如import{foo}fromfooCJS 代码无法使用如上所示的静态 import 语句ESM 代码可以 import CJS 代码但是只能使用“默认导入(default import)”语法如 import_fromlodash而不是“命名导入(named import)”语法如 import{shuffle}fromlodash因此如果 CJS 代码使用了命名导出就会很麻烦ESM 代码可以 require() CJS 代码即便是命名导出也可以但是明显不值得大费周章因为这样需要更多的框架平台而且最不好的一点就是诸如 Webpack 和 Rollup 这样的包不知道也不会知道怎么处理含有 require() 的 ESM 代码CJS 是默认允许使用的而 ESM 模式则需要你选择性加入。通过把代码文件从 .js 重命名为 .mjs 就可以启用 ESM 模式。除此之外在 package.json 中设置 type: module然后就可以通过把 .js 重命名为 .cjs 选择退出 ESM 模式。(你甚至可以在某一个子目录下添加一个只有一行 {type: module} 的 package.json 文件来调整。)这些条条框框太痛苦了。对于很多使用者尤其是 Node 入门者来说是更为痛苦的这些规则压根不可理喻。(不慌这篇文章里我都将解释清楚。)很多 Node 生态的关注者已经发现这些规则是由于先前领导的失败甚至是对 ESM 的敌意导致的。不过正如下文所说所有的规则都有其存在的意义这使得未来想要打破这些规则也很难。我为开源库的开发者整理了三条指南用于借鉴为你的开源库提供一个 CJS 的版本为你的 CJS 版本提供一个较浅的 ESM 封装在你的 package.json 文件中添加一个 exports 的映射。一切就会好起来了。背景介绍CJS 是什么ESM 又是什么从 Node 初见以来Node 中的模块就是以 CommonJS 模块来写的。我们使用 require() 来引入它们。当实现了一个模块并且想让他人使用时我们就会定义 exports 内容要么通过设置 module.exports.foobar 进行“命名导出”要么通过设置 module.exports baz 进行“默认导出”。这是一个 CJS 使用命名导出的例子util.cjs 有一个命名为 sum 的导出函数。// 文件名: util.cjsmodule.exports.sum (x, y) x y;// 文件名: main.cjsconst {sum} require(./util.cjs);console.log(sum(2, 4));这是一个 CJS 在 util.cjs 中使用默认导出的例子。默认导出是不指定名字的而是由使用 require() 的模块自行定义名称。// 文件名: util.cjsmodule.exports (x, y) x y;// 文件名: main.cjsconst whateverWeWant require(./util.cjs);console.log(whateverWeWant(2, 4));在 ESM 代码中import 和 export 是这类语言的一部分。和 CJS 类似它也有两套不同的语法进行命名导出和默认导出。这是一个 ESM 使用了命名导出的例子util.mjs 有一个命名为 sum 的导出函数。// 文件名: util.mjsexport const sum (x, y) x y;// 文件名: main.mjsimport {sum} from ./util.mjsconsole.log(sum(2, 4));这是一个 ESM 在 util.mjs 中设置了默认导出的例子。和 CJS 中一样默认导出是没有名字的但是使用了 import 的模块会自行定义名称。// 文件名: util.mjsexport default (x, y) x y;// 文件名: main.mjsimport whateverWeWant from ./util.mjsconsole.log(whateverWeWant(2, 4));ESM 和 CJS 是截然不同的动物在 CommonJS 中require() 是同步的。它不会返回一个 promise 或者调用回调函数。require() 从硬盘(或者甚至从网络)中进行读操作然后立刻执行代码。这样就会使得它自行进行 I/O 或产生其它副作用然后返回任何设置在 module.exports 上的值。在 ESM 中模块加载器是在异步阶段执行的。在第一个阶段它会做词法分析在不执行导入代码的情况下检测是否存在 import 和 export 的调用。在词法转换阶段ESM 加载器能够立刻检测到命名导入中的拼写错误并且在不执行依赖代码的情况下抛出异常。ESM 加载器接下来异步地下载并转译任何引入的代码然后对引入的代码进行编码根据依赖建立出一个“模块图(module graph)”直到最后它发现某块代码没有引入任何东西。最后这一块代码被允许执行然后所有这一块代码所依赖的代码被允许执行依次类推。ES 模块图中所有具有“兄弟”关系的代码都是并行下载的但是是按照次序执行的。这一次序由加载器指定并确保执行。CJS 是默认模式因为 ESM 改变了很多东西ESM 改变了 JavaScript 中的很多东西。ESM 语法默认使用严格模式(use strict)它们的 this 不指向全局对象作用域也有差异等等。这就是为什么甚至在浏览器中 标签默认也不是 ESM 模式的。要添加一个 typemodule 属性来选择进入 ESM 模式。从默认的 CJS 切换到 ESM 在向前兼容性方面存在很大断层。(最近炙手可热的 Node 替代品 Deno 将 ESM 作为默认但是其结果就是 Deno 的生态环境要从零开始搭建。)CJS 无法 require() ESM因为有顶层的 await 限制CJS 无法 require() ESM 的最简单原因就是 ESM 可以进行最外层的 await 但是 CJS 代码不行。顶层 await 能够让我们在 async 函数的外层使用 await 关键字也就是处于“顶层”。ESM 的多阶段加载器使得 ESM 实现顶层 await 时不会搬起石头砸自己的脚。从V8团队的博客文章中引用一些话也许你读过 Rich Harris 写的臭名昭著的 gist一开始就罗列了一些所担心的关于顶层 await 的问题并且迫切希望 JavaScript 语言不要实现出来。其中的一些问题是顶层 await 会阻塞执行顶层 await 会阻塞资源获取CommonJS 模块没法再做清晰的内嵌了。第三阶段版本的提议也强调了这些问题因为兄弟关系的代码是可以执行的因此最终没有造成阻塞顶层 await 出现在模块图的执行阶段。在此阶段所有的资源都已经获得并且建立了链接因此是不存在阻塞资源获取风险的顶层 await 仅仅限制在 ESM 模块中使用CommonJS 的模块或者代码中明确没有对此的支持。(Rich 现在已经同意了当前顶层 await 的实现。)因为 CJS 不支持顶层 await那么从 ESM 的顶层 await 转译为 CJS 就是不可能的。在 CJS 中怎么重写这段代码呢export const foo await fetch(./data.json);有点打击人因为绝大多数 ESM 代码不会去使用顶层 await但是正如这一条 thread 中的一个评论者所说“我并不认为设计系统的时候单单假定一些功能不会被使用是一条可行的路。”如何在 ESM 中进行 require() 的问题在这条 thread 上依旧激烈争论着。(请看完整条 thread 和其中关联的讨论后再进行评论。如果你深入研究你就会发现顶层 await 并不是唯一一个有着问题的情形。你觉得如果你同步 require 一个能够异步 import 一些能够同步 require ESM 的 CJS 的 ESM 会发生什么呢你就会得到像斑马条纹那样一会同步一会异步的能整死人的东西。顶层 await 就是棺材板上的最后一根钉子也是最容易解释的一个。)通过对那些讨论进行评审似乎我们不再会在 ESM 里做 require() 了。CJS 能够 import() ESM但是这并不好目前为止如果你在写 CJS你想 import 一段 ESM 代码你得使用异步动态的 import()。(async () { const {foo} await import(./foo.mjs);})();看上去……还行只要别有 exports 就行。如果你需要做 exports你就得导出一个 Promise这对于你的用户来说会是一个大大的不便。ESM 无法引入命名引出的 CJS除非 CJS 代码脱离执行顺序你可以这样写import _ from ./lodash.cjs但是你没法这样写import {shuffle} from ./lodash.cjs这是因为 CJS 代码会在执行的时候计算它们的命名导出而 ESM 的命名导出必须在转译阶段才会被计算。对我们而言幸运的是有曲线救国的方式这个曲线十分恼人但是还是能做的。我们这样引入 CJS 代码就可以了import _ from ./lodash.cjs;const {shuffle} _;这样做没什么特别的弊端而且感知了 ESM 的 CJS 库甚至能够提供它们自己的 ESM 包裹层为我们封装了这样的写法框架。完全没问题要是能更好点就好了。脱离执行顺序也能工作但是有更坏的结果有一部分的人提出在 ESM 引入之前执行 CJS 的引入是脱离了执行顺序的。这样一来CJS 的命名导出会和 ESM 的命名导出在同时计算。但是这样就会产生一个新的问题。import {liquor} from liquor;import {beer} from beer;如果 liquor 和 beer 最初都是 CJS把 liquor 从 CJS 换成 ESM 就会使得顺序从 liquor, beer 变成 beer, liquor那么如果 beer 中依赖 liquor 中先执行的内容这样就会令人呕吐地有问题。脱离顺序的执行依然在争论当中 虽然几周之前这个话题就几乎没啥声音了。动态模块能拯救但是它们的星号有毒有一个替代方案的提议既不需要脱离执行顺序也不需要做封装称作动态模块(Dynamic Modules)。在 ESM 中导出的地方会静态定义所有命名导出。在动态模块方案下引入的地方会在 import 中定义导出的名字。ESM 加载器一上来会信任动态模块(CJS 代码)能够提供所有需要的命名导出如果之后有地方不满足则再抛出一个异常。然而动态模块需要 JavaScript 语言发生一些变化这些变化需要 TC39 语言委员会进行同意。而他们不同意。ESM 代码可以 export*from./foo.cjs这意思是重新把 foo 中导出的所有名字进行导出。(称为“星号导出(star export)”。?)然而如果我们从动态模块中星号导出加载器就无法知道导出的是什么。动态模块的星号导出在规范合格性上也产生了问题。比如 export*fromomg;export*frombbq; 应该抛出异常因为 omg 和 bbq 都导出了相同名字的 wtf。允许这些命名能够被用户/消费者进行定义意味着这个合法性校验阶段需要被滞后处理或者忽略。动态模块的提倡者提议在动态模块中禁止星号导出方式但是 TC39 拒绝了这一提议。一个 TC39 的成员把这个提议比作是“语法毒(syntax poisoning)“因为星号导入在动态模块中就像是被“下毒”了一样。这个带毒的星星对你很生气。图片来源seekpng在我看来我们已经居住在一个语法毒的世界里了。在 Node 14 版中命名导出就是被下毒的在动态模块中星号导入也是被下毒的。因为命名导出极其普遍而星号导出相对罕见动态模块会在生态中减少语法毒的成分。这并不意味着动态模块已经穷途末路。案上依然有提议让所有 Node 模块都成为动态模块甚至带上纯 ESM 模块并且在 Node 中弃用 ESM 的多阶段加载器。让人眼前一亮的是这样并不会产生用户可见的影响除了一些可能发生的轻微启动性能下降。ESM 多阶段加载器是在网络缓慢的情况下加载代码而设计的。不过我依然不觉得会这么走运。Github 上关于动态模块的 issue 最近被关闭了因为去年没有关于动态模块的讨论。还有一个方案悬而未决那就是做一次充分努力的尝试把 CJS 模块进行词法分析从而检测出导出内容但是这个方案不可能在 100% 的用例中使用。(最新的 PR 在 npm 前 1000 的模块中只有 62% 正常工作。)因为这种启发式的东西太不可靠一些 Node 模块工作组成员是反对的。ESM 可以 require()但是很可能并不值得require() 默认并不在 ESM 代码范畴内不过你可以轻松把它找回。import { createRequire } from module;const require createRequire(import.meta.url);const {foo} require(./foo.cjs); 这个方法的问题在于它没能帮多大忙。实际上也就比做一个默认导入然后解构多了几行代码。import cjsModule from ./foo.cjs;const {foo} cjsModule;另外像 Webpack 和 Rollup 这样的打包工具并不知道如何处理 createRequire 这样的模式所以意义何在呢如何创建一个良好的包含了 CJS 和 ESM 的“二重包”如果你手上至今都维护着一个库需要支持 CJS 和 ESM那么就给你的用户做点好事按照上文的方针建造一个“二重包”能够在 CJS 和 ESM 下都良好工作。给库提供一个 CJS 的版本这是为了方便你的 CJS 用户。同时也确保了你的库能够在 Node 的早期版本中正常工作。如果你使用的是 TypeScript 或者其它最终转译成 JS 的语言那么就转译成 CJS 吧。给 CJS 提供一个浅的 ESM 封装注意给 CJS 库写一个 ESM 包裹层是不难的但是给 ESM 库写一个 CJS 包裹层就不可能了。import cjsModule from ../index.js;export const foo cjsModule.foo; 把 ESM 包裹层 放到一个 esm 的子目录下同时放入一个一行的 package.json里面只放 {type: module}。(你可以重命名你的包裹层文件为 .mjs在 Node 14 下是正常的但是有的工具和 .mjs 搭配不好因此我倾向于使用一个子目录。)避免二次转译。如果你是在从 TypeScript 做转译你可以转译成 CJS 和 ESM但是这就会带来一个潜在的危害用户可能偶然既 import 了你的 ESM 代码又 require() 了你的 CJS 代码。(比如假设一个库 omg.mjs 依赖于 index.mjs另一个库 bbq.cjs 依赖于 index.cjs然后你还既要依赖 omg.mjs 又要依赖 bbq.cjs。)Node 自身会给模块做去重不过 Node 并不知道你的 CJS 和 ESM 其实是”相同的“文件于是你的代码就会执行两次并且保留你的库状态的两份拷贝。这就能引发各种奇异的 Bug。给你的 package.json 添加一个 exports 映射就像这样exports: { require: ./index.js, import: ./esm/wrapper.js}注意添加一个 exports 映射永远要作为“语义化版本控制中的主要层级”的重大变化。默认情况下你的用户能够进入你的包然后 require() 任何他们想要的代码甚至是你想要变成内部层的文件。exports 映射确保了用户只能 require/import 你刻意暴露出来的入点文件。这就快是一个好的东西了但是这也是一个重大变化。如果你跟着你的用户进行 import 或者 require() 你的模块里的其他文件你也可以分开来设置入点。具体请查阅 ESM 的 Node 文档。始终要在导出映射目标中包含文件扩展名。写成 index.js 而不是 index 或者一个类似 ./build 的目录。如果你遵循了上述的方针你的用户就会很安分。一切都会变得很安分。关于本文 译者周雨楠 译文https://mp.weixin.qq.com/s/CxlolXUpK02wZbRNah_ZQA 作者Dan Fabulich 原文链接https://redfin.engineering/node-modules-at-war-why-commonjs-and-es-modules-cant-get-along-9617135eeca1为你推荐【第1994期】ES11来了【第1899期】调研 Federated Modules应用秒开应用集方案微前端加载方案改进等欢迎自荐投稿前端早读课等你来
http://www.zqtcl.cn/news/606755/

相关文章:

  • 新网站推广网站搜索引擎优化的步骤
  • 网站建设20推广公司网站建设推广方案
  • 如何设计酒店网站建设好的交互网站
  • 怎么把自己的网站放到百度上九亭做网站
  • 张家界旅游网站建设网页设计作品欣赏分析
  • 订阅号自定义可以做链接网站不做网站dreamwa
  • 电子商务网站规划的原则做网站的集群方案
  • 山东建设银行怎么招聘网站自己做商城网站
  • 建设网站成本预算网站页面设计尺寸
  • 微官网和微网站首页房产网怎么查到房产
  • 高端服装产品网站建设织梦网站识别
  • 做调像什么网站找活注册网站请签署意见是写无
  • 郑州公司网站设计深圳福田有哪些公司
  • 怎么看网站是谁做的asp企业网站开发技术
  • 传奇手游网站大全9377编辑器wordpress
  • 网站集约化建设意见和建议苏州建设交通招聘信息网站
  • 网站建设优化的技巧衣服定制的app有哪些
  • 营销型网站建设报价vue本地访问服务器跨域
  • 支持api网站开发大疆网站建设
  • 国家排污许可网站台账怎么做进销存永久免费
  • 做游戏脚本的网站精品国内网站建设
  • 好的网站建站公司门户网站栏目维护建设方案
  • 如何在电脑上建立网站企业百度网站怎么做的
  • 34线城市做网站推广网站页面如何设计图
  • 成都网站建设前十广州开发网站设计
  • qq人脸解冻自助网站加工平台推荐
  • 中国室内设计联盟网官网网站专题页优化
  • 设计模板图热狗网站关键词优化
  • 无锡网站开发公司重庆网站有哪些
  • 做网站找什么公司工作网站开发思维导图内容