Title
Pcrab's Blog

Web Components 开发配置

最近研究了一下 undefined,使用 undefinedundefinedundefined 来创建一个可用的组件。

当前的问题

现在在开发时,第三方组件库是一个很常用的选项。我们会通过 undefinedundefined 等等组件库来进行搭建。

使用这些组件库最大的缺点就在于,它们都限定了页面所使用的框架。这样一来能使用这些组件库的用户就被限定在了 规定的框架中,甚至是规定的版本中。

不仅如此,由于现在的页面越来越复杂,更容易出现样式冲突的问题,而且没有很好的隔离方案。在出现样式问题时, 更难调试与解决。

因此可以通过 Web Components 解决上述问题。

Web Components 介绍

根据 undefined 的介绍,Web Components 是一套创建可重用的自定义元素的技术, 可以在任何地方使用定义出的这些元素。

Web Components 可以被渲染在 Shadow DOM 中,其最大的好处在于不会将真实的 DOM 结构暴露出来,而且能够不被外界的样式所影响, 因此基本不会存在样式冲突的问题。

当然,Web Components 也存在一定的缺点,例如虽然能够隔离样式,但如果外界真的需要设置其中的样式时,会非常困难。而且如果页面需要多个组件之间的联动功能, 实现起来也相对会比较困难一些。

这里只是一些简单的介绍,如果想要更详细一些的介绍可以参阅掘金的这篇 undefined

目前尝试的配置

目前正在尝试使用 Solid.js,Vite 以及 UnoCSS 来进行开发。

Solid.js

选择 Solid.js 的原因是它可以用 JSX 编写组件,又有着 signal 以及很小的打包后体积,我认为很适合用于 Web Components 开发这种相对轻量的场景。

Solid.js 开发 Web Components 有一个 undefined 库,能够很方便地创建一个 Web Component。

import { customElement } from 'solid-element';

customElement('my-component', {someProp: 'one', otherProp: 'two'}, (props, { element }) => {
    return <div>Web Components with Solid.js</div>
})

其中第二个参数是可选的,在此声明了可以传给第三个参数创建的组件的 props。需要注意必须在此处列出的 props 才能正确传递给组件。

Vite

由于 Solid.js 官方推荐使用 Vite 进行开发,因此在创建这个 Web Components 组件项目时也希望能够使用 Vite。由于 Vite 主要用于页面的开发,因此对于这种情况 需要做一些额外配置。

import { defineConfig } from "vite";
import { resolve } from "path";
import solidPlugin from "vite-plugin-solid";

export default defineConfig({
  plugins: [
    solidPlugin(),
  ],
  build: {
    lib: {
      entry: resolve(__dirname, "src/index.tsx"),
      fileName: "my-component",
      formats: ["es", "cjs"],
    },
    minify: true,
    outDir: "dist/assets",
  },
});

通过配置成 lib 模式来生成最后的组件 js 文件。

在预览时,Vite 需要一个 index.html 文件,在其中会引入 ts 文件。而在 lib 模式下打包时,不会生成一个引用对应 js 文件的 html,因此选择将 outDit 设置 为 dist/assets,就是可以在 dist 中放置一个 html 文件,手动引用对应 js 文件来查看打包后的效果。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Test Web Components</title>
</head>

<body>
  <script src="/assets/my-component.js" type="module"></script>
  <my-component someProp="oneone" otherProp="twotwo"></my-component>
</body>

</html>

这样就能直接看到打包后的成果。

UnoCSS

UnoCSS 是最近很喜欢用的原子化 CSS 库,而且是 Vite 的作者写的,与 Vite 集成得很好,用起来也很方便。但是 在 Web Components 中使用时,只成功导入了 preflight 中的内容,因此最终选择通过 cli 的方式使用。

package.json 中的 devbuild 脚本中加入

unocss \"src/**/*.tsx\" -o src/index.css

dev 还可以补上 --watch 来监听文件变化实时生成 CSS。

随后,在入口文件中,引入生成的 CSS 文件,将其内容插入到一个 style 标签中即可。

import { customElement } from 'solid-element';
import style from "./index.css?inline";

const MyComponent = () => {
    return (
        <>
            <style>
                {style}
            </style>
            <div class="p-2"></div>
        </>
    );
}

customElement("my-component", {someProp: 'one', otherProp: 'two'}, MyComponent);
本作品采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 许可协议 进行许可。