MDH 前端周刊第 48 期:Remix Routes、ShadowRealms、Rome Formatter、Umi 4 RC 11 - 图1
dnevozhai @ unsplash

Hi,我是云谦,欢迎打开新一期的「MDH:前端周刊」,这是第 0048 期,发表于 2022/04/11。

本期主要内容有这些:

  • Remix Routes
  • ShadowRealms
  • Web Maker
  • Rome Formatter
  • Umi 4 RC 11
  • Resumability
  • Node 202203

Remix Routes

https://www.smashingmagazine.com/2022/03/remix-routes-demystified/

非常好的 Remix 入门教程,路由是 Remix 区别于其他框架的重要因素之一,作者从路由的目录结构、各种功能,到数据的 load 和 mutate、Header 和 Meta 设置、资源路由,做了详细介绍。

路由匹配规则如下,包含 layout、不使用 layout、动态路由、fallback 路由。

  1. + routes/
  2. + posts
  3. # 匹配 /posts/xxx/edit
  4. - $postId.edit.jsx
  5. # 匹配 /posts/xxx
  6. - $postId.jsx
  7. # 匹配 /posts/foo,但不使用 posts.jsx 作为 layout
  8. - posts.foo.jsx
  9. # 作为 /posts 的 layout 组件
  10. - posts.jsx
  11. # 匹配不到适的 fallback
  12. - $.jsx

Remix 还有 Resource 路由的概念,类似 Next.js 的 API Routes,路由文件如果只导出 loader 函数,没导出 React 组件,即是 Resource 路由。

ShadowRealms

https://2ality.com/2022/04/shadow-realms.html

ShadowRealm 可以想象成改进版的 eval,会为每个实例分配不同的全局环境,在在此执行的 JavaScript 不会影响到外部环境。

包含两个 API。evaluate 用于同步执行代码,注意代码中不能包含静态 import,但动态 import() 是允许的;importValue 用于导入外部文件中的方法,第二个参数是 specifier,当前提案中必须提供。

  1. const sr = new ShadowRealm();
  2. // 执行代码
  3. sr.evaluate(`'hello' + 'world'`); // helloworld
  4. // 导入 foo.js 导出的 bar 函数 为 sum
  5. const sum = sr.importValue('./foo.js', 'bar');
  6. sum('hello', 'world'); // helloworld

importValue 在未来还可和 Module blocks 提案搭配使用,减少不必要的 reexport 临时文件,

  1. module insideCode {
  2. export { runTests } from 'test-framework';
  3. import './my-tests.js';
  4. }
  5. const sr = new ShadowRealm();
  6. const runTests = await sr.importValue(insideCode, 'runTests');

适用于 ShadowRealm 的场景通常和沙箱、三方库有关。比如 Web IDE 或画图应用中装载三方插件,编程应用运行用户代码,服务端跑三方库代码,微前端沙箱,Test Runner,jsdom 等。同类方案有 eval/new Function、Web Worker、iframe、node 中的 Module vm。

ShadowRealm 目前尚未有落地的浏览器实现,可通过 shadowrealms-polyfill 补丁尝鲜。需注意补丁背后通过 iframe 实现,所以只适用 Web,暂不具备跨平台能力。

Web Maker

https://github.com/chinchang/web-maker

MDH 前端周刊第 48 期:Remix Routes、ShadowRealms、Rome Formatter、Umi 4 RC 11 - 图2

开源的 HTML、CSS、JS 在线 DEMO 工具,类似 CodePen 和 JSFiddle,特点是可离线工作。

Rome Formatter

https://rome.tools/blog/2022/04/05/rome_formatter_release

MDH 前端周刊第 48 期:Remix Routes、ShadowRealms、Rome Formatter、Umi 4 RC 11 - 图3

Rome Formatter 是基于 Rust 重写后的 Rome 的第一个版本,相比 Prettier,除了快 9-12 倍,还有个重要特点是如上图所示,就算代码里有错误,也能正确格式化,这是我使用 Prettier 经常遇到的问题。

两行命令尝鲜,

  1. $ pnpm i rome@next
  2. $ pnpm rome format .

搭配 VSCode 插件 使用效果更好。

Umi 4 RC 11

https://github.com/umijs/umi-next/releases/tag/v4.0.0-rc.11

包含 4 项更新,

1、新增命令 umi lint,包含 eslint 和 stylelint 的规则和命令

lint 有两种用法,1)仅使用 umi 提供的规则配置,然后用项目里安装的 eslint 和 stylelint 执行,好处是对 IDE 友好 2)使用 umi 的 lint 命令。

用法 1 是在 .eslintrc 和 .stylelintrc里扩展 umi 的配置,

  1. {
  2. "extends": "umi/eslint"
  3. }
  1. {
  2. "extends": "umi/stylelint"
  3. }

用法 2 是直接执行 umi lint 命令,默认会用前面的配置,当然也可通过配置文件进行修改。

同时,Umi 提供的 eslint 规则我们有进行梳理,目前仅包含质量类的规则,因为我们觉得,风格类的规则应该交给 prettier 或其他同类工具。

注:由于尺寸问题,umi 没有包含 @umijs/lint(@umijs/max 内置了),使用时会提示你手动安装。

2、支持通过环境变量 SOCKET_SERVER 指定 socket 服务器,场景是 umi.js 和页面 url 不是同一个 server 时使用,比如

  1. # 指向 socket 服务器到本地 umi dev 启动的服务器
  2. $ SOCKET_SERVER=http://localhost:8000/ umi dev
  3. # 打开开发服务器,这个页面里引用 http://localhost:8000/umi.js
  4. $ open http://dev.prod.domain/

3、支持 node: 前缀的 import 语法和补丁

越来越多的库使用 node: 前缀的 import,比如 chalk、file-type 等 sindresorhus 提供的依赖。之前会报 UnhandledSchemaError 的错误,现在通过 NormalModuleReplacementPlugin 替换资源 request 进行了修复。

  1. import { join } from 'node:path';
  2. join;

4、修复项目里指定 16 及以下版本的 react 时构建报错的问题

原因是,babel-preset-react 中的配置项 runtime 和 importSource 是要搭配使用的,比如 runtime 设置为 classic 而 importSource 设置为 react 时会报错。

  1. // 如果 react >= 17
  2. runtime: 'automatic',
  3. importSource: 'react',
  4. // 如果 react < 17
  5. runtime: 'classic',
  6. importSource: undefined,

Resumability

https://www.builder.io/blog/from-static-to-interactive-why-resumability-is-the-best-alternative-to-hydration

MDH 前端周刊第 48 期:Remix Routes、ShadowRealms、Rome Formatter、Umi 4 RC 11 - 图4

Prerender 可以让 HTML 更快出来,通常的办法是 SSR 和 SSR。问题是,现在的应用通常是动态和富交互的,如何给 prerender 的 HTML 加上交互,现代框架的解法是 Hydration。

Hydration 需要加载完整的 JS Bundle、执行代码、关联 event hanlder、恢复应用 state、重建组件树,这一系列的步骤相对来说都是非常慢的,让 TTI 时间变慢。

MDH 前端周刊第 48 期:Remix Routes、ShadowRealms、Rome Formatter、Umi 4 RC 11 - 图5

对于 Hydration 慢的问题,社区已在尝试其他解,比如序列化,通过解析 JSON 来恢复页面状态,让可交互时间变得很短。但问题是,状态可以序列化,而事件、组件树要做序列化的难度很大,因为要考虑闭包、Promise、资源引用等。

作者团队给的解是 Qwik 框架,通过框架让页面可恢复,从而让 TTI 时间降到最小。

Node 202203

https://simonplend.com/whats-new-in-node-js-core-march-2022-edition/

以下是我觉得重要的部分,

1、Node 17.0 内置全局的 structuredClone() 方法,用于 deep clone

2、Node 16.14 和 Node 17.3 支持 AbortSignal.timeout(),可用于自动取消 fetch

  1. try {
  2. const signal = AbortSignal.timeout(2000);
  3. await fetch(url, { signal });
  4. } catch(e) {
  5. if (e.name === 'AbortError') { ... }
  6. }

3、Node 17.5 引入 Fetch API,其中 FormData 在 17.6 引入,需通过 --experimental-fetch Flag 开启

4、Node 17.1 和 Node 16.14 支持 ES Modules 里 import JSON 文件,需要 --experimental-json-modules 开启,17.5 之后不需要 Flag

  1. import x from './package.json' assert { type: 'json' };

发布

以下是上周社区的其他重要发布。

周刊一锅端

小结

以上就是本期我的分享。如果需要文内资讯的链接,请点击「查看原文」进入语雀查看。持续更新不易,如果你喜欢本周刊,请转发给你的朋友,告诉他们到这里来订阅,这是对我最大的帮助。下期见!

MDH,让开发者有笑容 :)