如何开发一个脚手架

news/2024/11/26 22:57:53/

简介

你是否好奇如何通过命令 npm create vite@latest 来创建项目?使用脚手架可以是我们方便快捷的创建一些初始化的项目,这些基本都是一些常用的技术栈,比如 React、Vue、Angular、Node.js 等。那么,每次创建你是否都需要自己额外配置,如一些路由、存储、插件等?是否可以写一个脚手架专门用于创建属于自己常用的模板?下面,我将带你一起了解如何开发一个简单的脚手架。

设计原理

通过脚手架克隆远程自己仓库的模板到本地,在一个项目中创建多个不同分支的模板,例如本项目中我的模板有:

  • react
  • react-shadcn
  • vue
  • vue-shadcn
  • next
  • next-shadcn

1、创建项目

创建一个空文件夹,然后在该文件夹下执行以下命令:

pnpm init

package.json 文件会自动生成,可以添加一些额外的配置,比如:

{// 项目名称,格式: create-[脚手架名]"name": "create-xie392-template","version": "0.0.0",// +"type": "module","description": "",// + 等下会安装 tsup"scripts": {"dev": "tsup --watch","build": "tsup"},// + 和包名相同,通过 `npm create [脚手架名]` 命令创建项目"bin": {"create-xie392-template": "./dist/index.js"},"keywords": [],// + npm publish 时,需要包含的文件"files": ["dist", "README.md", "package.json"],// + 导出的模块"exports": "./dist/index.js","author": "",// + 远程仓库地址(可选)"repository": {"type": "git","url": "https://github>github.com/xie392/npm-template.git"},"license": "MIT"
}

【注意】:如果你想使用 npm create [脚手架名]命令,你的包名必须是 create-[脚手架名],比如 create-vite

2、安装依赖

2.1. 安装 tsup

tsup 是一个 TypeScript 打包器,它可以将 TypeScript 编译成 JavaScript,并且可以将依赖项打包到一起。

pnpm add tsup -D

2.2、安装 typescript

本项目使用 typescript,所以需要安装 typescript 依赖。

pnpm add typescript -D

2.3、安装 commander

commander 是一个 Node.js 命令行解析器,可以方便的解析命令行参数。

pnpm add commander

2.4、安装 chalk

chalk 是一个用于在终端上输出颜色的库。

pnpm add chalk

2.5、安装 inquirer

inquirer 是一个交互式命令行界面,可以让用户输入一些信息。如:输入、选择等

pnpm add inquirer

git_100">2.6、安装 degit(可选)

degit 是用来克隆远程 Git 仓库的命令行工具。(注意:这个库克隆不了 Gitee 的仓库,如果想要克隆 Gitee 的仓库,可以使用 giget)

pnpm add degit

2.7、安装 ora(可选)

ora 是一个用来显示命令行进度条的库。

pnpm add ora

3、创建文件

3.1、创建 tsup.config.ts 文件

import { defineConfig } from "tsup";const isDev = process.env.npm_lifecycle_event === "dev";export default defineConfig({clean: true,entry: ["src/index.ts"],format: ["esm"],minify: !isDev,target: "esnext",outDir: "dist",// 如果是 dev 环境,则使用 node 运行打包后的文件onSuccess: isDev ? "node dist/index.js" : undefined,
});

3.2、创建 tsconfig.json 文件夹

{"compilerOptions": {"target": "ES2020","lib": ["DOM", "DOM.Iterable", "ES2021"],"module": "Node16","moduleResolution": "nodenext","resolveJsonModule": true,"allowJs": true,"baseUrl": "./","paths": {"@/*": ["./src/*"]},"checkJs": true},"include": ["src", "tsup.config.ts"]
}

3.3、创建 src/index.ts 文件

如果是可执行文件,必须在顶层加上 #!/usr/bin/env node 注释。

#!/usr/bin/env nodeconsole.log("hello world");
// ...more

3.4、添加启动和打包命令

以上添加完毕后记得在 package.json 文件中的 scripts 中添加 "dev": "tsup --watch""build": "tsup" 命令。

{"scripts": {"dev": "tsup --watch","build": "tsup"}
}

4、初始测试运行

pnpm dev

如果输出 hello world 就说明初步的配置已经成功了,那么下面开始编写逻辑代码。

5、编写逻辑代码

为了简洁明了,我将逻辑代码放在 src/index.ts 文件中,具体实现可以根据自己的需求进行修改。

#!/usr/bin/env nodeimport { Command } from "commander";
import degit from "degit";
import path from "path";
import chalk from "chalk";
import ora from "ora";
import inquirer from "inquirer";// 终端显示命令行
async function askQuestion() {try {// 这里可以根据自己的需求添加更多的选项// 可以去看 inquirer 官方文档const answers = await inquirer.prompt([{type: "input",name: "name",message: "What is your name?",// 如果没有输入就是下面的默认值default: "new-project",validate: (fileName: string) => {// 可以校验输入的名称是否合法const isChinese = /[\u4e00-\u9fa5]/.test(fileName);// 如果是中文就提示if (isChinese) {return "Please enter a valid English name";}// 根据自己需要添加更多的校验规则return true;},},{type: "list",name: "branch",message: "What template do you want to use?",// 选择一个choices: [{ name: "React", value: "react" },{ name: "React-Shadcn", value: "react-shadcn" },{ name: "Vue", value: "vue" },{ name: "Vue-Shadcn", value: "vue-shadcn" },],},]);return answers;} catch (error) {if (error.name === "ExitPromptError") {console.log(chalk.red("Error creating project: User exited prompt"));}process.exit(1);}
}// 这里写你自己的仓库地址
const REPO = "github>github:xie392/create-xie392-template";// 创建项目
async function createProject(answers: { name: string; branch: string }) {// 结构项目名和分支名const { name, branch } = answers;// 使用 degit 工具从指定的 Git 仓库拉取项目模板const emitter = degit(`${REPO}#${branch}`, {cache: false,force: true,});// 解析目标目录的绝对路径const targetDir = path.resolve(process.cwd(), name);console.log(chalk.blue(`\nCreating project in ${chalk.green(targetDir)}...`));// 显示进度条const spinner = ora("Cloning repository...").start();try {// 克隆仓库到本地await emitter.clone(targetDir);spinner.succeed("Repository cloned successfully!");console.log(chalk.green(`\nProject created successfully!`));console.log(chalk.yellow(`\nNext steps:`));console.log(chalk.cyan(`  cd ${name}`));console.log(chalk.cyan(`  npm install`));console.log(chalk.cyan(`  npm run dev`));} catch (error) {spinner.fail("Error cloning repository.");console.error(chalk.red("Error creating project:"), error.message);}
}async function main() {try {const program = new Command();program.name("create-xie392-template").version("0.0.0").description("这是一个脚手架创建项目的工具").action(async () => {const answer = await askQuestion();await createProject(answer);process.exit(1);});program.parse(process.argv);} catch (error) {console.log(chalk.red(error.message));}
}main();

npm_309">6、发布 npm

6.1、发布前的检查

pnpm build
  1. 检查 dist 文件夹是否存在,如果不存在,请先执行 pnpm build 命令。
  2. 检查 package.json 文件中的 nameversion 是否正确。
  3. 检查 package.json 文件中的 files 是否正确。
  4. 检查 package.json 文件中的 bin 是否正确。
  5. 检查 package.json 文件中的 exports 是否正确。

npm_323">6.2、发布 npm

这里我希望是通过 Github action 去自动的发布。

在这之前先查看一下注册源是否是: https://registry.npmjs.org/

查看当前镜像源:

npm config get registry

如果不是,则需要修改镜像源:

npm config set registry https://registry.npmjs.org/

npm_341">6.3、登录 npm

npm login

6.4、生成 token

npm token create

生成成功后复制下来

6.5、将 Token 添加到 GitHub 项目中的 Secrets:

  • 打开你的 GitHub 仓库。
  • 进入 Settings > Secrets and variables > Actions
  • 点击 New repository secret
  • 添加一个名为 NPM_TOKENSecret,并将上一步生成的 Token 作为值保存。

6.6、编写工作流

创建 .github>github/workflows/publish.yml

name: publish to npmon:# 当创建标签时触发push:tags:- v* # 匹配所有以 `v` 开头的 tagjobs:publish:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v3- uses: actions/setup-node@v3with:node-version: 20# 配置 npm 的 authToken- name: Configure npmrun: |echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc# 安装依赖- name: Install dependenciesrun: npm install# 打包- name: Buildrun: npm run build# 发布到 npm- name: publish to npmrun: npm publishenv:NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

6.7、测试发布

git init
git add .
git commit -m "feat: init"
# 注意:你这里还需要先关联你的远程仓库,根据自己需求更改
git remote add origin https://github>github.com/xie392/create-xie392-template.git
git tag v0.0.1
git push origin v0.0.1

如果发布成功或失败都会通过邮箱通知你,你自己也可以看看 Action 的进度。

7、使用脚手架

npm create xie392-template

总结

通过本文,你应该对如何开发一个脚手架有了一个大概的了解,并且学会了如何使用 tsup 打包 TypeScript 项目,以及如何发布 npm 包。当然,脚手架的功能远不止这些,还可以实现更多的功能,比如:自定义模板、自动化测试、自动化部署等。学习永无止境!希望这篇文章能帮助到你。

参考项目

  • create-t3-app

Gtihub 地址

本项目地址


http://www.ppmy.cn/news/1550169.html

相关文章

python深度学习机器学习编程序接单服务代码指导编写脚本调试爬虫

您提到的Python在深度学习、机器学习、编程、接单服务、代码指导、编写脚本、调试以及爬虫等多个方面的应用,确实展示了Python作为一种强大且多功能的编程语言在多个领域的广泛应用。以下是对这些方面的简要说明及建议: Python深度学习与机器学习 深度…

Python爬虫:获取1688关键词API接口数据

引言 在当今的电子商务领域,数据的价值不言而喻。对于商家来说,掌握行业关键词趋势是洞察市场动态、优化产品布局的重要手段。1688作为中国领先的B2B电商平台,提供了海量的商品数据。本文将介绍如何使用Python编写爬虫程序,通过A…

2025杭州国际智能网联新能源汽车展览会

2025杭州国际智能网联新能源汽车展览会 同期举办:杭州国际车灯与车辆照明技术展览会 杭州国际汽车零配件、动力电池与充(换)电技术展览会 杭州国际汽车内外饰与车用纺织品展览会 时间:2025年06月20日-22日 地点:杭州大…

【ChatGPT】ChatGPT在多领域知识整合中的应用

ChatGPT在多领域知识整合中的应用 随着人工智能技术的发展,ChatGPT以其强大的自然语言处理能力,在知识整合和信息生成方面展现出独特优势。通过将多个领域的知识有机结合,ChatGPT不仅能够回答复杂问题,还能帮助用户处理跨学科的任…

第九章 使用Apache服务部署静态网站

1. 网站服务程序 1970 年,作为互联网前身的 ARPANET(阿帕网)已初具雏形,并开始向非军用部门开放,许多大学和商业机构开始陆续接入。虽然彼时阿帕网的规模(只有 4 台主机联网运行)还不如现在的…

【eNSP】ISIS动态路由协议实验

和OSPF一样,IS-IS也是一种基于链路状态并使用最短路径优先算法进行路由计算的一种IGP协议。IS-IS最初是国际化标准组织ISO为它的无连接网络协议CLNP设计的一种动态路由协议。 为了提供对IP的路由支持,IETF在RFC1195中对IS-IS进行了扩充和修改&#xff0c…

大语言模型提示词工程学习--写小说系列(文心一言豆包通义千问):2~确定核心谜团

在上一篇 大语言模型提示词工程学习--写小说系列(文心一言&豆包&通义千问):1~创作前的准备工作 中,我们已经使用AI确定了进行小说创作的8个步骤,在接下来的章节中,我们将一步一步按照AI给出的步骤&…

《用Python画蔡徐坤:艺术与编程的结合》

简介 大家好!今天带来一篇有趣的Python编程项目,用代码画出知名偶像蔡徐坤的形象。这个项目使用了Python的turtle库,通过简单的几何图形和精心设计的代码来展示艺术与编程的结合。 以下是完整的代码和效果介绍,快来试试看吧&…