通往通用JavaScript的道路
发表于2022年5月9日
作者:@ddprrt
阅读时间:6分钟
更多关于JavaScript的内容
通用的JavaScript。在各种环境下都能使用的JavaScript。在客户端和服务器上都能运行的JavaScript,这是多年来一直在考虑的事情(见1,2)。我们现在在哪里?
一个小例子#
假设我需要解析100个播客集的标题。它们是一些老的XML格式,解析起来有点困难。我需要用现代的Node.js来写这个,需要什么?
import { XMLParser } from "fast-xml-parser";import { url_prefix } from "./data.mjs"; function fetch_episode(episode_number) { return fetch(`${url_prefix}${episode_number}`) .then(res => res.text()) .then(data => { const obj = new XMLParser().parse(data) return obj['!doctype'].html.head.meta.meta.title }) .catch((e) => { return undefined })}const episode_requests = new Array(100) .fill(0) .map((el, i) => fetch_episode(i))const results = await Promise.all(episode_requests)// List all of themconsole.log(results.filter(Boolean))
好吧,这还不错。fast-xml-parser 是Node.js的一个依赖项。由于Node.js团队花了一些时间让模块运行起来,我可以在EcmaScript模块中使用这个CommonJS风格的模块。就像这样。
$ npm install --save fast-xml-parser
在Node 18中,通过fetch 加载资源在标志--experimental-fetch 后面是可用的。有一些边缘情况可能需要注意,但总的来说,它的状态很好,使用起来很有趣。Node和Undici团队做得很好!
Deno怎么样?#
现在有更多的JavaScript运行时。那么Deno呢?这是我的主要脚本。
import { XMLParser } from "fast-xml-parser";import { url_prefix } from "./data.mjs"; function fetch_episode(episode_number) { return fetch(`${url_prefix}${episode_number}`) .then(res => res.text()) .then(data => { const obj = new XMLParser().parse(data) return obj['!doctype'].html.head.meta.meta.title }) .catch((e) => { return undefined })}const episode_requests = new Array(100) .fill(0) .map((el, i) => fetch_episode(i))const results = await Promise.all(episode_requests)// List all of themconsole.log(results.filter(Boolean))
等等,这是同一个脚本吗?它的工作方式就像这样吗?
不完全是。Deno使用了一种不同的方式来加载模块。它通过指向一个URL来要求它们。像Skypack和JSPM这样的工具允许Node.js依赖性通过URL传递。还有一个很好的功能,叫做导入地图,可以在你的代码中把它们连接起来。
{ "imports": { "fast-xml-parser": "https://ga.jspm.io/npm:[email protected]/src/fxp.js" }, "scopes": { "https://ga.jspm.io/": { "strnum": "https://ga.jspm.io/npm:[email protected]/strnum.js" } } }
在JSPM网站上有一个导入地图生成器。同样的输出可以用来使相同的脚本在浏览器中工作(尽管有CORS问题)。
但那不是很酷吗?由于fast-xml-parser ,没有本地的依赖性,只有JavaScript,所以它开箱即用。
Cloudflare工人#
好吧,还有更多的JavaScript运行时。我经常使用的一个JS运行时是Cloudflare workers。它们是边缘处理程序,可以在你交付之前对响应进行快速转换。我可以使用--你猜对了--和上面一样的脚本。我通过把它们捆绑在一起来处理依赖性问题。esbuild
$ esbuild index.mjs --bundle --outfile=bundle.js --format=esm
我还将获取的标题数量限制为10个。Cloudflare工作者是为边缘响应服务的,他们需要限制出站连接,原因很多。
关于我自己的JavaScript运行时#
我目前在做一个JavaScript运行时。它以Rust和Deno为基础,处理一些我所从事的领域所特有的复杂问题。早期我们决定专注于网络标准,并支持fetch ,EcmaScript模块等,以确保我们有一个共同的兼容性子集。你猜怎么着。上面的脚本在我自己的JavaScript运行时上也是这样工作的。
冬天#
我认为有可能在任何地方运行相同的代码是令人兴奋的,这也是朝着正确方向迈出的美妙一步。这只是一个开始,未来还有很多事情要实现。但未来看起来很光明。
今天,Cloudflare、Deno、Vercel、Node.js、Bloomberg和Shopify的人们宣布了Web Interoperable JavaScript Community Group,或简称:wintercg 。这个小组希望通过采用浏览器中的功能作为通用标准,确保所有运行时供应商朝着同一方向发展。
另外,请看James Snell的演讲 "是的,Node.js是网络平台的一部分",这应该会让你对一切的发展方向有更多的想法。
对我来说,这很好!选择网络标准使我的努力与所有其他供应商兼容。这对你意味着什么?跨平台兼容的依赖性。你选择了最适合你需要的平台,你可以带着你的应用程序一起走。
TL/DR🏃♀️🚶♀️庆祝🎉🎉