在日常的前端开发中,经常会遇到文本处理,日期处理,文本转换等需求。通常是将它写到一个utils 文件中。问题来了,每个项目都要处理,那么文件就要重复的复制,我是个懒人。想着用rollup将它打包成一个 npm 插件,然后直接安装,之后局部引入来。这样就方便了,同时也只需要我需要的插件。这样一来随着工具函数的扩展,势必会带来一个问题,如何维护函数的使用呢?那么就需要一个文档了,文档的便于管理也是个问题,这里采用vitepess 来作为工具函数的文档官网。

npm 插件包构建

这里我根据个人需求采用的是rollup 作为插件的打包工具。

说一下我选择它的原因:

  1. 我的插件是纯工具函数,所以不需要 html 的渲染,那么vite就不在我的考虑,vite 主要还是应用在界面插件的开发上,会比较好一点,
  2. rollup 使用了 ES6 修订版 JavaScript 中包含的代码模块的新标准化格式,而不是以前的特定解决方案,如 CommonJSAMD。这意味着可以自由无缝地组合你最喜欢的库中最有用的单个函数。实现局部加载的功能。
  3. Tree-Shaking会静态分析您导入的代码,并排除任何未实际使用的内容**。**

步骤 1: 初始化项目

  1. 创建项目目录

    mkdir my-rollup-package
    cd my-rollup-package
    
  2. 初始化项目
    初始化一个新的 npm 项目,这将会生成一个 package.json 文件:

    pnpm init -y
    
  3. 安装开发依赖
    安装 Rollup 和所需的插件:

    pnpm install --save-dev rollup rollup-plugin-typescript2 @rollup/plugin-commonjs @rollup/plugin-babel @rollup/plugin-node-resolve rollup-plugin-node-globals rollup-plugin-node-builtins @rollup/plugin-terser @rollup/plugin-json rollup-plugin-dts rollup-plugin-import-export typescript @types/node
    
    • rollup:核心打包工具。
    • rollup-plugin-typescript2:处理 TypeScript 文件。
    • @rollup/plugin-commonjs:将 CommonJS 转换为 ES6。
    • @rollup/plugin-babel:使用 Babel 转译代码。
    • @rollup/plugin-node-resolve:解析模块。
    • rollup-plugin-node-globals:处理 Node.js 的全局变量。
    • rollup-plugin-node-builtins:处理 Node.js 的内置模块。
    • @rollup/plugin-terser:压缩代码。
    • @rollup/plugin-json:导入 JSON 文件。
    • rollup-plugin-dts:生成 TypeScript 声明文件。
    • typescript:安装 TypeScript。
    • @types/node: types 声明文件
  4. 配置 TypeScript
    添加 tsconfig.json 来配置 TypeScript:

    {
      "compilerOptions": {
        "allowJs": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "noEmit": true,
        "resolveJsonModule": true,
        "forceConsistentCasingInFileNames": true,
        "sourceMap": true,
        "strict": true,
        "target": "esnext",
        "isolatedModules": true,
        "useDefineForClassFields": true,
        "jsx": "preserve",
        "lib": ["esnext", "dom"],
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"]
        }
      },
      "exclude": ["dist", "node_modules"]
    }
    

步骤 2: 项目结构

创建项目文件夹和文件结构:

my-rollup-package/
 └── src/
 │   └── modules/ (工具函数文件)
 │   │   └── hello.ts
 │   └── index.ts (入口文件改成全体导出)
 │   └── iem.d.ts (这个文件是方便导入)
 └── dist/ (将会生成)
 └── package.json
 └── rollup.config.js
 └── tsconfig.json
  • src/index.ts 是你的主文件,它将包含你的主要代码。

步骤 3: 编写代码

src/modules/hello.ts 中添加一些简单的代码,例如一个简单的工具函数

export function greet(name: string): string {
  return `Hello, ${name}!`;
}

src/iem.d.ts 中导人所有的函数

declare module "iem:./modules/*" {
  export {};
}
  • 告诉 TypeScript,所有匹配 "iem:./modules/*" 模式的导入都是有效的模块。
  • 使用空的导出 (export {}) 来表示这些模块不导出任何内容。
  • 主要目的是让 TypeScript 理解那些通过自定义加载器或者特殊路径的模块,以确保项目正常编译,特别是在集成非标准模块加载或路径时。

src/index.ts 导出所有的工具函数

export * from "iem:./modules/**/*";

步骤 4: 配置 Rollup

创建一个名为 rollup.config.js 的文件,并粘贴给出的配置代码:

import { defineConfig } from "rollup"; // 从 rollup 导入 defineConfig 函数,用于定义配置
import ts from "rollup-plugin-typescript2"; // 导入 TypeScript 插件,用于编译 TypeScript 文件
import commonjs from "@rollup/plugin-commonjs"; // 导入 CommonJS 插件,将 CommonJS 模块转换为 ES6
import babelPlugin from "@rollup/plugin-babel"; // 导入 Babel 插件,用于转译代码
import resolve from "@rollup/plugin-node-resolve"; // 导入 Node.js 解析插件,用于解析模块
import globals from "rollup-plugin-node-globals"; // 导入插件以处理 Node.js 全局变量
import builtins from "rollup-plugin-node-builtins"; // 导入插件以处理 Node.js 内置模块
import terser from "@rollup/plugin-terser"; // 导入 Terser 插件,用于压缩 JavaScript 代码
import json from "@rollup/plugin-json"; // 导入 JSON 插件,用于导入 JSON 文件
import dts from "rollup-plugin-dts"; // 导入 DTS 插件,用于生成 TypeScript 声明文件
import { importExportPlugin } from "rollup-plugin-import-export"; // 导入自定义插件,用于处理导入和导出

// 定义 Rollup 配置
const config = defineConfig([
  {
    input: ["src/index.ts"], // 输入文件为 src/index.ts
    output: [
      {
        dir: "dist/esm", // 输出目录为 dist/esm
        format: "esm", // 输出格式为 ES Module
        preserveModules: true, // 保持模块结构
      },
      {
        dir: "dist/cjs", // 输出目录为 dist/cjs
        format: "cjs", // 输出格式为 CommonJS
        preserveModules: true, // 保持模块结构
      },
    ],
    plugins: [
      importExportPlugin(), // 使用自定义导入导出插件
      ts(), // 添加 TypeScript 插件
      babelPlugin({ exclude: "**/node_modules/**" }), // 添加 Babel 插件,排除 node_modules
      json(), // 添加 JSON 插件
      commonjs(), // 添加 CommonJS 插件
    ],
  },
  {
    input: "src/index.ts", // 再次使用 src/index.ts 作为输入
    output: [
      {
        file: "dist/umd/index.js", // 输出文件为 dist/umd/index.js
        format: "umd", // 输出格式为 UMD
        name: "utils", // UMD 格式时的全局变量名
      },
    ],
    plugins: [
      importExportPlugin(), // 使用自定义导入导出插件
      ts(), // 添加 TypeScript 插件
      babelPlugin({ exclude: "**/node_modules/**" }), // 添加 Babel 插件,排除 node_modules
      json(), // 添加 JSON 插件
      commonjs(), // 添加 CommonJS 插件
      resolve({ preferBuiltins: true, mainFields: ["browser"] }), // 添加解析插件,优先使用内置模块
      globals(), // 添加全局变量插件
      builtins(), // 添加内置模块插件
      terser(), // 添加压缩插件
    ],
  },
  {
    input: "src/index.ts", // 输入文件为 src/index.ts
    output: {
      dir: "dist/types", // 输出目录为 dist/types
      format: "esm", // 输出格式为 ES Module
      preserveModules: true, // 保持模块结构
    },
    plugins: [importExportPlugin(), dts()], // 使用自定义插件和 DTS 插件生成声明文件
  },
]);

export default config; // 导出配置

步骤 5: 添加打包脚本

打开 package.json,并添加 scripts 部分来配置打包命令:

json
复制代码
"scripts": {
  "build": "rollup -c",
  "build:watch": "rollup -c -w"
}
  • build:执行打包。
  • build:watch:监视文件变化并实时打包。

步骤 6: 打包项目

运行以下命令以打包你的项目:

pnpm run build

这将会生成以下文件和目录:

  • dist/esm:包含 ES Module 格式的代码。
  • dist/cjs:包含 CommonJS 格式的代码。
  • dist/umd/index.js:包含 UMD 格式的代码,可以用于浏览器和 Node.js。
  • dist/types:包含 TypeScript 的声明文件(.d.ts 文件)。

步骤 7: 测试生成的 npm 包

你可以创建一个 test 目录来测试生成的包:

  1. 创建测试目录
    mkdir test
    cd test
    
  2. 编写测试代码
    test 目录中创建一个 JavaScript 或 TypeScript 文件来测试该包,例如 hello.test.ts
    import { describe, it, expect } from "vitest";
    import { greet } from "../src/modules/hello";
    describe("hello", () => {
      it("greet", () => {
        expect(greet("david")).toMatchInlineSnapshot(`"Hello, david!"`);
      });
    });
    
  3. 添加测试脚本
    在 package.json 文件中添加如下内容
    ......
      "scripts": {
        "test": "vitest",
      },
      ......
    
  4. 运行测试
    pnpm run test
    

添加 Vitepess 文档插件

使用官网的单独安装指令

pnpm add -D vitepress

由于 vitepessrollup其实是分开的,无所谓先后安装的顺序,你也可以使用vitepess官网的向导安装指令

  1. 在文件中建立如下目录

    my-rollup-package/
    ├─ docs
    │  ├─ .vitepress
    │  │  └─ config.js (配置文件主题之类的设置)
    │  ├─ api-examples.md
    │  ├─ markdown-examples.md
    │  └─ index.md
    └─ package.json
    
  2. 启动并运行
    将以下 npm 脚本注入到 package.json 中:

    {
      ...
      "scripts": {
        "docs:dev": "vitepress dev docs",
        "docs:build": "vitepress build docs",
        "docs:preview": "vitepress preview docs"
      },
      ...
    }
    

    docs:dev 脚本将启动具有即时热更新的本地开发服务器。使用以下命令运行它:

    pnpm run docs:dev
    

基本配置到这里就结束了,更多关于 vitepress 的用法关注官网