news 2026/9/13 16:47:00

从 CHANGELOG 读懂 lit-starter-js:Lit 3 起始模板的工程化实践与版本演进路线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 CHANGELOG 读懂 lit-starter-js:Lit 3 起始模板的工程化实践与版本演进路线

从 CHANGELOG 读懂 lit-starter-js:Lit 3 起始模板的工程化实践与版本演进路线

【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit

@lit/lit-starter-js是 Lit 官方仓库中面向 JavaScript 开发者的 Web Component 起始模板包,其 CHANGELOG.md 完整记录了该模板从 1.0.0 到 2.0.2 的演进过程。本文以这份变更日志为骨架,结合仓库内my-element.jsrollup.config.jsweb-test-runner.config.js等真实源码,逐版本解读其中的关键工程决策——从放弃 IE11、引入MODE=dev/prod双模式、统一打包压缩链路,到测试与文档自动化。读完本文,你将理解 Lit 起始模板的构建、测试、文档生成整套工程实践,并能据此评估自己的 Lit 项目在升级时需要注意的变更点。

一、包定位:lit-starter-js 在 Lit 生态中的角色

packages/lit-starter-js是一个"private": true的示例模板包,其package.jsonname@lit/lit-starter-jsversion2.0.2description为 "A simple web component"。它并不是一个发布到 npm 供生产使用的库,而是由npm create类脚手架生成的起始项目模板——你可以把它复制出来作为自己组件库的起点。

模板的核心组件定义在 my-element.js:

import {LitElement, html, css} from 'lit'; export class MyElement extends LitElement { static get styles() { return css` :host { display: block; border: solid 1px gray; padding: 16px; max-width: 800px; } `; } static get properties() { return { name: {type: String}, count: {type: Number}, }; } constructor() { super(); this.name = 'World'; this.count = 0; } render() { return html` <h1>${this.sayHello(this.name)}!</h1> <button @click=${this._onClick} part="button"> Click Count: ${this.count} </button> <slot></slot> `; } _onClick() { this.count++; this.dispatchEvent(new CustomEvent('count-changed')); } sayHello(name) { return `Hello, ${name}`; } } window.customElements.define('my-element', MyElement);

这份源码演示了 LitElement 的四个核心能力:css标签定义的 Shadow DOM 样式(:hostpadding等)、properties声明的响应式属性(name/count)、render()中的声明式模板(事件绑定@clickpart="button"暴露给外部样式、<slot>投影)、以及通过CustomEvent('count-changed')对外通信。模板依赖lit@^3.2.0,对应 Lit 3.x 版本线。

二、2.0 大版本:从 Lit 2 到 Lit 3 的迁移信号

CHANGELOG 的 2.0.0 条目标记为Major Changes,其中明确列出的破坏性变更有:

  • Drop IE11 support(PR #3756):Lit 3.0 彻底移除对 IE11 的支持,这也是 2.0.0 大版本最核心的破坏性变更;
  • 依赖同步升级为lit@3.0.0

结合模板 README.md 中 "About this release" 一节,Lit 3.0 相对 2.0 的破坏性变更很少,总共三点:

  1. 放弃 IE11;
  2. 以 ES2021 标准发布产物;
  3. 移除少量已废弃的 Lit 1.x API。

README 还给出了一个实用的兼容性结论:绝大多数用户从 Lit 2 升级到 Lit 3 不需要改动代码,应用或库可以同时兼容两个大版本,例如把依赖范围写成"^2.7.0 || ^3.0.0";且 Lit 2.x 与 3.x 是互操作的——模板、基类、指令、装饰器可以跨版本混用。

对模板使用者的直接含义:如果你还在维护需要支持 IE11 的旧项目,应停留在 lit-starter-js 1.x 线;如果你的目标浏览器是现代浏览器(支持 ES2021 模块、attachShadowgetRootNode),可以放心升级到 2.x 模板,因为它已经围绕现代浏览器的能力设计。

三、MODE=dev/prod 双模式机制:模板的"调试开关"

CHANGELOG 的 1.0.0 条目记录了一项重要功能:

Added Lit dev mode to test and serve commands, controlled via the MODE=dev or MODE=prod environment variables.

这一机制在两个配置文件中都有落地实现。

3.1 开发服务器端的实现

web-dev-server.config.js 中通过MODE环境变量控制nodeResolve的导出条件:

const mode = process.env.MODE || 'dev'; if (!['dev', 'prod'].includes(mode)) { throw new Error(`MODE must be "dev" or "prod", was "${mode}"`); } export default { nodeResolve: {exportConditions: mode === 'dev' ? ['development'] : []}, preserveSymlinks: true, plugins: [ legacyPlugin({ polyfills: { // Manually imported in index.html file webcomponents: false, }, }), ], };

MODE=dev时,exportConditions包含development,会解析到 Lit 的开发构建产物(带更详细的报错信息);当MODE=prod时为空数组,解析到生产构建产物。注意MODE默认值为dev,且只接受dev/prod两个取值,传其他值会直接抛错——这是模板内置的防呆校验。

3.2 测试端的实现

web-test-runner.config.js 中使用了完全相同的模式约定:

const mode = process.env.MODE || 'dev'; if (!['dev', 'prod'].includes(mode)) { throw new Error(`MODE must be "dev" or "prod", was "${mode}"`); } // ... export default { rootDir: '.', files: ['./test/**/*_test.js'], nodeResolve: {exportConditions: mode === 'dev' ? ['development'] : []}, preserveSymlinks: true, browsers: commandLineBrowsers ?? Object.values(browsers), testFramework: { config: { ui: 'tdd', timeout: '60000', }, }, plugins: [ legacyPlugin({ polyfills: { webcomponents: true, custom: [ { name: 'lit-polyfill-support', path: 'node_modules/lit/polyfill-support.js', test: "!('attachShadow' in Element.prototype) || !('getRootNode' in Element.prototype) || window.ShadyDOM && window.ShadyDOM.force", module: false, }, ], }, }), ], };

除了同样受MODE控制的双模式解析外,该配置还包含几个值得注意的细节:

  • 默认通过 Playwright 启动chromiumfirefoxwebkit三个浏览器运行测试,也可以通过BROWSERS=chromium,firefox npm run test指定子集;配置文件中还预留了 Sauce Labs 与 BrowserStack 云端测试的注释示例;
  • legacyPlugin会在不支持 Web Component 的旧浏览器上注入webcomponentspolyfill,并额外注入 Lit 的polyfill-support模块(路径为node_modules/lit/polyfill-support.js),这是 Lit 与 webcomponents polyfill 协同工作的必要胶水层;
  • 测试框架使用 Mocha 的 TDD 风格(ui: 'tdd'),超时 60 秒。

3.3 对应的 npm scripts

package.json 中的脚本完整体现了双模式设计:

"serve": "wds --watch", "serve:prod": "MODE=prod npm run serve", "test": "npm run test:dev && npm run test:prod", "test:dev": "wtr", "test:watch": "wtr --watch", "test:prod": "MODE=prod wtr", "test:prod:watch": "MODE=prod wtr --watch"
  • npm test会先跑 dev 模式测试、再跑 prod 模式测试,保证代码在两种构建下行为一致;
  • npm run serve默认 dev 模式,npm run serve:prod切换为生产模式;
  • npm test:watch在每次源码变更时以 dev 模式重跑测试。

与之配套,根目录的 index.html 提供了指向/dev/index.html组件示例的入口链接,而 dev/index.html 演示了如何在浏览器中加载组件——手动引入webcomponents-loader.jslit/polyfill-support.js,再以<script type="module">方式加载my-element.js

四、打包与压缩:从 Terser 依赖更新看构建链路

CHANGELOG 中有多条与打包相关的条目:

  • 1.0.3:更新 Rollup 及 Rollup 插件;
  • 1.0.5:更新@rollup/plugin-replace
  • 1.0.6:Improve bundling and minification recommendations(改进打包与压缩建议);
  • 2.0.2:更新 Rollup 与 Terser 依赖。

这些变更的实际落点就是 rollup.config.js:

import summary from 'rollup-plugin-summary'; import {terser} from 'rollup-plugin-terser'; import resolve from '@rollup/plugin-node-resolve'; import replace from '@rollup/plugin-replace'; export default { input: 'my-element.js', output: { file: 'my-element.bundled.js', format: 'esm', }, onwarn(warning) { if (warning.code !== 'THIS_IS_UNDEFINED') { console.error(`(!) ${warning.message}`); } }, plugins: [ replace({preventAssignment: false, 'Reflect.decorate': 'undefined'}), resolve(), terser({ ecma: 2021, module: true, warnings: true, mangle: { properties: { regex: /^__/, }, }, }), summary(), ], };

配置要点解读:

  • replace插件把Reflect.decorate替换为undefined——这是针对装饰器相关的代码路径优化,避免保留未使用的运行时逻辑;
  • terserecma: 2021为压缩目标,module: true开启 ES module 友好的压缩,mangle.properties.regex: /^__/只混淆以双下划线开头的私有属性名;
  • summary插件在构建结束后输出产物大小摘要,方便观察打包体积。

重要前提:该 Rollup 配置仅为静态文档站点生成打包产物,并不用于发布到 npm。模板 README 的 "Bundling and minification" 一节明确建议:把组件以未优化的 ES module 形式发布,在应用层做构建期优化,这样构建工具才能最大化地去重、去除死代码。这是 1.0.6 版本"改进打包与压缩建议"的核心内容——模板刻意把"发布组件"与"构建应用"两种场景分开处理。

package.json中还提供了checksize脚本,用于快速评估产物体积:

"checksize": "rollup -c ; cat my-element.bundled.js | gzip -9 | wc -c ; rm my-element.bundled.js"

该脚本先执行 Rollup 打包,再对产物做 gzip 压缩并输出字节数,最后清理临时文件。

五、测试体系:从 open-wc 测试套件到多浏览器验证

CHANGELOG 1.0.0 条目还记录了模板测试体系的确立:使用 open-wc analyzer 生成custom-elements.json,并把模板内置的 API 文档生成器更新为新清单格式。测试本身则基于@open-wc/testing@web/test-runner

test/my-element_test.js 覆盖了组件的四个核心行为:

import {MyElement} from '../my-element.js'; import {fixture, assert} from '@open-wc/testing'; import {html} from 'lit/static-html.js'; suite('my-element', () => { test('is defined', () => { const el = document.createElement('my-element'); assert.instanceOf(el, MyElement); }); test('renders with default values', async () => { const el = await fixture(html`<my-element></my-element>`); assert.shadowDom.equal(el, ` <h1>Hello, World!</h1> <button part="button">Click Count: 0</button> <slot></slot> `); }); test('renders with a set name', async () => { const el = await fixture(html`<my-element name="Test"></my-element>`); assert.shadowDom.equal(el, ` <h1>Hello, Test!</h1> <button part="button">Click Count: 0</button> <slot></slot> `); }); test('handles a click', async () => { const el = await fixture(html`<my-element></my-element>`); const button = el.shadowRoot.querySelector('button'); button.click(); await el.updateComplete; assert.shadowDom.equal(el, ` <h1>Hello, World!</h1> <button part="button">Click Count: 1</button> <slot></slot> `); }); test('styling applied', async () => { const el = await fixture(html`<my-element></my-element>`); await el.updateComplete; assert.equal(getComputedStyle(el).paddingTop, '16px'); }); });

这套测试验证了:元素注册成功、默认渲染(Hello, World!与计数 0)、属性驱动的渲染(name="Test"输出Hello, Test!)、交互后的响应式更新(点击后计数变为 1,且通过await el.updateComplete等待更新完成)、以及 Shadow DOM 样式的实际生效(paddingTop为 16px)。

六、文档与自定义元素清单:Eleventy + custom-elements.json 链路

CHANGELOG 1.0.0 的另一项变更是把模板的 API 文档生成切换到新的清单格式,具体链路如下:

  • 分析:package.json中的analyze脚本执行cem analyze --litelement --globs "**/*.js" --exclude docs,基于 Custom Elements Manifest Analyzer 扫描 JS 源码并生成custom-elements.jsonpackage.json"customElements": "custom-elements.json"字段指向该清单);
  • 文档源:站点的 Markdown 页面位于 docs-src 目录(index.mdinstall.mdexamples/等),模板与页面布局在_includes/下;
  • 生成:docs:build脚本rollup -c --file docs/my-element.bundled.js打包组件示例,docs:gen脚本通过 Eleventy(.eleventy.cjs)把 Markdown 渲染为静态站点输出到docs/目录;
  • 预览:docs:serve使用wds --root-dir=docs --node-resolve --watch本地预览文档站点。

值得留意的是,模板把生成的docs/目录直接提交进仓库,从而可以配合 GitHub Pages 的 "main branch /docs folder" 发布源设置直接托管文档站点——README 的 "Static Site" 一节对此有完整说明。

七、1.x 时代的工程细节:serve 修复与安全维护

CHANGELOG 低版本条目中还有两个容易被忽视但影响日常使用的变更:

  • 1.0.1:修复npm run serve使其正确服务根目录,并在根目录/添加指向/dev/index.html组件示例的链接。对应到仓库中就是根目录 index.html 里的<a href="/dev/index.html">Component Demo</a>;同时依赖lit@2.1.0
  • 1.0.2:更新 README,说明 issue 与 PR 应提交到 Lit 主仓库——这也是本文所依据的 CHANGELOG.md 本身位于packages/lit-starter-js/而非独立仓库的原因。
  • 2.0.1:Minor security fixes(小幅安全修复)。这提醒模板使用者:即使是示例性质的模板,也应跟随其安全修复更新。
  • 1.0.4:更新依赖并移除未使用的依赖,说明模板维护者会持续清理依赖,保持模板的最小化。

八、版本演进对照与升级建议

综合 CHANGELOG,可以把 lit-starter-js 的演进总结为两条主线:

版本变更性质关键内容
1.0.0功能确立引入MODE=dev/prod、open-wc analyzer 生成custom-elements.json、升级 TypeScript 4.4.2、依赖lit@2.0.0
1.0.1修复npm run serve服务根目录、根页面链接组件示例
1.0.2~1.0.5维护README 归属说明、依赖清理、Rollup 插件更新
1.0.6文档改进强化"发布组件 vs 应用构建"的打包压缩建议
2.0.0破坏性变更放弃 IE11、升级 TypeScript 5.x、依赖lit@3.0.0
2.0.1安全修复小幅安全修复
2.0.2维护更新 Rollup 与 Terser 依赖、依赖lit@3.2.0

对模板使用者的三条实操建议:

  1. 升级前先确认浏览器目标:2.x 模板放弃 IE11 且以 ES2021 为压缩目标,若仍须支持旧浏览器,请锁定 1.x 版本线;
  2. 善用双模式验证:保持npm test(dev+prod 两次测试)作为默认质量门禁,避免只在开发构建下通过测试而生产构建出错;
  3. 不要把模板的 Rollup 配置当作发布配置:发布组件应输出未优化的 ES module,应用构建期的压缩去重交给应用自己的构建链完成——这正是 CHANGELOG 1.0.6 版本想传达的核心建议。

九、延伸阅读

  • 模板源码与入口:my-element.js、index.html
  • 构建与配置:package.json、rollup.config.js、web-test-runner.config.js、web-dev-server.config.js
  • 测试用例:test/my_element_test.js
  • 组件演示页:dev/index.html
  • 文档站点源文件:docs-src 目录
  • TypeScript 版本模板:packages/lit-starter-ts/CHANGELOG.md(其 2.0.3 条目显示 TypeScript 依赖升级至 5.8 并同步了ariaColIndexText等 ARIAMixin 类型变更,可作为 TS 用户对照参考)

【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 16:46:34

VMD-Attention-LSTM时间序列预测:原理、源码与参数调优实战

简介&#xff1a;基于VMD-Attention-LSTM的时间序列预测模型完整项目包&#xff0c;面向深度学习初学者及需要完成课程设计、毕业设计的学生。内含VMD变分模态分解、Attention注意力机制与双层LSTM网络的完整搭建代码&#xff0c;以及数据预处理、训练、预测和模型权重保存逻辑…

作者头像 李华
网站建设 2026/9/13 16:45:16

LKY Office Tools:3 步 5 分钟完成 Office 下载、安装、激活

LKY Office Tools&#xff1a;3 步 5 分钟完成 Office 下载、安装、激活 【免费下载链接】LKY_OfficeTools 一键自动化 下载、安装、激活 Office 的利器。 项目地址: https://gitcode.com/GitHub_Trending/lk/LKY_OfficeTools 刚重装完系统&#xff0c;发现没 Office 可…

作者头像 李华
网站建设 2026/9/13 16:44:02

数据分箱技术:特征工程中的核心预处理方法

1. 分箱技术概述与核心价值分箱&#xff08;Binning&#xff09;是数据预处理中的一项基础但至关重要的技术&#xff0c;尤其在特征工程和模型训练阶段扮演着关键角色。简单来说&#xff0c;分箱就是将连续变量离散化为有限个区间&#xff08;称为"箱"或"桶&quo…

作者头像 李华
网站建设 2026/9/13 16:43:55

Django 如何覆盖第三方应用或 django.contrib.admin 的内置模板

Django 如何覆盖第三方应用或 django.contrib.admin 的内置模板 【免费下载链接】django The Web framework for perfectionists with deadlines. 项目地址: https://gitcode.com/GitHub_Trending/dj/django 当你在项目中使用了第三方应用或 django.contrib.admin 这类 …

作者头像 李华