本篇依然来自于我们的 《前端周刊》 项目!
由团队成员 田八 翻译,欢迎大家 进群 持续追踪全球最新前端资讯!!
原文地址:Frontend Masters

公认的好方案™:在构建任何形式的数字信息页面时,最佳实践是通过组件,再由这些组件组合成完整的界面。这个可以有很多种细分方式,但通常来说:一个组件就是该界面所需功能中一个相对独立、合理的部分。比如在网站中,像页眉、页脚、网格、卡片、按钮等元素,就可以看作一个个组件。这也就是所谓的设计系统。相关概念可以参考"原子设计"(Atomic Design)。
JavaScript
框架兴起带来的一个意外收获是,它们进一步巩固了这一理念。React
、Vue
、Svelte
......你使用它们的方式就是通过构建组件并将它们组合在一起。这正是它们的核心所在。
我十分认同这样一种理念:像 JavaScript
框架这样的用户态工具不断突破边界,进而推动 Web
平台本身的演进,最终使其不再依赖这些工具。那么,我们是否能够构建一个基于组件化结构的项目,且完全不依赖构建流程与框架?我们离这个目标很近了。
这是我想要构建网站的示例:

这些组件(在我们的简单示例中,按钮、卡片和标题)都是:
- 在文件夹内
components
,每个文件夹都有自己命名的文件夹(有组织结构!) - 有一个用于其模板和逻辑的文件
- 有一个单独的
CSS
文件
像这样:

这种逻辑上的分组和隔离,是我觉得在搭建组件架构时比较合理的方式。更复杂的项目里,一个组件可能还会有 .graphql 文件
、自己的图片
、测试用例
等等。而把相关文件同地部署真的很重要,能让代码更容易维护。
我们该如何集成那些 component.js
和 component.css
文件呢?这个问题困扰了我很久。 打包工具可以完成这项工作。例如 webpack
发明了一套自己的处理方法。如果你在一段由 webpack
处理的 JavaScript
文件里写上 import "./card.css";
,webpack
就会明白你的意思,并以某种方式确保这个 CSS
文件最终被加载到页面上。 同样地,Vite也有它自己的一套处理机制:
导入
.css
文件时,打包工具会通过<style>
标签将其内容注入到页面中,并支持热更新。
这很棒,但我们现在想尝试的是原生方式。没有打包/构建流程。我们该如何导入这样的 CSS
呢?
引入 CSS 模块脚本
好消息: JavaScript
对我们刚刚提出的问题已经给出了解决方案,它被称为 CSS 模块脚本。
坏消息: 只有 Chrome
支持它。(WebKit 异常;Firefox 异常)
谷歌的博客文章(链接见上文)是为数不多的关于它们的信息之一,其中还包含一些 错误的语法 ,所以要小心。它应该是这样的(如果你看到 assert
它是过时的/错误的,with
关键字是正确的):
python
import sheet from './styles.css' with { type: 'css' };
当您这样做时(在支持该特性的浏览器中),sheet
就会成为一份"可构造样式表",然后您可以使用它,在我们的例子中,将其应用到一个 Web Component
的 Shadow Root
上。
scala
class MyComponent extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.adoptedStyleSheets = [sheet];
}
...
这些的"导入属性(import attributes)",我认为它们应该这么称呼,其实还能做其他事情。以这种方式导入 JSON
会得到更好的支持,例如:
python
import sheet from './data.json' with { type: 'json' };
Lit
使用 Lit 应用 styleset
(或"通过 CSS
模块脚本导入的可构造样式表")来完成整个过程,如下所示:
scala
import {html, LitElement} from 'lit';
import sheet from './button.css' with { type: 'css' };
class My Component extends LitElement {
static styles = [sheet];
...
Demo

点评
我们靠 React、Vue、Svelte 等框架来实现网页,现在浏览器也在慢慢补上,给出了原生的方案,比如 CSS 模块脚本:可以像导入 JS 一样直接 import CSS 文件,还能和 Web Components 的 Shadow DOM 配合使用,实现真正无依赖的组件架构。虽然目前只有 Chrome 支持,但方向已经很明确了。