前端快讯|Lit 3.0 已发布,再见 IE,你好 TC39 装饰器!
【前端快讯 10月11日】经过数月的开发,Lit 团队很高兴地宣布 Lit 3.0 的最终版本发布,该版本是自2021年初 Lit 2.0 以来的第一个主要版本,还有 Lit Labs 套件 @lit/react
、@lit/task
和 @lit/context
的首次发布,以及两个额外的发布 @lit-labs/compiler
和 @lit-labs/preact-signals
。
这是一个大版本,主要包含:
Lit 3.0 全新的 Lit 模板编译器 Preact Signals 信号集成
Lit 3.0:再见 IE,你好 TC39 装饰器!
Lit 团队非常重视社区的稳定性。任何用户和整个生态系统都必须承担破坏性更改的成本:项目必须进行升级,应用程序中可以包含多个版本,并且文档、示例、教程、启动套件等必须针对每个破坏性更改进行更新。
因此,Lit 团队只希望在必须时或者当对社区的好处明显超过成本时才进行破坏性更改。对于好处,团队通常寻求减小代码量、提高性能、减少维护负担和更好地与标准对齐。
团队还遵循语义版本管理,因此只有在出现重大变更时,他们才会增加主版本。新功能通常会出现在新的次版本中,而这些次版本是向后兼容的。因此,Lit 3.0旨在仅作为一个破坏性更改,而没有新增功能。不过,有一个例外——标准装饰器!
破坏性更改
对于 Lit 3.0,最大的破坏性更改是Lit 团队放弃了对 IE11 的支持。在调查了Lit 的开发者社区之后,团队认为现在是时候告别IE了,而且很少有用户会受到影响。
此版本还是一个机会,可以进行一些其他破坏性更改,以清除一些技术债务,为 Lit 的3.x版本系列及以后预定的新功能铺平道路。
这些更改对大多数用户来说应该是次要的。如果您使用 Lit 2.x 且没有使用任何弃用警告,并且使用支持现代 JS 的工具链,则应该可以无缝升级!
以下是Lit 3.0的主要变化:
不再支持 IE11。 Lit的 npm 模块现已发布为 ES2021。 删除了 Lit 2.0 版本中废弃的 API。 SSR hydration支持模块已移至 @lit-labs/ssr-client
包。在TypeScript 实验性装饰器和标准装饰器之间统一装饰器行为。 不再支持 Babel 装饰器 "2018-09" 版本
新功能:支持标准装饰器
Lit 团队在 Lit 3.0 中添加的一个新功能是为现有的装饰器添加了对 TC39 标准装饰器规范的支持。
新的装饰器规范在 TC39 中已经达到了第三阶段,这意味着浏览器和编译器现在都在实施它们。这是 Lit 迈出的一大步!标准装饰器的出现让Lit 可以开始转向无需编译器即可使用的装饰器实现。
Lit 团队非常重视让从实验性装饰器升级到标准装饰器的路径尽可能顺畅。为了实现这一点,团队使现有的装饰器支持标准规范,并使它们能够与实验性装饰器模式中的新访问器关键字配合使用。
这样,您就可以使用带有自动访问器(使用访问器关键字)的 Lit 装饰器,从而使同一调用站点在两种设置下都能正常工作:
class MyElement extends LitElement {
@property()
accessor myProperty = 'hello';
}
一旦您的项目中的所有装饰器调用站点都使用了 accessor
关键字,您可以在experimentalDecorators
设置为 true
或 false
时进行构建而无需改变行为。
但是,为了使这些混合装饰器在两种模式下具有一致的行为,Lit 团队不得不对自己的实验装饰器进行一些次要的破坏性更改:
Lit 现在会自动调用 @property
和@state
装饰的访问器的requestUpdate()
,以前这是 settter 的责任。在第一次渲染时读取访问器的值,并将其用作 changedProperties
和属性反射的初始值。@property和@state必须用于手动编写的访问器的setter。
标准装饰器模式要求使用 TypeScript 5.2 或具有 @babel/plugin-proposal-decorators
插件且装饰器版本为 2023-05
的 Babel 7.23。
升级
对于绝大多数用户来说,从 Lit 2.0 升级应该是无缝的。通常可以通过以下方式升级 npm 依赖版本:
npm i lit@latest
使用新的 Lit 模板编译器实现更快的渲染速度
全新的 @lit-labs/compiler
包提供了一个 TypeScript 转换器,可在 JavaScript 或 TypeScript 文件上运行,对 Lit 模板进行构建时准备,这些准备通常在运行时由 Lit 完成。
配图:compiler-benchemark
虽然并非所有模板都能通过编译提高渲染性能,但在 "重模板 "基准测试中,我们测得首次渲染速度提高了 46%,更新速度提高了 21%!
要在今天试用 @lit-labs/compiler
,您需要一个接受 TypeScript 转换器的构建步骤。对于 Rollup.js
用户,可以使用 @rollup/plugin-typescript
。Rollup.config.js
文件的示例如下:
// File: rollup.config.js
import typescript from '@rollup/plugin-typescript';
import {compileLitTemplates} from '@lit-labs/compiler';
export default {
// ...
plugins: [
typescript({
transformers: {
before: [compileLitTemplates()],
},
}),
// other rollup plugins
],
};
转换器的作用?
给定一些包含用于声明模板的 html
标签函数的源代码:
const hi = (name) => html`<h1>Hello ${name}!</h1>`;
Lit模板转换将删除html标签函数,并用类似以下内容替换:
const b = (s) => s;
const lit_template_1 = {h: b`<h1>Hello <?></h1>`, parts: [{type: 2, index: 1}]};
const hi = (name) => ({_$litType$: lit_template_1, values: [name]});
团队称之为编译模板,它的行为与您编写的模板相同,只是当 Lit 渲染编译模板时,可以跳过内部的渲染阶段(称为准备阶段),这意味着您会获得更快的初始渲染。
正如您在上面的示例中所看到的,转换过程中生成了一些额外的代码。Lit 团队已经测量过,经过缩小和压缩,编译文件的文件大小可能会增加 5%。团队计划解决这个问题。
展望未来
Lit 团队很想听取您对使用这个转换过程的体验的反馈,以及您希望看到哪些优化!请在这个实验室反馈讨论中留下您的意见。Lit 团队还想了解Lit使用的构建系统,并欢迎贡献!
这仅仅是个开始。有了这个新软件包,Lit 团队就有了在构建时进行更多优化的基础。团队已经考虑了一些优化方案:
对于可以完全编译的 Lit 应用程序,我们可以提供更小的 lit-html
导入。在编译器转换中添加一个选项,将模板中的 HTML 也最小化。 对 Lit API 的其他部分进行编译时评估,例如编译掉内置的 Lit 装饰器。 通过应用特定领域的文件压缩功能来压缩输出文件。
Preact Signals 集成
Signals:它现在非常热门!
许多框架正在采用信号 - 用于性能和开发体验改进的反应式状态和计算 - 来提升表现。Lit 已经拥有非常高效的渲染系统,我们的初步基准测试并未显示出信号的明显性能优势。
对于 Lit 开发人员来说,Lit 团队认为信号有望为共享可观察状态提供一个方便且相对简单的选择,而这正是社区的一个经常性需求。因此,Lit 团队开始探索如何通过新的 @lit-labs/preact-signals 软件包将信号与 Lit 集成。
对于 Lit 开发人员,Lit 团队认为信号承诺提供了一种方便且相对简单的共享可观察状态的选项,这是社区中经常需要的。因此,Lit 团队开始探索如何使用一个新的 @lit-labs/preact-signals
包将信号与 Lit 集成。
该软件包提供了三种使用 Preact Signals 的方式:
SignalWatcher mixin,可以使组件自动监视更新过程中使用的所有信号。 watch()指令,用于监视一个信号并将其更新到绑定上。 一个特殊的 html 模板标签,可以自动将 watch()
指令应用于使用信号的所有绑定。
以下是使用 SignalWatcher mixin 的示例:
import {LitElement, html} from 'lit';
import {customElement, property} from 'lit';
import {SignalWatcher, signal} from '@lit-labs/preact-signals';
const count = signal(0);
@customElement('signal-example')
export class SignalExample extends SignalWatcher(LitElement) {
render() {
return html`
<p>The count is ${count.value}</p>
<button @click=${this._onClick}>Increment</button>
`;
}
private _onClick() {
// A change to the signal value causes the element to re-render!
count.value = count.value + 1;
}
}
为什么选择Preact Signals信号
在 Web组件 中存在的一个问题是,有许多不同的信号实现,并且它们之间没有互操作性。这与 Web组件的互操作性目标相悖。因此,目前Lit 团队计划不建立自己的信号包,也不选择他们认可的信号包,而是计划提供集成包,以便在 Lit 中使用各种信号库。
这些集成将相对简单,因为 Lit 有两种直接使用信号的方式:
将组件的更新生命周期视为一个效果,这样当访问的任何信号(比如在模板中)发生变化时,它就会被执行。这样可以将信号与Lit的批处理异步生命周期结合起来,以实现良好的性能。 使用指令将信号直接连接到 DOM 中的位置。
Lit 选择 Preact 的信号库作为首次集成,因为它是一个相对小巧、快速、易于理解的实现,并以标准 JS 模块的形式发布到 npm。
最后
鹅厂的 Web Components 框架——omi
(https://github.com/Tencent/omi) 已发布 v7.0.0-rc4 版本,欢迎大家了解和 star。
大家都在看