MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Svelte组件库构建:从零开始打造自己的组件库

2022-03-246.3k 阅读

项目初始化

  1. 创建 Svelte 项目
    • 首先,确保你已经安装了 npm(Node Package Manager),这是 JavaScript 的包管理工具。如果没有安装,可以从 Node.js 官网(https://nodejs.org/)下载并安装 Node.js,npm 会随 Node.js 一同安装。
    • 使用 npm init svelte@latest 命令来初始化一个新的 Svelte 项目。执行该命令后,会提示你输入项目名称,例如 my - component - library
    • 接下来,会询问你一些关于项目模板的问题,比如是否使用 TypeScript,是否使用 ESLint 等。对于组件库项目,我们可以先选择不使用 TypeScript(后续可以再添加),也暂时不使用 ESLint(之后可以按需配置)。
    • 进入项目目录:cd my - component - library
  2. 安装必要依赖
    • 组件库通常需要进行打包,我们使用 rollup 来进行打包。rollup 是一个 JavaScript 模块打包器,它可以将多个小的模块打包成一个或多个大的文件,供浏览器或其他环境使用。
    • 安装 rollup 及其相关插件:
      npm install --save - dev rollup rollup - plugin - commonjs rollup - plugin - json rollup - plugin - node - resolve rollup - plugin - svelte rollup - plugin - terser
      
      • rollup - plugin - commonjs:用于将 CommonJS 模块转换为 ES6 模块,因为很多第三方库使用的是 CommonJS 规范,而 Svelte 项目使用 ES6 模块。
      • rollup - plugin - json:允许我们在项目中导入 JSON 文件。
      • rollup - plugin - node - resolve:帮助 rollup 找到 node_modules 中的模块。
      • rollup - plugin - svelte:用于处理 Svelte 组件,将 Svelte 组件编译为 JavaScript 代码。
      • rollup - plugin - terser:用于压缩打包后的代码,减小文件体积。
    • 为了在开发过程中方便地预览组件,我们安装 svelte - kit
      npm install --save - dev @sveltejs/kit
      

目录结构规划

  1. src 目录
    • components:这个文件夹将存放我们所有的组件。例如,我们可以创建一个 Button 组件,它的文件结构如下:
      src/components/Button
        ├── Button.svelte
        ├── Button.css
        ├── index.js
      
      • Button.svelte 是 Svelte 组件的主体文件,包含组件的 HTML、CSS 和 JavaScript 逻辑。
      • Button.css 是组件的样式文件,采用局部作用域,只会应用到 Button 组件内部。
      • index.js 用于将 Button.svelte 组件导出,方便在其他地方导入使用。例如:
        import Button from './Button.svelte';
        export default Button;
        
    • styles:存放全局样式文件,比如一些通用的字体设置、颜色变量等。例如,我们可以创建一个 variables.css 文件:
      :root {
        --primary - color: #007BFF;
        --secondary - color: #6C757D;
      }
      
    • utils:这个文件夹用于存放一些工具函数。比如,我们可能有一个 formatDate.js 文件,用于格式化日期:
      export function formatDate(date) {
        const year = date.getFullYear();
        const month = (date.getMonth() + 1).toString().padStart(2, '0');
        const day = date.getDate().toString().padStart(2, '0');
        return `${year}-${month}-${day}`;
      }
      
  2. rollup.config.js
    • 在项目根目录创建 rollup.config.js 文件,这是 rollup 的配置文件。内容如下:
    import svelte from 'rollup - plugin - svelte';
    import commonjs from 'rollup - plugin - commonjs';
    import resolve from 'rollup - plugin - node - resolve';
    import json from 'rollup - plugin - json';
    import terser from 'rollup - plugin - terser';
    
    const production =!process.env.ROLLUP_WATCH;
    
    export default {
      input:'src/index.js',
      output: [
        {
          file: 'dist/my - component - library.js',
          format: 'umd',
          name:'myComponentLibrary',
          sourcemap: true
        },
        {
          file: 'dist/my - component - library.esm.js',
          format: 'esm',
          sourcemap: true
        }
      ],
      plugins: [
        svelte({
          compilerOptions: {
            dev:!production
          }
        }),
        resolve({
          browser: true,
          dedupe: ['svelte']
        }),
        json(),
        commonjs(),
        production && terser()
      ]
    };
    
    • 这里配置了 rollup 的输入文件为 src/index.js,输出两个文件,一个是 UMD 格式(适用于浏览器全局变量引入),另一个是 ESM 格式(适用于现代 JavaScript 模块系统)。同时,配置了各个插件的使用。

组件开发示例 - Button 组件

  1. Button.svelte
    <script>
      import { onMount } from'svelte';
      import styles from './Button.css';
    
      let buttonText = 'Click me';
      let isDisabled = false;
    
      const handleClick = () => {
        console.log('Button clicked');
      };
    
      onMount(() => {
        console.log('Button mounted');
      });
    </script>
    
    <button {isDisabled} class={styles.button} on:click={handleClick}>
      {buttonText}
    </button>
    
    • script 标签内,我们导入了 onMount 生命周期函数,用于在组件挂载到 DOM 后执行一些操作。同时导入了本地的 CSS 样式文件 Button.css
    • 定义了 buttonTextisDisabled 两个变量,分别用于显示按钮文本和控制按钮是否禁用。
    • handleClick 函数是按钮点击时执行的逻辑,这里简单地在控制台打印一条信息。
    • button 标签上,通过 {isDisabled} 绑定按钮的禁用状态,通过 class={styles.button} 应用本地 CSS 样式,通过 on:click={handleClick} 绑定点击事件。
  2. Button.css

.button { padding: 10px 20px; background - color: var(--primary - color); color: white; border: none; border - radius: 5px; cursor: pointer; }

.button:disabled { background - color: var(--secondary - color); cursor: not - allowed; }

- 这里定义了按钮的基本样式,包括背景颜色、文字颜色、边框等。同时,定义了按钮禁用时的样式。

### 组件导出与引用
1. **在 src/index.js 中导出组件**:
- 在 `src/index.js` 文件中,我们需要将所有组件导出,以便外部使用。假设我们只有 `Button` 组件,文件内容如下:
```javascript
import Button from './components/Button/index.js';

export { Button };
  1. 在项目中引用组件
    • 如果我们在项目的 App.svelte 中想要使用 Button 组件,可以这样做:
    <script>
      import { Button } from './src';
    </script>
    
    <main>
      <Button buttonText="Custom text" />
    </main>
    
    <style>
      main {
        padding: 20px;
      }
    </style>
    
    • 首先在 script 标签中导入 Button 组件,然后在 main 标签内使用 Button 组件,并通过 buttonText 属性传递自定义的按钮文本。

文档编写

  1. 使用工具生成文档
    • 对于 Svelte 组件库,我们可以使用 svelte - docgen 来生成文档。首先安装它:
      npm install --save - dev svelte - docgen
      
    • package.json 中添加脚本:
      "scripts": {
        "generate:docs": "svelte - docgen src/components - o docs"
      }
      
    • 上述脚本会扫描 src/components 目录下的所有 Svelte 组件,并在 docs 目录生成文档。
  2. 手动编写文档
    • 除了使用工具生成文档,我们也可以手动编写详细的文档。在项目根目录创建一个 docs 文件夹。

    • 对于 Button 组件,可以创建一个 Button.md 文件,内容如下:

      Button 组件

      概述

      Button 组件用于触发操作,是用户与界面交互的重要元素。

      使用方法

      <script>
        import { Button } from './src';
      </script>
      
      <Button buttonText="Custom text" />
      

      属性

      • buttonText:类型为字符串,用于设置按钮显示的文本,默认值为 'Click me'
      • isDisabled:类型为布尔值,用于控制按钮是否禁用,默认值为 false

      事件

      • click:按钮被点击时触发,在组件内部的 handleClick 函数中定义了点击后的逻辑(当前为在控制台打印信息)。

测试组件

  1. 安装测试框架
    • 对于 Svelte 组件,我们可以使用 vitest@testing - library/svelte 来进行测试。首先安装它们:
      npm install --save - dev vitest @testing - library/svelte
      
    • package.json 中添加测试脚本:
      "scripts": {
        "test": "vitest"
      }
      
  2. 编写测试用例 - 以 Button 组件为例
    • src/components/Button 目录下创建 Button.test.js 文件:
    import { render, screen } from '@testing - library/svelte';
    import Button from './Button.svelte';
    
    describe('Button component', () => {
      it('should display the correct text', () => {
        render(Button, { buttonText: 'Test text' });
        const buttonElement = screen.getByText('Test text');
        expect(buttonElement).toBeInTheDocument();
      });
    
      it('should call the click handler', () => {
        const handleClick = vi.fn();
        render(Button, { buttonText: 'Click me', handleClick });
        const buttonElement = screen.getByText('Click me');
        buttonElement.click();
        expect(handleClick).toHaveBeenCalled();
      });
    });
    
    • 第一个测试用例 should display the correct text 检查按钮是否显示了正确的文本。通过 render 函数渲染 Button 组件,并传递 buttonText 属性,然后使用 screen.getByText 获取按钮元素,并通过 expect 断言按钮元素在文档中。
    • 第二个测试用例 should call the click handler 检查按钮点击时是否调用了点击处理函数。通过 vi.fn() 创建一个模拟函数 handleClick,传递给 Button 组件,点击按钮后,使用 expect(handleClick).toHaveBeenCalled() 断言模拟函数被调用。

发布组件库

  1. 准备工作
    • 确保在 package.json 中设置了正确的 nameversiondescriptionmain(指向打包后的 UMD 文件路径,例如 dist/my - component - library.js)、module(指向打包后的 ESM 文件路径,例如 dist/my - component - library.esm.js)等字段。
    • 例如:
    {
      "name": "my - component - library",
      "version": "1.0.0",
      "description": "My custom Svelte component library",
      "main": "dist/my - component - library.js",
      "module": "dist/my - component - library.esm.js",
      "scripts": {
        "build": "rollup - c",
        "generate:docs": "svelte - docgen src/components - o docs",
        "test": "vitest"
      },
      "keywords": [
        "svelte",
        "components",
        "library"
      ],
      "author": "Your Name",
      "license": "MIT"
    }
    
  2. 发布到 npm
    • 首先,确保你已经在 npm 官网(https://www.npmjs.com/)注册了账号。
    • 登录 npm:在终端执行 npm login,按照提示输入用户名、密码和邮箱。
    • 构建组件库:执行 npm run build 命令,生成打包后的文件。
    • 发布组件库:执行 npm publish 命令,将组件库发布到 npm 仓库。发布成功后,其他开发者就可以通过 npm install my - component - library 来安装和使用你的组件库了。

通过以上步骤,我们就从零开始打造了一个 Svelte 组件库,涵盖了项目初始化、组件开发、文档编写、测试以及发布等各个方面。在实际开发中,可以根据具体需求不断扩展和完善组件库的功能和组件种类。