- 作者:老汪软件技巧
- 发表时间:2024-10-31 11:01
- 浏览量:
导读
本文基于以下包和版本配置:
包名版本号
next
14.2.15
react
18.2.0
react-dom
18.2.0
tailwindcss
3.4.1
@changesets/cli
2.27.9
@commitlint/cli
19.5.0
@commitlint/config-conventional
19.5.0
husky
9.1.6
typescript
5.4.4
本文介绍的开发环境是Macbook Pro M1 MacOS 14.6.1。
项目启动与打包验证创建项目
创建项目,使用next 14.2.15
npx reate-next-app@14.2.15
使用app router的模式
本地运行
确保你使用了pnpm作为包管理工具,如果没有安装,请使用 npm i -g pnpm安装。
本地运行项目,使用 pnpm dev命令
到这里,一切都是正常的,说明我们的应用没有问题,一切都是纯粹的模样,接下来我们直接打包,保证我们的项目不会半途因为出现不知名的问题无法排查。(笔者在此之前已经用pages router模式搭建几乎完成了,但是打包部署始终无法成功,更要命的是开发模式也无法正常启动了。因此强烈建议每引入新的东西不仅开发模式引入就行了,打包部署尽可能都尝试一遍看看,如何出现发生了错误就能快速定位了。)
当前的next.config.js 文件的配置是
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;
可以看到是空的,我们什么都不给尝试打包 npm run build
可以看到,打包是成功了的。
由于我们的项目是一个monorepo的组件库和文档,我们需要pnpm 的workspace(工作空间)提供的能力,
可以在项目根目录中加入一个文件pnpm-workspace.yaml,内容如下:
packages:
- "packages/*"
这表示我们的子应用(有自己的package.json),也就是之后的每一个组件存放在根目录的packages子目录之下,如图所示:
需要注意的是,我们的根目录也是存在tsconfig.json文件,nextjs应用打包时,也会去检查packages下的typescript配置,这功能应该交给各个组件库包决定,因此我们需要排除packages目录:,在tsconfig.json 文件中的exclude中配置:
该项目最终目的是部署到githua pages,我们需要1)集成changesets 实现monorepo的包管理、2)commitlint实现git commit提交的规范验证和代码格式化检查,我们每上线一个功能都希望能够3)结合github pages的 工作流实现项目的一键部署。下面一节将介绍这些。
集成部署changesets
我们通过命令pnpm add -Dw @changesets/cli 安装changesets。
再通过 pnpm changeset init 初始化我们的 changeset
项目的根目录下多出一个.changeset目录。
接着我们需要在项目根目录下的packages.json文件中的 scripts命令中增加几条
{
"compile": "pnpm --filter=@zerotower/* run build",
"pub": "pnpm compile && pnpm --recursive --registry=https://registry.npmjs.org/ publish --access public",
}
第一条命令用来对packages下的组件执行编译打包命令,pub用来将我们的仓库发布到npm。
为了测试,我们先新增两个组件目录用来测试。
两个组件都是支持typescript的,我们需要同时安装 5.4.4版本。(更高的版本在笔者的使用中经常会导致奇怪的问题),在项目的根目录下执行以下命令
pnpm add typescript@5.4.4 -r -D
未来该版本可能不可用,如果5.4.4没用的话,可以通过执行 pnpm view typescript versions查看一个可用的版本。
分别查看packages/image-gallery/packages.json 和packages/color-picker/packages.json,发现都安装了指定的typescript。
改造一下
所有的组件库包都将拥有一个统一的前缀@zerotower,而我们也仅仅需要编译这些库包,根目录的next.js不参与编译。
接着,将这两个添加到根目录的package.json文件中,之后执行pnpm install -w重新安装依赖。
打开项目根目录的node_modules,@zerotower有两个字目录,它们都有红框框选的一个小图标,这表示两个目录都是软链接创建的,是将packages/**软链接到了/node_modules/@zerotower/**,底层其实就是 ln packages/** node_modules/@zerotower/**,使用的ln命令。
添加commilint
一键安装三个库包,在项目的根目录下执行:
pnpm add —D @commitlint/{config-conventional,cli} husky -w
执行以下的~~husky~~命令,完成husky的初始化。()
npx husky-init
# 下面这一句通常执行成功,但是没什么吊用
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
我们需要手动在项目根目录下的.husky目录下新增一个commit-msg文件
文件内容为:
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install commitlint --edit
"$1"
为了避免执行错误,我们还需要赋予执行的权限
chmod +x .husky/commit-msg
之后,我们需要在项目的根目录添加一个commitlint.config.cjs的文件
// @see: https://cz-git.qbenben.com/zh/guide
/** @type {import('cz-git').UserConfig} */
module.exports = {
ignores: [commit => commit.includes('init')],
extends: ['@commitlint/config-conventional'],
rules: {
// @see: https://commitlint.js.org/#/reference-rules
'body-leading-blank': [2, 'always'],
'footer-leading-blank': [1, 'always'],
'header-max-length': [2, 'always', 108],
'subject-empty': [2, 'never'],
'type-empty': [2, 'never'],
'subject-case': [0],
'type-enum': [
2,
'always',
[
'feat',
'fix',
'docs',
'style',
'refactor',
'perf',
'test',
'build',
'ci',
'chore',
'revert',
'wip',
'workflow',
'types',
'release'
]
]
},
prompt: {
messages: {
// 中文版
type: '选择你要提交的类型 :',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
footerPrefixsSelect: '选择关联issue前缀(可选):',
customFooterPrefixs: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
confirmCommit: '是否提交或修改commit ?'
},
types: [
// 中文版
{ value: 'feat', name: '特性: 新增功能', emoji: '' },
{ value: 'fix', name: '修复: 修复缺陷', emoji: '' },
{ value: 'docs', name: '文档: 文档变更', emoji: '' },
{ value: 'style', name: '格式: 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '' },
{ value: 'refactor', name: '重构: ♻️ 代码重构(不包括 bug 修复、功能新增)', emoji: '♻️' },
{ value: 'perf', name: '性能: ⚡️ 性能优化', emoji: '⚡️' },
{ value: 'test', name: '测试: ✅ 添加疏漏测试或已有测试改动', emoji: '✅' },
{
value: 'build',
name: '构建: ️ 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)',
emoji: '️'
},
{ value: 'ci', name: '集成: 修改 CI 配置、脚本', emoji: '' },
{ value: 'chore', name: '回退: ⏪️ 回滚 commit', emoji: '⏪️' },
{
value: 'revert',
name: '其他: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)',
emoji: ''
},
{ value: 'wip', name: '开发: 正在开发中', emoji: '' },
{ value: 'workflow', name: '工作流: 工作流程改进', emoji: '' },
{ value: 'types', name: '类型: 类型定义文件修改', emoji: '' }
],
useEmoji: true,
customScopesAlign: 'bottom',
emptyScopesAlias: 'empty',
customScopesAlias: 'custom',
allowBreakingChanges: ['feat', 'fix']
}
};
我们尝试一个错误的提交:
git commit -m "apx: test commit"
果真失败了,让我们尝试正确的提交
git commit -m "ci: 项目初始化,完成基本构建配置"
如果依然碰到**.husky/commit-msg**执行权限的问题,你可能需要重新删除并创建它。
添加github工作流
项目最终需要部署到github pages,我们需要搭建工作流环境。
首先,在github 创建一个仓,该仓库不可以是私有的。
在本地项目的根目录下添加仓库
git remote add github
接着,我们需要进一步修改next.config.js打包配置文件,修改后如下:
/** @type {import('next').NextConfig} */
const nextConfig = {
output:"export",
images:{
//github pages 无法对图像优化
unoptimized:true
},
//都是对应仓库名
basePath:"/react-components",
assetPrefix:"/react-components"
};
export default nextConfig;
再接着,我们再在项目根目录下创建一个github工作流文件,.github/workflows/deploy.yml
# 1. 为工作流定义名字
name: Building React Components for github pages
# 2. 触发条件修改为: 当 指定的分支, 有 push 的时候, 执行任务
on:
push:
branches:
- gh-pages
# 这个选项可以使你手动在 Action tab 页面触发工作流
workflow_dispatch:
# 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages。
permissions:
contents: read
pages: write
id-token: write
# 允许一个并发的部署
concurrency:
group: 'pages'
cancel-in-progress: true
# 3. 创建工作流
jobs:
deploy: #单次部署的工作描述
# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest # 依赖环境
steps: # 工作流步骤
# step 1. 获取源码, 拉取仓库代码
- name: Checkout ️ # 步骤名
uses: actions/checkout@v3 # 使用插件 => https://github.com/actions/checkout
# step 2. 使用指定版本 node
- name: Use Node # 步骤名
uses: actions/setup-node@v3 # 使用插件 => https://github.com/actions/setup-node
with: # 插件携带参数
node-version: 18.19.0 # 指定 node 版本
# step 3. 安装pnpm
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: '8.10.0'
# step 4. 安装依赖并打包
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm build
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
# next 打包输出的文件夹
path: './out'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2 #使用插件 => https://github.com/actions/deploy-pages
注意事项:
需要指定触发的分支,只有指定的分支才可以触发工作流,本文指定了gh-pages分支,main作为开发分支不做部署,在需要部署时才把相关的commit 通过cherry-pick到gh-pages分支。因此,可以把工作流文件放置在gh-pages分支中,并从main分支中删除。
在工作流步骤的第二步中,需要指定node的版本,有时我们的项目需要node版本大等于某个版本,如果不符合要求将会导致工作流执行失败。
在工作流的第三步,需要指定pnpm的版本号符合package.json中的最低要求,和node版本的要求一致,如不符合也将导致工作流报错。
在工作流的第四步,需要指定真正的打包命令,一般都是pnpm build,但也有可能是其它的命令,特别是需要多种构建模式的项目中。如:pnpm build:web
最后,我们需要指定打包输出的文件夹,打包成功后,每次访问github pages 都将从这个目录下访问有关的静态资源。
最后,将gh-pages分支推送到github,即可触发工作流,完成部署。可以在 仓库顶端的actions 里查看所有的构建情况: