前言
本文介绍的案例已同步到github,github地址。
vue-cli 和 create-react-app 等 cli 脚手架工具用于快速搭建应用,无需手动配置复杂的构建环境。本文介绍如何使用 rollup 搭建一个脚手架工具。
脚手架工具的工作流程简言为:提供远端仓库各种模版 => 用户通过命令选择模版 => 拉取仓库代码
分别对应如下几个重要模块:
- 配置 打包命令
- 配置 命令行交互,如 create、-v 等,其中 create 是核心逻辑,用于根据用户的选择拉取远程仓库中相应的初始代码。
- 发布至 npm
1. 初始化项目
初始化项目
npm init -y
生成:typescript 配置文件 tsconfig.json,在此之前需要确保全局安装了 TypeScript
npm install -g typescript // 如果已经安装,无需理会
npx tsc --init
package.json 中添加依赖
"devDependencies": {
"@inquirer/prompts": "^3.2.0",
"@rollup/plugin-commonjs": "^25.0.3",
"@rollup/plugin-json": "^6.0.1",
"@rollup/plugin-node-resolve": "^15.1.0",
"@rollup/plugin-terser": "^0.4.3",
"@types/fs-extra": "^11.0.2",
"@types/lodash": "^4.14.199",
"@types/node": "^16.18.40",
"axios": "^1.5.0",
"chalk": "^4.1.2",
"commander": "^11.0.0",
"figlet": "^1.8.0",
"fs-extra": "^11.1.1",
"lodash": "^4.17.21",
"log-symbols": "^4.1.0",
"ora": "5",
"progress-estimator": "^0.3.1",
"pure-thin-cli": "^0.1.8",
"rollup": "^4.6.1",
"rollup-plugin-dts": "^5.3.0",
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-node-externals": "^5.1.2",
"rollup-plugin-typescript2": "^0.36.0",
"simple-git": "^3.19.1",
"tslib": "^2.6.1",
"typescript": "^5.2.2"
}
本文用到的所有依赖说明:下文中也会一一介绍依赖的用处与用法
"devDependencies": {
// 用于命令行交互。
"@inquirer/prompts": "^3.2.0",
// Rollup 相关的插件,用于模块打包
"@rollup/plugin-commonjs": "^25.0.3", // 支持rollup打包commonjs模块
"@rollup/plugin-json": "^6.0.1", // 支持rollup打包json文件
"@rollup/plugin-node-resolve": "^15.1.0", // 用于帮助 Rollup 解析和处理 Node.js 模块(Node.js 的 CommonJS 模块规范)
"@rollup/plugin-terser": "^0.4.3", // Rollup 构建过程中对生成的 JavaScript 代码进行压缩和混淆,以减小最终输出文件的体积。
// TypeScript 的类型定义文件
"@types/fs-extra": "^11.0.2",
"@types/lodash": "^4.14.199",
"@types/node": "^16.18.40",
// 用于发起 HTTP 请求。
"axios": "^1.5.0",
// 在命令行中输出彩色文本。
"chalk": "^4.1.2",
// 命令行界面的解决方案
"commander": "^11.0.0",
// 优化打印效果
"figlet": "^1.8.0",
// 扩展了标准 fs 模块的文件系统操作
"fs-extra": "^11.1.1",
// 一个提供实用函数的 JavaScript 库。
"lodash": "^4.17.21",
// 在命令行中显示日志符号。
"log-symbols": "^4.1.0",
// 创建可旋转的加载器
"ora": "5",
// 估算操作进度。
"progress-estimator": "^0.3.1",
// 一个特定于项目或定制的 CLI 工具
"pure-thin-cli": "^0.1.8",
"rollup": "^4.6.1",
"rollup-plugin-dts": "^5.3.0", // 是一个 Rollup 插件,它的主要作用是处理 TypeScript 的声明文件(.d.ts 文件)
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-node-externals": "^5.1.2", // 使rollup自动识别外部依赖
"rollup-plugin-typescript2": "^0.36.0", // 支持rollup打包ts文件
// 用于 Git 命令的 Node.js 封装。
"simple-git": "^3.19.1",
// TypeScript 运行时库。
"tslib": "^2.6.1",
"typescript": "^5.2.2"
},
目录结构如下,index.js:命令入口文件;command:命令逻辑;utils:公共方法
2. 配置打包命令
下载依赖
pnpm add -D rollup @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-json rollup-plugin-typescript2 @rollup/plugin-terser rollup-plugin-node-externals
依赖说明:
- rollup:打包工具,有很多选择,如webpack
- @rollup/plugin-node-resolve:支持rollup打包node.js模块
- @rollup/plugin-commonjs:支持rollup打包commonjs模块
- @rollup/plugin-json:支持rollup打包json文件
- rollup-plugin-typescript2:支持rollup打包ts文件
- @rollup/plugin-terser:压缩打包代码
- rollup-plugin-node-externals:使rollup自动识别外部依赖
根目录下新建 rollup.config.js
import {
defineConfig } from 'rollup';
import nodeResolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import externals from "rollup-plugin-node-externals";
import json from "@rollup/plugin-json";
import terser from "@rollup/plugin-terser";
import typescript from 'rollup-plugin-typescript2';
export default defineConfig([
{
input: {
index: 'src/index.ts', // 打包入口文件
},
output: [
{
dir: 'dist', // 输出目标文件夹
format: 'cjs', // 输出 commonjs 文件
}
],
// 这些依赖的作用上文提到过
plugins: [
nodeResolve(),
externals({
devDeps: false, // 可以识别我们 package.json 中的依赖当作外部依赖处理 不会直接将其中引用的方法打包出来
}),
typescript(),
json(),
commonjs(),
terser(),
],
},
]);
在 package.json 中配置打包命令,-c
指定 rollup 配置文件,--bundleConfigAsCjs
将配置转为 commonjs 执行。
{
......
"scripts": {
......
"build": "rollup -c rollup.config.js --bundleConfigAsCjs"
},
}
index.ts 中加入一定代码后,执行 npm run build
测试打包结果
发现如下报错,这是因为默认生成的 tsconfig.json 中 moudle
为 commonjs
,改为 'module: "ES2015"', 'module: "ES2020"', 'module: "ES2022"', or 'module: "ESNext"'
后即可。
再次执行 npm run build
,打包配置完毕
3. 命令行交互配置依赖介绍
查看 create-react-app
cli 的源码,发现其使用了如下依赖,我们也选择一部分安装
本文使用了如下依赖:
- commander:解析命令行指令
- ora:终端加载动画
- progress-estimator:终端加载条动画
- log-symbols:终端输出符号
- chalk:终端字体美化
- @inquirer/prompts:终端输入交互
其中最重要的是 commander
,下载:pnpm install commander -D
,用于解析用户在命令行输入的指令,可以到官方文档查看基本使用,并应用到 src/index.ts
中。
4. -v --version指令配置
src/index.ts
中尝试导入 Command 和 version 遇到如下报错
根据提示,将 tsconfig.json 中默认注释的 moduleResolution
放开即可,发现导入 package.json 仍报错,将 resolveJsonModule
取消注释。
继续完善 index.ts,自定义指令名称为 benchu,和 vite、vue-cli 一样就是一个命令名,添加 -v 或 --version 返回版本号,版本号为 package.json 中的 version 字段,该字段会在每次提交上传至 npm 时强制更新。
import {
Command } from "commander"
import {
version } from "../package.json"
const program = new Command("benchu")
program.version(version, "-v, --version", "获取版本号")</