Node.js 18 新特性解读
简介 Node.js 刚刚发布了 18.0.0 版本,内置了 fetch、node:test 等标准模块。
<p> </p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">需要注意的是,该版本不是 LTS 版本,请勿在生产环境使用,需要等到 2022-10-25 才会成为 LTS 版本。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;"><img style="vertical-align: middle; border: 0px; cursor: pointer;" title="https://github.com/nodejs/Release" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/012135a1091b40ef807c8b6e3919bcce~tplv-k3u1fbpfcp-zoom-1.image" alt="image.png" /></p>
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">Looking to the future</h2>
<blockquote style="padding-left: 15px; margin-bottom: 20px; margin-left: 0px; border-left-width: 5px; border-left-color: #eeeeee; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; line-height: 1.7em; white-space: pre-wrap; overflow-wrap: break-word; overflow: auto;">The project is also continuing its ‘Next 10’ effort. The goal of this effort is to reflect on what led to success in the first 10 years of Node.js and set the direction for success in the next 10.</p>
</blockquote>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">Node.js 官方启动了 <a style="color: #0088cc;" href="https://github.com/nodejs/next-10" target="_blank" rel="noopener">next-10</a> 工作,并讨论出了<a style="color: #0088cc;" href="https://github.com/nodejs/node/blob/master/doc/contributing/technical-priorities.md" target="_blank" rel="noopener">未来重要的几件事</a>:</p>
<ul style="margin-bottom: 10px; margin-left: 25px; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<li style="line-height: 2em;">现代化的 HTTP</li>
<li style="line-height: 2em;">友好的类型支持</li>
<li style="line-height: 2em;">对初学者更友好的渐进式文档</li>
<li style="line-height: 2em;">对 ECMAScript 规范的支持和及时跟进</li>
<li style="line-height: 2em;">可观测性,包括 logging/metrics/tracing,以及 APM 等</li>
<li style="line-height: 2em;">更好的多线程支持</li>
<li style="line-height: 2em;">支持打包为单文件的分发方式</li>
</ul>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">譬如前面说的 Fetch 就和 Modern HTTP 的会议讨论有关,<a style="color: #0088cc;" href="https://github.com/nodejs/next-10/blob/main/meetings/summit-jan-2022.md" target="_blank" rel="noopener">相关纪要</a>。</p>
<blockquote style="padding-left: 15px; margin-bottom: 20px; margin-left: 0px; border-left-width: 5px; border-left-color: #eeeeee; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; line-height: 1.7em; white-space: pre-wrap; overflow-wrap: break-word; overflow: auto;">6 月份的 OpenJS World 会议中将分享 ESM 和 Observability 进展,可以关注下相关动态。</p>
</blockquote>
<hr style="margin-top: 20px; margin-bottom: 20px; border-bottom-width: 1px; border-right-style: initial; border-left-style: initial; border-image: initial; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff; border-color: #eeeeee initial #ffffff initial;" />
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">Fetch API</h2>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">前端同学应该都很熟悉<code style="padding: 4px 6px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: #000000; border-radius: 1px; white-space: nowrap; background: 0px 0px #fcfafa; border: none; margin-right: 1px; margin-left: 1px;">fetch()</code>这个 API,它提供了标准的网络请求能力,取代了远古的 XMLHttpRequest 。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">反观 Node.js 侧,官方提供的 <a style="color: #0088cc;" href="https://nodejs.org/dist/latest-v18.x/docs/api/http.html#httprequesturl-options-callback" target="_blank" rel="noopener">http.request()</a>,太底层太基础了,用起来往往需要大量的封装。譬如 302 后自动跳转、文件上传、响应结果解析等等。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">因此在 Node.js 社区有非常多的上层请求库封装:</p>
<ul style="margin-bottom: 10px; margin-left: 25px; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<li style="line-height: 2em;">曾经广受社区欢迎的 request 库去年<a style="color: #0088cc;" href="https://github.com/request/request/issues/3142" target="_blank" rel="noopener">宣布停止维护</a>后,也引起了社区比较大的混乱。。</li>
<li style="line-height: 2em;">我们 Egg 内置的是 <a style="color: #0088cc;" href="https://www.npmjs.com/package/urllib" target="_blank" rel="noopener">urllib</a>,沉淀了阿里多年在网络请求上踩的坑,足够稳定,不过代码也有点久远了。</li>
<li style="line-height: 2em;">更多参见 <a style="color: #0088cc;" href="https://github.com/request/request/issues/3143" target="_blank" rel="noopener">Alternative libraries to request</a> 以及 <a style="color: #0088cc;" href="https://zhuanlan.zhihu.com/p/415361629" target="_blank" rel="noopener">《天猪:那些你应该说再见的 npm 祖传老库》</a>。</li>
</ul>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;"><span style="font-weight: bold;">去年 Node.js 官方推出了 <a style="color: #0088cc;" href="https://undici.nodejs.org/" target="_blank" rel="noopener">undici</a>,一个非常现代化的库,具备优越的性能,良好的扩展性,内置的 mock 等能力,集大成者。</span></p>
<blockquote style="padding-left: 15px; margin-bottom: 20px; margin-left: 0px; border-left-width: 5px; border-left-color: #eeeeee; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; line-height: 1.7em; white-space: pre-wrap; overflow-wrap: break-word; overflow: auto;">undici 的命名也很有趣:A HTTP/1.1 client → 11 → Eleven → Undici,即意大利语的 11。</p>
</blockquote>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">从而 <span style="font-weight: bold;">Node.js 终于内置了新的请求库</span>,它遵循 <a style="color: #0088cc;" href="https://fetch.spec.whatwg.org/" target="_blank" rel="noopener">Fetch 规范</a>,底层就是基于 undici 来实现的。</p>
<pre class="prettyprint language-javascript" style="line-height: 22px; white-space: pre-wrap; padding: 0px 15px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; color: #333333; border-radius: 0px; margin: 20px -10px; word-break: break-all; overflow-wrap: break-word; background-color: #f7f7f7; border-width: 1px 0px; border-style: none; border-color: initial; border-image: initial; word-spacing: 0px;"><code style="padding: 0px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: inherit; background-color: transparent; border: 0px;"><span class="kwd" style="color: #000088;">const</span><span class="pln" style="color: #000000;"> res </span><span class="pun" style="color: #666600;">=</span><span class="pln" style="color: #000000;"> await fetch</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'https://nodejs.org/api/documentation.json'</span><span class="pun" style="color: #666600;">);</span>
<span class="kwd" style="color: #000088;">if</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">res</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">ok</span><span class="pun" style="color: #666600;">)</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span>
<span class="kwd" style="color: #000088;">const</span><span class="pln" style="color: #000000;"> data </span><span class="pun" style="color: #666600;">=</span><span class="pln" style="color: #000000;"> await res</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">json</span><span class="pun" style="color: #666600;">();</span><span class="pln" style="color: #000000;">
console</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">log</span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">data</span><span class="pun" style="color: #666600;">);</span>
<span class="pun" style="color: #666600;">}</span></code></pre>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">就这么简单,比 <a style="color: #0088cc;" href="https://nodejs.org/dist/latest-v18.x/docs/api/http.html#httprequesturl-options-callback" target="_blank" rel="noopener">http.request()</a> 那一坨 callback-style 代码简洁多了,平时写个脚本啥的,不用再引入额外的类库了。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">全局增加了 fetch, FormData, Headers, Request, Response 这几个 API,以及 Web Streams API。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">目前还处于默认开启的实验性特性阶段,文档在 <a style="color: #0088cc;" href="https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch" target="_blank" rel="noopener">Globals</a> 章节,近乎没有,有需要直接看 <a style="color: #0088cc;" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" target="_blank" rel="noopener">MDN 文档</a> 即可。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">可能是为了遵循规范, undici 的很多能力如 Mock,Proxy,Pool 等都没有提供出来。</p>
<hr style="margin-top: 20px; margin-bottom: 20px; border-bottom-width: 1px; border-right-style: initial; border-left-style: initial; border-image: initial; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff; border-color: #eeeeee initial #ffffff initial;" />
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">Test Runner</h2>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">单元测试很重要,很多新兴的编程语言都是会内置对应的能力,但前端这块一直都是由社区来实现,前端同学耳熟能详的 Test Runner 有 <a style="color: #0088cc;" href="https://mochajs.org/" target="_blank" rel="noopener">Mocha</a>、<a style="color: #0088cc;" href="https://jestjs.io/" target="_blank" rel="noopener">Jest</a>。</p>
<pre class="prettyprint language-javascript" style="line-height: 22px; white-space: pre-wrap; padding: 0px 15px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; color: #333333; border-radius: 0px; margin: 20px -10px; word-break: break-all; overflow-wrap: break-word; background-color: #f7f7f7; border-width: 1px 0px; border-style: none; border-color: initial; border-image: initial; word-spacing: 0px;"><code style="padding: 0px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: inherit; background-color: transparent; border: 0px;"><span class="com" style="color: #880000;">// mocha showcase</span>
<span class="kwd" style="color: #000088;">import</span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">assert</span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">from</span><span class="pln" style="color: #000000;"> </span><span class="str" style="color: #008800;">'assert/strict'</span><span class="pun" style="color: #666600;">;</span><span class="pln" style="color: #000000;">
describe</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'test/index.test.js'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">()</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span><span class="pln" style="color: #000000;">
it</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'test1'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> async </span><span class="pun" style="color: #666600;">()</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span>
<span class="kwd" style="color: #000088;">const</span><span class="pln" style="color: #000000;"> res </span><span class="pun" style="color: #666600;">=</span><span class="pln" style="color: #000000;"> await fetch</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'https://nodejs.org/api/documentation.json'</span><span class="pun" style="color: #666600;">);</span>
<span class="kwd" style="color: #000088;">assert</span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">res</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">ok</span><span class="pun" style="color: #666600;">);</span>
<span class="pun" style="color: #666600;">});</span><span class="pln" style="color: #000000;">
it</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">skip</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'skip some test'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">()</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{});</span>
<span class="pun" style="color: #666600;">});</span></code></pre>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">终于,Node.js 在 18.x 里官方支持了 <a style="color: #0088cc;" href="https://nodejs.org/dist/latest-v18.x/docs/api/test.html" target="_blank" rel="noopener">Test 能力</a>:</p>
<pre class="prettyprint language-javascript" style="line-height: 22px; white-space: pre-wrap; padding: 0px 15px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; color: #333333; border-radius: 0px; margin: 20px -10px; word-break: break-all; overflow-wrap: break-word; background-color: #f7f7f7; border-width: 1px 0px; border-style: none; border-color: initial; border-image: initial; word-spacing: 0px;"><code style="padding: 0px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: inherit; background-color: transparent; border: 0px;"><span class="kwd" style="color: #000088;">import</span><span class="pln" style="color: #000000;"> test </span><span class="kwd" style="color: #000088;">from</span><span class="pln" style="color: #000000;"> </span><span class="str" style="color: #008800;">'node:test'</span><span class="pun" style="color: #666600;">;</span>
<span class="kwd" style="color: #000088;">import</span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">assert</span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">from</span><span class="pln" style="color: #000000;"> </span><span class="str" style="color: #008800;">'assert/strict'</span><span class="pun" style="color: #666600;">;</span>
<span class="com" style="color: #880000;">// 等价于 describe()</span><span class="pln" style="color: #000000;">
test</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'asynchronous passing test'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> async </span><span class="pun" style="color: #666600;">()</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span>
<span class="kwd" style="color: #000088;">const</span><span class="pln" style="color: #000000;"> res </span><span class="pun" style="color: #666600;">=</span><span class="pln" style="color: #000000;"> await fetch</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'https://nodejs.org/api/documentation.json'</span><span class="pun" style="color: #666600;">);</span>
<span class="kwd" style="color: #000088;">assert</span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">res</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">ok</span><span class="pun" style="color: #666600;">);</span>
<span class="pun" style="color: #666600;">});</span><span class="pln" style="color: #000000;">
test</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'multi level test'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> async </span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">t</span><span class="pun" style="color: #666600;">)</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span>
<span class="com" style="color: #880000;">// 等价于 it()</span><span class="pln" style="color: #000000;">
await t</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">test</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'subtest 1'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">t</span><span class="pun" style="color: #666600;">)</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span>
<span class="kwd" style="color: #000088;">assert</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">strictEqual</span><span class="pun" style="color: #666600;">(</span><span class="lit" style="color: #006666;">1</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="lit" style="color: #006666;">1</span><span class="pun" style="color: #666600;">);</span>
<span class="pun" style="color: #666600;">});</span><span class="pln" style="color: #000000;">
await t</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">test</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'subtest 2'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">(</span><span class="pln" style="color: #000000;">t</span><span class="pun" style="color: #666600;">)</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span>
<span class="kwd" style="color: #000088;">assert</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">strictEqual</span><span class="pun" style="color: #666600;">(</span><span class="lit" style="color: #006666;">2</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="lit" style="color: #006666;">2</span><span class="pun" style="color: #666600;">);</span>
<span class="pun" style="color: #666600;">});</span>
<span class="pun" style="color: #666600;">});</span>
<span class="com" style="color: #880000;">// 等价于 describe.skip() / it.skip()</span><span class="pln" style="color: #000000;">
test</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'skip option'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span><span class="pln" style="color: #000000;"> skip</span><span class="pun" style="color: #666600;">:</span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">true</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">},</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">()</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{});</span>
<span class="com" style="color: #880000;">// 等价于 describe.only() / it.only()</span><span class="pln" style="color: #000000;">
test</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'only option'</span><span class="pun" style="color: #666600;">,</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{</span><span class="pln" style="color: #000000;"> only</span><span class="pun" style="color: #666600;">:</span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">true</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">},</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">()</span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">=></span><span class="pln" style="color: #000000;"> </span><span class="pun" style="color: #666600;">{});</span></code></pre>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">可以看到:</p>
<ul style="margin-bottom: 10px; margin-left: 25px; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<li style="line-height: 2em;">语法其实差不多,会更简洁一点,就一个 <code style="padding: 4px 6px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: #000000; white-space: nowrap; background-color: #fcfafa; border: none;">test()</code>,options 除了 skip 和 only 外,还支持 concurrency 并发。</li>
<li style="line-height: 2em;">无需启动器,每一个文件都是一个可执行的 Node.js 代码。</li>
<li style="line-height: 2em;">暂未支持 <code style="padding: 4px 6px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: #000000; white-space: nowrap; background-color: #fcfafa; border: none;">before/after/beforeEach/afterEach</code> 能力,看 issue 描述会后续支持。</li>
<li style="line-height: 2em;">暂未支持 Reporter,但日志输出为标准 <a style="color: #0088cc;" href="https://testanything.org/" target="_blank" rel="noopener">TAP</a> 格式,所以应该很容易能复用现有的社区生态。</li>
</ul>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">类似覆盖率的演进过程,以前我们需要通过 nyc 对代码转译打桩,现在变为的 Node.js 内置覆盖率输出,nyc 变为 c8 这样的覆盖率报告生成工具。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">后续 mocha 等估计会变为类似的上层封装,提供批量执行 和 Reporter 等能力。</p>
<hr style="margin-top: 20px; margin-bottom: 20px; border-bottom-width: 1px; border-right-style: initial; border-left-style: initial; border-image: initial; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff; border-color: #eeeeee initial #ffffff initial;" />
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">Build-time user-land snapshot</h2>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">简单的说,可以把某个 js 直接编译成 v8 snapshot,从而可以极大的提速启动时间。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">目前这个版本,还只能通过 Node.js 源码来编译,且只能编译成 Node.js Runtime 的方式,即 Build-time。</p>
<pre class="prettyprint language-bash" style="line-height: 22px; white-space: pre-wrap; padding: 0px 15px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; color: #333333; border-radius: 0px; margin: 20px -10px; word-break: break-all; overflow-wrap: break-word; background-color: #f7f7f7; border-width: 1px 0px; border-style: none; border-color: initial; border-image: initial; word-spacing: 0px;"><code style="padding: 0px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: inherit; background-color: transparent; border: 0px;"><span class="com" style="color: #880000;"># 把一段 markdown 渲染的逻辑,直接打包到 Node Runtime</span><span class="pln" style="color: #000000;">
$ cd </span><span class="pun" style="color: #666600;">/</span><span class="pln" style="color: #000000;">path</span><span class="pun" style="color: #666600;">/</span><span class="pln" style="color: #000000;">to</span><span class="pun" style="color: #666600;">/</span><span class="pln" style="color: #000000;">node</span><span class="pun" style="color: #666600;">/</span><span class="pln" style="color: #000000;">source
$ </span><span class="pun" style="color: #666600;">./</span><span class="pln" style="color: #000000;">configure </span><span class="pun" style="color: #666600;">--</span><span class="pln" style="color: #000000;">node</span><span class="pun" style="color: #666600;">-</span><span class="pln" style="color: #000000;">snapshot</span><span class="pun" style="color: #666600;">-</span><span class="pln" style="color: #000000;">main</span><span class="pun" style="color: #666600;">=</span><span class="pln" style="color: #000000;">marked</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">js
$ make node
</span><span class="com" style="color: #880000;"># 执行编译好的 Node Runtime</span><span class="pln" style="color: #000000;">
$ </span><span class="kwd" style="color: #000088;">out</span><span class="pun" style="color: #666600;">/</span><span class="typ" style="color: #660066;">Release</span><span class="pun" style="color: #666600;">/</span><span class="pln" style="color: #000000;">node
</span><span class="pun" style="color: #666600;">></span><span class="pln" style="color: #000000;"> </span><span class="kwd" style="color: #000088;">const</span><span class="pln" style="color: #000000;"> html </span><span class="pun" style="color: #666600;">=</span><span class="pln" style="color: #000000;"> globalThis</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">marked</span><span class="pun" style="color: #666600;">(</span><span class="str" style="color: #008800;">'# this is title'</span><span class="pun" style="color: #666600;">);</span></code></pre>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">秋怡正在继续推进<a style="color: #0088cc;" href="https://github.com/nodejs/node/issues/35711" target="_blank" rel="noopener">该能力</a>,未来可以无需编译 Node.js 源码:</p>
<pre class="prettyprint language-bash" style="line-height: 22px; white-space: pre-wrap; padding: 0px 15px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 14px; color: #333333; border-radius: 0px; margin: 20px -10px; word-break: break-all; overflow-wrap: break-word; background-color: #f7f7f7; border-width: 1px 0px; border-style: none; border-color: initial; border-image: initial; word-spacing: 0px;"><code style="padding: 0px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; font-size: 12px; color: inherit; background-color: transparent; border: 0px;"><span class="pln" style="color: #000000;">$ node </span><span class="pun" style="color: #666600;">--</span><span class="pln" style="color: #000000;">build</span><span class="pun" style="color: #666600;">-</span><span class="pln" style="color: #000000;">snapshot </span><span class="pun" style="color: #666600;">--</span><span class="pln" style="color: #000000;">snapshot</span><span class="pun" style="color: #666600;">-</span><span class="pln" style="color: #000000;">blob marked</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">blob marked</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">js
$ node </span><span class="pun" style="color: #666600;">--</span><span class="pln" style="color: #000000;">snapshot</span><span class="pun" style="color: #666600;">-</span><span class="pln" style="color: #000000;">blob marked</span><span class="pun" style="color: #666600;">.</span><span class="pln" style="color: #000000;">blob</span></code></pre>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">PS:这个能力用在命令行 CLI 的独立打包好像也不错。<a style="color: #0088cc;" href="https://github.com/nodejs/node/issues/42566" target="_blank" rel="noopener">https://github.com/nodejs/node/issues/42566</a></p>
<hr style="margin-top: 20px; margin-bottom: 20px; border-bottom-width: 1px; border-right-style: initial; border-left-style: initial; border-image: initial; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff; border-color: #eeeeee initial #ffffff initial;" />
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">V8 引擎升级</h2>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">内置的 V8 引擎升级到 10.1 版本,值得注意的特性:</p>
<ul style="margin-bottom: 10px; margin-left: 25px; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<li style="line-height: 2em;">class fields 和 private class methods 的性能优化。</li>
<li style="line-height: 2em;"><a style="color: #0088cc;" href="https://v8.dev/blog/v8-release-99#intl.locale-extensions" target="_blank" rel="noopener">Intl 规范</a> 的支持,在做日期的本地化,字符串处理的时候非常有用。</li>
<li style="line-height: 2em;">数组支持 findLast() 和 findLastIndex() 等。</li>
</ul>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">秋怡也写了一篇文章 <a style="color: #0088cc;" href="https://v8.dev/blog/faster-class-features" target="_blank" rel="noopener">Faster initialization of instances with new class features</a> 分享了背后的实现。</p>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">PS:<a style="color: #0088cc;" href="https://mp.weixin.qq.com/s/6PTcjJQTED3WpJH8ToXInw" target="_blank" rel="noopener">ECMAScript 双月报告:装饰器提案进入 Stage 3</a> ,阿里的 Node 架构团队今年会推动 Decorator 方案在 V8 的落地实现,不过肯定赶不上了,只能 Node.js 20.x 见了。</p>
<hr style="margin-top: 20px; margin-bottom: 20px; border-bottom-width: 1px; border-right-style: initial; border-left-style: initial; border-image: initial; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff; border-color: #eeeeee initial #ffffff initial;" />
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">ESM 的支持</h2>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">虽然在 18.x 中没有新的内容,但在过去的几个月中一直在持续推动 ECMAScript模块实现:</p>
<ul style="margin-bottom: 10px; margin-left: 25px; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<li style="line-height: 2em;">对 <a style="color: #0088cc;" href="https://github.com/tc39/proposal-import-assertions" target="_blank" rel="noopener">JSON Import Assertions</a> 的支持。</li>
<li style="line-height: 2em;">JSON 模块的正式支持。</li>
<li style="line-height: 2em;">对 HTTPS 和 HTTP 导入的实验性支持。</li>
<li style="line-height: 2em;"><a style="color: #0088cc;" href="https://github.com/nodejs/loaders" target="_blank" rel="noopener">Node.js 加载器团队</a>也在继续开发 ECMAScript 模块加载器实现。</li>
</ul>
<hr style="margin-top: 20px; margin-bottom: 20px; border-bottom-width: 1px; border-right-style: initial; border-left-style: initial; border-image: initial; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff; border-color: #eeeeee initial #ffffff initial;" />
<h2 style="margin-top: 30px; margin-bottom: 15px; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; line-height: 40px; color: #333333; text-rendering: optimizelegibility; font-size: 26px; border-bottom: 1px solid #eeeeee; background-color: #ffffff;">工具链和编译器的升级</h2>
<ul style="margin-bottom: 10px; margin-left: 25px; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; font-size: 14px; background-color: #ffffff;">
<li style="line-height: 2em;">Linux 版是在 RHEL8 上构建的,要求 glibc 2.28 以上版本。</li>
<li style="line-height: 2em;">macOS 要求 10.15 以上版本。</li>
<li style="line-height: 2em;">Windows 很多旧版本也不支持了。</li>
</ul>
<p style="margin-top: 1em; margin-bottom: 1em; font-size: 15px; word-break: break-word; white-space: pre-wrap; overflow-wrap: break-word; line-height: 1.7em; overflow: auto; color: #333333; font-family: 'Helvetica Neue', 'Luxi Sans', 'DejaVu Sans', Tahoma, 'Hiragino Sans GB', STHeiti, sans-serif; background-color: #ffffff;">PS:CentOS 7 官方不再维护了,它对应的 glibc 版本太低,所以升不了。。。</p>
分享到:
转载:
https://zhuanlan.zhihu.com/p/502951532
喜欢 2
收藏
暂无评论信息
- 相关文章
- 文章推荐
-
群辉nas docker容器 配置svn仓库,并实现外网访问
2022-08-11的这一天, 群辉nas到手了, 实现svn仓库外网的访问,折腾了好久。记录一下。
-
Node 配置sequelize + mysql,根据模型自动创建数据库表
研究了一下午的node + sequelize + mysql。
-
docker搭建jenkins环境执行宿主机的docker无权限的解决方法
初次搭建jenkins持续集成工具的时候,在运行项目阶段出现 permission denied的情况
-
淘宝 NPM 镜像站喊你切换新域名啦
淘宝 NPM 镜像站(npm.taobao.org)自 2014 年 正式对外服务,一开始只是想简单地做 NPM 的中国镜像站点,回馈国内前端社区,不知不觉竟然一直运行到现在。当年参考 Ruby Gems 淘宝镜像 的方式,跟阿里开源组织申请了 taobao.org 的二级域名,镜像站点名称也自然而然地取名为 淘宝 NPM 镜像站 (下称 CNPM)。
- 点击排行
- 站长推荐
- 猜你喜欢
- 网站信息
- 站内问答:12篇
- 站内文章:212篇
- 建站时间:已运行1107天
- 备案号: 浙ICP备2022018799号
- 语言:
English(USA)
French(FR)
Chinese(ZH)
无数据