手把手搭建Rollup+Typescirpt的工具库

231 阅读18分钟

工具库:RollupTsUtils 指南

概览

本文将引导您从零开始构建一个高效、现代的 JavaScript 工具库——RollupTsUtils。这个库将集成 TypeScript 的类型安全、Rollup 的模块打包能力,以及多种工具以确保代码质量、自动化测试和文档生成。

特性概览

  • TypeScript 支持:利用 TypeScript 提供的静态类型检查,提升代码质量和开发体验。
  • 模块化设计:通过 Rollup 支持多种模块格式,包括 CommonJS、ES modules 和 UMD。
  • 跨平台兼容性:使用 Babel 确保代码在不同环境中的兼容性。
  • 代码质量保障:集成 ESLint 和 Prettier,统一代码风格和质量标准。
  • 自动化测试:采用 Jest 进行单元测试,确保功能的正确性和稳定性。
  • 版本控制工作流:通过 Commitlint 和 Husky 规范提交信息和自动化代码检查。
  • 文档自动生成:使用 VitePress 生成清晰、易于维护的文档。
  • 持续集成/持续部署(CI/CD):配置自动化的构建和发布流程。
  • 高效的包管理:使用 pnpm 作为包管理器,提高依赖安装效率和磁盘空间利用率。

项目初始化

项目初始化是成功构建项目的基础。本节将介绍如何创建项目结构、初始化包管理器和设置版本控制。

创建项目目录

首先,创建一个新的目录来存放项目:

mkdir RollupTsUtils
cd RollupTsUtils

初始化 pnpm 项目

选择 pnpm 作为包管理器,因其安装速度快且磁盘空间利用率高:

pnpm init

编辑生成的 package.json 文件,添加必要的信息:

{
  "name": "rollup-ts-utils",
  "version": "0.1.0",
  "description": "A modern JavaScript utility library built with Rollup and TypeScript",
  "main": "dist/index.js",
  "module": "dist/index.esm.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": ["utils", "typescript", "rollup"],
  "author": "Your Name",
  "license": "MIT"
}

设置 .gitignore 文件

创建 .gitignore 文件以指定 Git 忽略的文件和目录:

touch .gitignore

编辑 .gitignore 文件,添加以下内容:

# Dependencies
node_modules/

# Build output
dist/

# IDE and editor files
.vscode/
.idea/
*.swp
*.swo

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Operating System Files
.DS_Store
Thumbs.db

# Test coverage
coverage/

# Temporary files
*.tmp
*.temp

# Environment variables
.env
.env.local
.env.*.local

初始化 Git 仓库

初始化 Git 仓库并创建第一个提交:

git init
git add .
git commit -m "Initial commit: Project setup"

创建基本目录结构

为项目创建基本的目录结构:

mkdir src tests docs
  • src:存放源代码
  • tests:存放测试文件
  • docs:存放文档

创建初始源文件

src 目录中创建一个初始的入口文件:

echo "// RollupTsUtils main entry point" > src/index.ts

安装基本开发依赖

安装 TypeScript 和类型定义作为开发依赖:

pnpm add -D typescript @types/node

至此,我们已经完成了 RollupTsUtils 项目的基本初始化,为后续开发奠定了基础。

在接下来的部分中,我们将深入探讨如何配置 TypeScript,以利用其静态类型检查的优势,提高代码质量和开发效率。

配置 TypeScript

TypeScript 为 JavaScript 添加了可选的静态类型和基于类的面向对象编程特性,显著提升代码质量和可维护性。本节将介绍如何为 RollupTsUtils 项目设置 TypeScript。

安装 TypeScript

确保安装了 TypeScript:

pnpm add -D typescript @types/node

创建 TypeScript 配置文件

创建 tsconfig.json 文件以配置 TypeScript 编译器选项:

npx tsc --init

根据项目需求修改生成的 tsconfig.json 文件:

{
  "compilerOptions": {
    "target": "ES2018",
    "module": "esnext",
    "lib": ["DOM", "ES2018", "ESNext"],
    "outDir": "./dist",
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationDir": "./dist",
    "sourceMap": true,
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "removeComments": false,
    "preserveConstEnums": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "**/*.test.ts"
  ]
}

这些配置选项的意义如下:

  • target:指定 ECMAScript 目标版本。
  • module:指定生成的模块系统代码类型。
  • lib:指定需要包含的库文件。
  • outDir:指定输出目录。
  • strict:启用所有严格类型检查选项。
  • moduleResolution:决定如何处理模块。
  • esModuleInterop:启用 CommonJS 和 ES 模块之间的互操作性。
  • declaration:生成相应的 .d.ts 文件。
  • sourceMap:生成相应的 .map 文件。
  • noUnusedLocalsnoUnusedParameters:报告未使用的局部变量和参数。
  • includeexclude:指定哪些文件应被 TypeScript 编译器处理或忽略。

更新 package.json

package.json 文件中添加 TypeScript 相关脚本:

"scripts": {
  "type-check": "tsc --noEmit",
}

这些脚本将用于:

  • 运行类型检查而不生成文件。
  • 只生成类型声明文件。
  • 使用 Rollup 构建 JavaScript 文件(后续步骤中配置)。

创建示例 TypeScript 文件

src 目录中创建 math.ts

export function add(a: number, b: number): number {
  return a + b;
}

export function subtract(a: number, b: number): number {
  return a - b;
}

export function multiply(a: number, b: number): number {
  return a * b;
}

export function divide(a: number, b: number): number {
  return a / b;
}

修改 src/index.ts 以导出:

export * from './math';

运行类型检查

运行类型检查以确保一切正常:

pnpm run type-check

如果没有错误,说明 TypeScript 配置正确。

接下来,我们将设置 Rollup 来处理项目的构建过程,这将使我们能够将 TypeScript 代码编译成各种模块格式的 JavaScript。

配置 Rollup

Rollup 是一个高效的 JavaScript 模块打包器,特别适合库和工具的构建。本节将介绍如何为 RollupTsUtils 配置 Rollup。

安装 Rollup 及相关插件

首先,安装 Rollup 和相关插件:

pnpm add -D rollup @rollup/plugin-typescript tslib @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-terser rollup-plugin-dts

这些插件的作用如下:

  • @rollup/plugin-typescript:使 Rollup 能够处理 TypeScript 文件。
  • @rollup/plugin-node-resolve:允许 Rollup 查找外部模块。
  • @rollup/plugin-commonjs:将 CommonJS 模块转换为 ES6。
  • @rollup/plugin-json:允许 Rollup 导入 JSON 文件。
  • @rollup/plugin-terser:压缩输出的 JavaScript。
  • rollup-plugin-dts:生成 TypeScript 声明文件(.d.ts)。

创建 Rollup 配置文件

创建 rollup.config.base.mjs

import typescript from '@rollup/plugin-typescript';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import dts from 'rollup-plugin-dts';
import replace from '@rollup/plugin-replace';

const isProduction = !process.env.ROLLUP_WATCH;

export const baseConfig = {
  input: 'src/index.ts',
  plugins: [
    resolve(),
    commonjs(),
    typescript({
      declaration: false,
    }),
    json(),
    replace({
      'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
      preventAssignment: true,
    }),
  ],
};

export const dtsConfig = {
  input: 'src/index.ts',
  output: [{ file: 'dist/index.d.ts', format: 'es' }],
  plugins: [dts()],
};

创建 rollup.config.prod.mjs

import terser from '@rollup/plugin-terser';
import { baseConfig, dtsConfig } from './rollup.config.base.mjs';

const packageName = 'rollupTsUtils';

const productionConfig = {
  ...baseConfig,
  output: [
    {
      file: 'dist/index.js',
      format: 'cjs',
    },
    {
      file: 'dist/index.esm.js',
      format: 'es',
    },
    {
      file: 'dist/index.umd.js',
      format: 'umd',
      sourcemap: true,
      name: packageName,
      globals: {
        // 如果你的库依赖其他全局变量,在这里定义它们
        '@babel/runtime-corejs3/regenerator': 'regeneratorRuntime',
        '@babel/runtime-corejs3/helpers/asyncToGenerator': 'asyncToGenerator',
        '@babel/runtime-corejs3/core-js-stable/promise': 'Promise',
      },
    },
  ],
  plugins: [...baseConfig.plugins, terser()],
};

export default [productionConfig, dtsConfig];

配置构建脚本

package.json 文件中添加以下脚本:

"scripts": {
  "build": "npm run clean && rollup -c rollup.config.prod.mjs",
  "clean": "rm -rf dist",
  "type-check": "tsc --noEmit",
  "prepublishOnly": "pnpm run build"
}

完善开发环境

为了提供更好的开发体验,我们将进一步完善开发环境的设置。

新增 rollup.config.dev.mjs

import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
import { baseConfig } from './rollup.config.base.mjs';
const packageName = 'rollupTsUtils';

const devConfig = {
  input: baseConfig.input,
  output: {
    file: 'dev/bundle.js',
    format: 'iife',
    name: packageName,
    sourcemap: true,
  },
  plugins: [
    ...baseConfig.plugins,
    serve({
      contentBase: ['dev'],
      open: true,
      port: 3000,
    }),
    livereload({
      watch: ['dev'],
    }),
  ],
};
export default devConfig;

在开发环境中:

  1. 添加了 @rollup/plugin-replace 插件,用于在构建时替换环境变量。
  2. 添加了 rollup-plugin-serverollup-plugin-livereload 插件。
  3. 为开发构建创建了单独的 devConfig 对象。

创建开发环境入口文件

dev 目录中创建一个更完善的 index.html 文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>RollupTsUtils Dev</title>
    <style>
      body {
        font-family: Arial, sans-serif;
        line-height: 1.6;
        padding: 20px;
      }
      h1 {
        color: #333;
      }
      #output {
        background-color: #f4f4f4;
        padding: 10px;
        border-radius: 5px;
      }
    </style>
  </head>
  <body>
    <h1>RollupTsUtils Development</h1>
    <div id="output"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.12.1/polyfill.min.js"></script>
    <script src="bundle.js"></script>
    <script>
      // 示例:使用库中的函数
      document.addEventListener("DOMContentLoaded", () => {
        const outputDiv = document.getElementById("output");
        if (window.rollupTsUtils) {
          outputDiv.textContent = "1 + 2 = " + window.rollupTsUtils.add(1, 2);
          console.log(window.rollupTsUtils.asyncFunction());
        }
      });
    </script>
  </body>
</html>

更新 package.json 中的开发脚本

"scripts": {
  "dev": "rollup -c rollup.config.dev.mjs",
}

现在,您可以使用以下命令启动开发环境:

pnpm run dev

这将启动 Rollup 的监视模式和开发服务器。您可以在浏览器中打开 http://localhost:3000 来查看结果。

接下来,我们将配置 Babel,这是现代 JavaScript 开发中非常重要的一部分。Babel 允许我们使用最新的 JavaScript 特性,同时确保代码能在各种环境中运行。

完善 Babel 配置

安装 Babel 及相关预设

首先,安装 Babel 和相关的预设及插件:

pnpm add -D @babel/core @babel/preset-env @babel/preset-typescript @babel/plugin-transform-runtime
pnpm add @babel/runtime

这些包的作用如下:

  • @babel/core:Babel 的核心功能。
  • @babel/preset-env:智能预设,根据目标环境自动确定需要的 Babel 插件和 polyfills。
  • @babel/preset-typescript:用于转换 TypeScript 代码。
  • @babel/plugin-transform-runtime:用于优化 Babel 辅助代码,减少代码体积。
  • @babel/runtime:包含 Babel 模块化运行时助手,是 @babel/plugin-transform-runtime 的依赖。

创建并解释 babel.config.js

在项目根目录创建 babel.config.js 文件:

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        targets: {
          node: '12',
          browsers: ['>0.25%, last 2 versions'],
        },
        useBuiltIns: 'usage',
        corejs: 3,
      },
    ],
    '@babel/preset-typescript',
  ],
  plugins: [
    [
      '@babel/plugin-transform-runtime',
      {
        corejs: 3,
      },
    ],
  ],
  env: {
    test: {
      presets: [
        [
          '@babel/preset-env',
          {
            targets: { node: 'current' },
          },
        ],
      ],
    },
  },
};

这个配置的详细解释如下:

  1. presets

    • @babel/preset-env
      • targets:指定目标环境。这里我们设置了 Node.js 12+ 和覆盖全球超过 0.25% 使用率的浏览器。
      • modules: false:保留 ES 模块语法,让 Rollup 来处理模块。
      • useBuiltIns: 'usage':根据实际代码使用情况和目标环境自动添加 polyfills。
      • corejs: 3:使用 core-js 3 版本来提供 polyfills。
    • @babel/preset-typescript:用于处理 TypeScript 代码。
  2. plugins

    • @babel/plugin-transform-runtime
      • 提取 Babel 辅助函数,避免重复注入,减小打包体积。
      • corejs: 3:使用 core-js 3 版本的运行时助手。
  3. env

    • test:为测试环境提供特定配置,使用当前 Node.js 版本作为目标,这对于使用 Jest 等测试框架很有用。

更新 rollup.config.base.mjs

确保 Rollup 配置正确使用 Babel。更新 rollup.config.mjs 中的 Babel 插件配置:

// 在 import 语句部分
import { babel } from '@rollup/plugin-babel';

// 在 plugins 数组中
    babel({
      babelHelpers: 'runtime',
      exclude: 'node_modules/**',
      extensions: ['.js', '.ts'],
    }),

这里的 babelHelpers: 'runtime' 选项与我们使用的 @babel/plugin-transform-runtime 插件配合使用。

接下来,我们将设置代码质量工具,包括 ESLint 和 Prettier,以确保代码风格和质量的一致性。

代码质量工具

设置 ESLint

ESLint 是一个强大的静态代码分析工具,用于识别和报告 JavaScript/TypeScript 代码中的模式。

安装 ESLint 及相关插件

运行以下命令安装 ESLint 及其相关插件:

bash
pnpm add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-import eslint-config-airbnb-base eslint-config-airbnb-typescript

创建 ESLint 配置文件

在项目根目录创建 .eslintrc.js 文件:

module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
  ],
  plugins: ['@typescript-eslint', 'prettier'],
  env: {
    node: true,
    es6: true,
  },
  parserOptions: {
    ecmaVersion: 2018,
    sourceType: 'module',
  },
  rules: {
    'prettier/prettier': 'error',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/no-explicit-any': 'warn',
    '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
    'no-console': 'warn',
  },
};

这个配置:

  • 使用 @typescript-eslint/parser 解析 TypeScript 代码。
  • 采用 Airbnb 的基础规则集。
  • 启用 TypeScript 特定的推荐规则。
  • 自定义了一些规则,如关闭默认导出的强制要求。

添加 .eslintignore 文件:

node_modules
dist
dev
docs

设置 Prettier

Prettier 是一个代码格式化工具,可以确保团队中的所有代码遵循一致的样式。

安装 Prettier 及相关插件

运行以下命令:

pnpm add -D prettier eslint-config-prettier eslint-plugin-prettier

创建 Prettier 配置文件

在项目根目录创建 .prettierrc.js 文件:

module.exports = {
  semi: true,
  trailingComma: 'all',
  singleQuote: true,
  printWidth: 100,
  tabWidth: 2,
};

更新 ESLint 配置

更新 .eslintrc.js 文件以集成 Prettier:

module.exports = {
  // ... 之前的配置
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier', // 添加这行
    'plugin:prettier/recommended', // 添加这行
  ],
  // ... 其余配置保持不变
};

配置 lint-staged 进行预提交检查

lint-staged 允许我们在 git 暂存区的文件上运行脚本,配合 husky 可以在提交前自动运行 linter。

安装 lint-staged 和 husky

pnpm add -D lint-staged husky

配置 husky

初始化 husky:

npx husky install

添加 pre-commit 钩子:

npx husky add .husky/pre-commit "npx lint-staged"

如果失败,执行:

echo "npx lint-staged" > .husky/pre-commit

配置 lint-staged

package.json 中添加 lint-staged 配置:

{
  "lint-staged": {
    "*.{js,ts}": [
      "eslint --fix",
      "prettier --write"
    ],
    "*.{json,md}": [
      "prettier --write"
    ]
  }
}

更新 package.json 脚本

添加以下脚本到 package.json

{
  "scripts": {
    // ... 其他脚本
    "lint": "eslint 'src/**/*.{js,ts}'",
    "lint:fix": "eslint 'src/**/*.{js,ts}' --fix",
    "format": "prettier --write 'src/**/*.{js,ts,json,md}'",
    "prepare": "husky install"
  }
}

集成到开发流程

  1. 运行 pnpm run lint 来检查代码风格。
  2. 运行 pnpm run lint:fix 来自动修复可以自动修复的问题。
  3. 运行 pnpm run format 来格式化代码。
  4. Git commit 前会自动运行 lint-staged,检查并格式化暂存的文件。

通过这些设置,我们实现了:

  1. 使用 ESLint 进行代码质量检查。
  2. 使用 Prettier 确保一致的代码格式。
  3. 通过 lint-staged 和 husky 在提交前自动运行检查和格式化。

这些工具共同工作,可以显著提高代码质量,减少因格式或常见错误导致的问题。在团队协作中,这些工具尤其重要,可以确保所有贡献者遵循相同的代码标准。

接下来,我们将设置版本控制工作流,包括 Commitlint 来规范化提交信息。

版本控制工作流

设置 Commitlint

Commitlint 用于检查提交信息是否符合预定义的格式,这有助于保持提交历史的清晰和一致。

安装 Commitlint

运行以下命令安装 Commitlint 及其配置:

pnpm add -D @commitlint/cli @commitlint/config-conventional

创建 Commitlint 配置文件

在项目根目录创建 commitlint.config.mjs 文件:

export default { extends: ['@commitlint/config-conventional'] };

这个配置使用了 conventional commit 规范,它定义了以下提交类型:

  • feat:新功能。
  • fix:错误修复。
  • docs:文档更改。
  • style:不影响代码含义的更改(空白、格式化、缺少分号等)。
  • refactor:既不修复错误也不添加功能的代码更改。
  • perf:改进性能的代码更改。
  • test:添加缺失的测试或更正现有的测试。
  • build:影响构建系统或外部依赖项的更改。
  • ci:对 CI 配置文件和脚本的更改。
  • chore:其他不修改 src 或测试文件的更改。
  • revert:恢复之前的提交。

配置 Husky 钩子

我们已经在前面的步骤中安装了 Husky,现在我们将添加更多的 Git 钩子来集成 Commitlint。

添加 commit-msg 钩子

运行以下命令来添加 commit-msg 钩子:

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'

如果失败,执行:

echo 'npx --no -- commitlint --edit ${1}' > .husky/commit-msg

这将在提交消息创建后但提交完成之前运行 Commitlint。

配置 Conventional Commits 工具(可选)

为了更容易地创建符合规范的提交信息,我们可以使用 Conventional Commits 工具。

安装 commitizen

pnpm add -D commitizen cz-conventional-changelog

配置 commitizen

package.json 中添加以下配置:

{
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

添加 npm 脚本

package.jsonscripts 部分添加:

{
  "scripts": {
    // ... 其他脚本
    "commit": "cz"
  }
}

现在,开发者可以使用 pnpm run commit 来创建规范化的提交信息。

使用工作流

  1. 进行代码更改。
  2. 暂存更改:git add .
  3. 提交更改:
    • 使用 git commit -m "your message" 并遵循 conventional commit 格式。
    • 或使用 pnpm run commit 通过交互式提示创建提交信息。
  4. 如果提交消息不符合规范,Commitlint 将阻止提交并显示错误信息。

通过这些设置,我们实现了:

  1. 使用 Commitlint 强制执行一致的提交消息格式。
  2. 利用 Husky 在适当的 Git 钩子中运行必要的检查。
  3. (可选)使用 Commitizen 帮助创建规范的提交信息。

接下来,我们可以继续设置单元测试,确保代码的稳定性和可靠性。

单元测试

安装 Jest 和 ts-jest

首先,我们需要安装 Jest、ts-jest 以及相关的类型定义:

pnpm add -D jest @types/jest ts-jest

配置 Jest

创建一个 jest.config.js 文件在项目根目录下:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coveragePathIgnorePatterns: ['/node_modules/'],
};

这个配置的详细解释如下:

  • preset: 'ts-jest':使用 ts-jest 预设,允许 Jest 直接运行 TypeScript 测试文件。
  • testEnvironment: 'node':指定测试环境为 Node.js。
  • moduleFileExtensions:指定 Jest 应该识别的文件扩展名。
  • collectCoverage: true:启用代码覆盖率收集。
  • coverageDirectory: 'coverage':指定存放覆盖率报告的目录。
  • coveragePathIgnorePatterns:指定在收集覆盖率时要忽略的路径模式。

更新 package.json

package.json 中添加测试脚本:

"scripts": {
  "test": "jest"
}

这样,您就可以通过运行 pnpm test 来执行测试了。

编写示例测试用例

tests 目录下创建一个 math.test.ts 文件:

// tests/math.test.ts
import { add, subtract } from '../src/math';

describe('Math functions', () => {
  test('adds 1 + 2 to equal 3', () => {
    expect(add(1, 2)).toBe(3);
  });

  test('subtracts 5 - 3 to equal 2', () => {
    expect(subtract(5, 3)).toBe(2);
  });

  test('adds negative numbers', () => {
    expect(add(-1, -2)).toBe(-3);
  });

  test('subtracts with negative result', () => {
    expect(subtract(2, 5)).toBe(-3);
  });
});

运行测试

现在,您可以运行 pnpm test 来执行测试。Jest 将运行所有测试文件并显示结果,包括通过/失败的测试数量和代码覆盖率报告。

通过这些设置,我们确保了代码的稳定性和可靠性,同时自动化测试流程也提高了开发效率。

接下来,我们将探讨如何生成文档,这对于维护和使用库至关重要。

文档生成

安装 VitePress

首先,我们需要安装 VitePress 作为开发依赖:

pnpm add -D vitepress

初始化 VitePress

在项目根目录下创建一个 docs 文件夹,这将是我们存放文档的地方:

npx vitepress init docs

这样就初始化了 VitePress 项目。

运行文档开发服务器

现在您可以通过以下命令启动文档开发服务器:

pnpm docs:dev

这将启动一个本地服务器,您可以在浏览器中预览文档。

构建文档

要构建生产版本的文档,运行:

pnpm docs:build

这将在 docs/.vitepress/dist 目录下生成静态 HTML 文件。

预览构建后的文档

要预览构建后的文档,运行:

pnpm docs:preview

部署文档

您可以将构建后的文档部署到静态网站托管服务,如 GitHub Pages、Netlify 或 Vercel。具体的部署步骤会根据您选择的平台而有所不同。

通过这些步骤,我们成功地为 RollupTsUtils 项目配置了文档生成和预览,这对于项目的维护和使用非常有帮助。

最后,我们将设置持续集成/持续部署(CI/CD),以自动化测试、构建和发布流程。

持续集成/持续部署(CI/CD)

创建 GitHub Actions 工作流文件

在您的项目根目录下创建 .github/workflows 目录,然后在其中创建一个名为 ci.yml 的文件:

mkdir -p .github/workflows
touch .github/workflows/ci.yml

配置 CI 工作流

编辑 ci.yml 文件,添加以下内容:

name: CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
    - uses: actions/checkout@v3

    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}

    - name: Install pnpm
      uses: pnpm/action-setup@v2
      with:
        version: 8.x

    - name: Install dependencies
      run: pnpm install

    - name: Run linter
      run: pnpm run lint

    - name: Run tests
      run: pnpm test

    - name: Build
      run: pnpm run build

  publish:
    needs: build
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/master'

    steps:
    - uses: actions/checkout@v3

    - name: Use Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '16.x'
        registry-url: 'https://registry.npmjs.org'

    - name: Install pnpm
      uses: pnpm/action-setup@v2
      with:
        version: 6.0.2

    - name: Install dependencies
      run: pnpm install

    - name: Build
      run: pnpm run build

    - name: Publish to npm
      run: npm publish --access public
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

这个工作流做了以下几件事:

  1. 在每次推送到 master 分支和创建 Pull Request 时触发。
  2. 在不同版本的 Node.js (18.x, 20.x) 上运行测试。
  3. 使用 pnpm 安装依赖。
  4. 运行 linter 检查代码质量。
  5. 运行测试。
  6. 构建项目。
  7. 如果所有检查都通过,并且是推送到 master 分支的事件,则发布到 npm。

设置 Secrets

为了能够发布到 npm,您需要在 GitHub 仓库中设置一个 secret:

  1. 去到您的 GitHub 仓库页面。
  2. 点击 "Settings" 标签。
  3. 在左侧菜单中选择 "Secrets and variables" 然后选择 "Actions"。
  4. 点击 "New repository secret"。
  5. 名称设为 NPM_TOKEN,值设为您的 npm 访问令牌。

配置 npm 访问令牌

如果您还没有 npm 访问令牌,请按以下步骤创建:

  1. 登录到您的 npm 账户。
  2. 点击右上角的头像,选择 "Access Tokens"。
  3. 点击 "Generate New Token",选择 "Publish" 类型的令牌。
  4. 复制生成的令牌,将其作为 NPM_TOKEN secret 的值。

文档自动部署(可选)

如果您想自动部署文档到 GitHub Pages,可以添加一个单独的工作流文件 docs.yml

# 构建 VitePress 站点并将其部署到 GitHub Pages 的示例工作流程
#
name: Deploy VitePress site to Pages

on:
  # 在针对 `main` 分支的推送上运行。如果你
  # 使用 `master` 分支作为默认分支,请将其更改为 `master`
  push:
    branches: [master]
    paths:
      - 'docs/**'  # 只有当 docs 目录下的文件发生变化时才触发
      - '.github/workflows/docs.yml' # 当 .github/workflows/docs.yml 文件发生变化时也触发
      
  # 允许你从 Actions 选项卡手动运行此工作流程
  workflow_dispatch:

# 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# 只允许同时进行一次部署,跳过正在运行和最新队列之间的运行队列
# 但是,不要取消正在进行的运行,因为我们希望允许这些生产部署完成
concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  # 构建工作
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # 如果未启用 lastUpdated,则不需要

      - name: Install pnpm
        uses: pnpm/action-setup@v3
        with:
          version: 8.x  # 明确指定版本
      
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm # 或 pnpm / yarn
      
      - name: Setup Pages
        uses: actions/configure-pages@v4

      - name: Install dependencies
        run: pnpm install # 或 pnpm install / yarn install / bun install

      - name: Build with VitePress
        run: pnpm docs:build # 或 pnpm docs:build / yarn docs:build / bun run docs:build

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: docs/.vitepress/dist

  # 部署工作
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

这个工作流会在每次推送到 master 分支时自动构建并部署文档到 GitHub Pages。

启用 GitHub Pages

要使用 GitHub Pages 托管您的文档:

  1. 去到您的 GitHub 仓库页面。
  2. 点击 "Settings" 标签。
  3. 滚动到 "Pages" 部分。
  4. 在 "Source" 下拉菜单中选择 "gh-pages" 分支。
  5. 点击 "Save"。

现在,每次您推送到 master 分支时,GitHub Actions 将自动运行测试、构建您的项目,如果一切正常,它将发布新版本到 npm 并更新您的文档。

这个设置提供了一个强大的 CI/CD 管道,确保您的代码质量,并自动化发布过程。

发布配置

更新 package.json 中的发布相关字段:

{
  "name": "rollup-ts-utils",
  "version": "1.0.1",
  "description": "A modern JavaScript tooling library built with TypeScript and Rollup",
  "main": "dist/index.js",
  "module": "dist/index.esm.js",
  "types": "dist/index.d.ts",
  "unpkg": "dist/index.umd.js",
  "jsdelivr": "dist/index.umd.js",
  "exports": {
    ".": {
      "import": "./dist/index.esm.js",
      "require": "./dist/index.js",
      "types": "./dist/index.d.ts",
      "umd": "./dist/index.umd.js"
    }
  },
  "scripts": {
    "build": "npm run lint && npm run clean && rollup -c rollup.config.prod.mjs",
    "lint": "eslint 'src/**/*.{js,ts}'",
    "lint:fix": "eslint 'src/**/*.{js,ts}' --fix",
    "format": "prettier --write 'src/**/*.{js,ts,json,md}'",
    "dev": "rollup -c rollup.config.dev.mjs",
    "test": "jest",
    "commit": "cz",
    "clean": "rm -rf dist",
    "type-check": "tsc --noEmit",
    "prepublishOnly": "pnpm run build",
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs",
    "version": "npm run build && git add -A dist",
    "postversion": "git push && git push --tags",
    "release": "npm run test && npm run build && npm publish"
  },
}

添加发布相关的 npm 脚本

您的 package.json 已经包含了许多有用的脚本。让我们回顾并解释一些关键脚本:

  "scripts": {
    "build": "npm run lint && npm run clean && rollup -c rollup.config.prod.mjs",
    "lint": "eslint 'src/**/*.{js,ts}'",
    "lint:fix": "eslint 'src/**/*.{js,ts}' --fix",
    "format": "prettier --write 'src/**/*.{js,ts,json,md}'",
    "dev": "rollup -c rollup.config.dev.mjs",
    "test": "jest",
    "commit": "cz",
    "clean": "rm -rf dist",
    "type-check": "tsc --noEmit",
    "prepublishOnly": "pnpm run build",
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs",
    "version": "npm run build && git add -A dist",
    "postversion": "git push && git push --tags",
    "release": "npm run test && npm run build && npm publish"
}

这些脚本涵盖了开发、测试、构建和文档生成等方面。特别注意:

  • prepublishOnly:这个脚本会在包发布之前自动运行,确保发布的是最新构建的版本。

为了更好地支持发布流程,我们可以添加以下脚本:

"scripts": {
  "version": "npm run build && git add -A dist",
  "postversion": "git push && git push --tags",
  "release": "npm run test && npm run build && npm publish"
}

解释新添加的脚本:

  • version:在版本更新时自动构建并将 dist 目录添加到 git。
  • postversion:在版本更新后推送代码和标签到远程仓库。
  • release:运行测试、构建,然后发布到 npm。

发布前的检查清单

在发布之前,请确保:

  1. 所有测试都通过(运行 npm test)。
  2. 文档是最新的,包括 README.md 和 API 文档。
  3. CHANGELOG.md 已更新(如果您维护更改日志)。
  4. 版本号已正确更新。
  5. files 字段中包含了所有需要发布的文件和目录。

发布步骤

  1. 更新版本号:

    npm version patch  # 或 minor 或 major
    
  2. 发布到 npm:

    npm run release
    

    如果是首次发布带 scope 的包,使用:

    npm publish --access public
    
  3. 推送代码和标签到 GitHub:

    git push && git push --tags
    

通过这些配置和脚本,您已经为发布做好了准备。这个设置允许您轻松地更新版本、运行测试、构建项目并发布到 npm,同时确保代码和标签被推送到 GitHub。