初始化
创建项目
bash
npm install pnpm -g
// 切换工作目录 "vn"是我的项目文件夹
cd desktop/workspace/vn/
pnpm init
Wrote to /Users/x/Desktop/workspace/vn/package.json
{
"name": "vn",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
arduino
mkdir packages
根目录新建pnpm-workspace.yaml
文件:
pnpm-workspace.yaml
packages:
- 'packages/*'
这样会将packages
下面归纳给到pnpm
工作空间进行管理
然后开始构建前后端:
前端使用vite
:
bash
cd packages
sudo pnpm create vite@latest
.../Library/pnpm/store/v3/tmp/dlx-7672 | +1 +
.../Library/pnpm/store/v3/tmp/dlx-7672 | Progress: resolved 1, reused 1, downloaded 0, added 1, done
✔ Project name: ... web
✔ Select a framework: › Vue
✔ Select a variant: › TypeScript
Scaffolding project in /Users/x/Desktop/workspace/vn/packages/web...
Done. Now run:
cd web
pnpm install
pnpm run dev
后端使用nest-cli
:
js
sudo nest new server
⚡ We will scaffold your app in a few seconds..
? Which package manager would you ❤️ to use? pnpm
CREATE server/.eslintrc.js (663 bytes)
CREATE server/.prettierrc (51 bytes)
CREATE server/README.md (3347 bytes)
CREATE server/nest-cli.json (171 bytes)
CREATE server/package.json (1947 bytes)
CREATE server/tsconfig.build.json (97 bytes)
CREATE server/tsconfig.json (546 bytes)
CREATE server/src/app.controller.ts (274 bytes)
CREATE server/src/app.module.ts (249 bytes)
CREATE server/src/app.service.ts (142 bytes)
CREATE server/src/main.ts (208 bytes)
CREATE server/src/app.controller.spec.ts (617 bytes)
CREATE server/test/jest-e2e.json (183 bytes)
CREATE server/test/app.e2e-spec.ts (630 bytes)
✔ Installation in progress... ☕
🚀 Successfully created project server
👉 Get started with the following commands:
$ cd server
$ pnpm run start
Thanks for installing Nest 🙏
Please consider donating to our open collective
to help us maintain this package.
🍷 Donate: https://opencollective.com/nest
在根目录中执行pnpm install
安装依赖
kotlin
cd workspace/vn/
pnpm install
Already up to date
Done in 248ms
sudo pnpm install
Scope: all 3 workspace projects
packages/web | WARN Moving @vitejs/plugin-vue that was installed by a different package manager to "node_modules/.ignored"
packages/web | WARN Moving typescript that was installed by a different package manager to "node_modules/.ignored"
packages/web | WARN Moving vue-tsc that was installed by a different package manager to "node_modules/.ignored"
packages/web | WARN Moving vite that was installed by a different package manager to "node_modules/.ignored"
packages/web | WARN Moving vue that was installed by a different package manager to "node_modules/.ignored"
Packages: +696
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 730, reused 621, downloaded 75, added 696, done
node_modules/.pnpm/@nestjs+core@10.3.2_@nestjs+common@10.3.2_@nestjs+platform-express@10.3.2_reflect-metadata@0.1.14_rxjs@node_modules/.pnpm/@nestjs+core@10.3.2_@nestjs+common@10.3.2_@nestjs+platform-express@10.3.2_reflect-metadata@0.1.14_rxjs@7.8.1/node_modules/@nestjs/core: Running postinstall script, done in 6.3s
node_modules/.pnpm/esbuild@0.19.12/node_modules/esbuild: Running postinstall script, done in 340ms
Done in 19.7s
然后分别启动两个项目, 没有问题:
对比两个子模块的package.json
文件:
web:
json
{
"name": "web",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.4.15"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.3",
"typescript": "^5.2.2",
"vite": "^5.1.0",
"vue-tsc": "^1.8.27"
}
}
server:
json
{
"name": "server",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.5.0",
"prettier": "^3.0.0",
"source-map-support": "^0.5.21",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
我们可以把公共的比如typescript
eslint
prettier
这些放到最外层的package.json
中,这样子模块可以共用:
这样:
json
{
"name": "vn",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "bsuooo",
"license": "ISC",
"devDependencies": {
"prettier": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"typescript": "^5.1.3"
}
}
我们把项目中的3
个node_modules
都删掉, 然后重新在根目录pnpm install
, 执行完后再看node_modules
:
共用的依赖已经在最外层了,重启web
和sever
也都没有问题。
在根目录创建tsconfig.json
文件:
json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@web": ["packages/web/src"],
"@server": ["packages/server/src"]
},
},
}
这是我们现在的目录结构:
项目规范
我们把nest生成的eslintrc.js
和prettier
放到根目录,与web
端共用。
同时把格式化脚本放到根目录package.json
的script
中:
json
"scripts": {
"lint": "eslint --cache --ext .js,.ts,.tsx",
"format": "prettier --write --cache ."
},
这样只需要在最外层执行一次命令就可以覆盖整个项目。
但是针对vue
项目,eslint是有特殊插件的,这个插件只有web
目录使用,所以我们只需要在web
中安装。
根目录运行命令:
css
pnpm install eslint-plugin-vue -D --filter web
然后在/packages/web
目录下创建.eslintrc.js
:
js
module.exports = {
extends: ['plugin:vue/vue3-essential'],
plugins: ['vue'],
};
这时还需要把web
的package.json
中的module
改为commonjs
这样eslint
就没问题了(不生效可以reload一下vscode)
.ignore文件
创建.gitignore
文件,这个文件可以过滤一些我们不想要托管到git
的目录或文件,比如node_modules
或者打包后的dist
等。
.gitignore
dist
node_modules
coverage
pnpm-workspace.yaml
.idea
*.log
.eslintcache
创建.eslintignore
,这个文件和过滤不需要eslint
检查的目录或文件。
.eslintignore
node_modules
dist
coverage
创建.prettierignore
这个是prettier
的
.prettierignore
dist
*.md
*.html
pnpm-lock.yaml
然后我们想每次代码提交到git
前,自动执行一次eslint
的检查,并使用prettier
格式化代码风格。这个就需要使用到husky
与lint-staged
。
安装husky
依赖并初始化:
csharp
// 安装
pnpm i -wD husky
// 初始化
pnpm dlx husky-init
pnpm dlx husky-init
会在根目录 创建 .husky
文件夹。
其中的pre-commit
就是每次git commit
前的钩子。
sh
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
这个就表示每次git commit
前会执行一次npm test
。
我们修改一下这个文件:
sh
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint && npm run format
现在每次git commit
时就会运行 检查并格式化代码。
但是这个这样是全量检查,每次执行范围都是全项目,我们想要的肯定是只检查我们修改 的内容, 而且我们修改后的代码还在暂存区中放着,并没有直接一起合到commit
中。
这个问题使用lint-staged
解决:
安装lint-staged
:
js
sudo pnpm i -wD lint-staged
Password:
Packages: +34 -1
++++++++++++++++++++++++++++++++++-
Progress: resolved 764, reused 725, downloaded 5, added 34, done
devDependencies:
- husky 9.0.10
+ husky 8.0.3 (9.0.10 is available)
+ lint-staged 15.2.2
Done in 6.8s
修改pre-commit
文件与package.json
文件:
pre-commit
:
package.json
:
这时我们测试一下,我们随便找个文件删掉一个;
然后提交一下代码:
已经格式化了, 说明我们配置的没问题。
小提示,commit在vscode中可以点这里撤回:
很多项目不仅仅对代码风格有要求,对commit message
也有要求,比如:
这个我们可以使用commitizen
进行检查:
安装依赖:
pnpm install --wD @commitlint/cli @commitlint/config-conventional
项目根目录中新建commitlint.config.js
文件:
js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat', // 新特性
'fix', // 修复
'docs', // 文档
'style', // 风格
'refactor', // 重构
'perf', // 优化
'test', // 测试
'build', // 构建流程、外部依赖变更
'ci', // 修改 CI 配置、脚本
'revert', // 回滚
'chore', // 对构建过程或辅助工具和库的更改
],
],
'type-case': [0],
'type-empty': [0],
'scope-empty': [0],
'scope-case': [0],
'subject-full-stop': [0, 'never'],
'subject-case': [0, 'never'],
'header-max-length': [0, 'always', 72],
},
};
config-conventional 是我们选用的commit
规范。
最后执行npx husky add .husky/commit-msg "npx commitlint --edit $1"
创建我们检测coomit-msg
的钩子。
测试一下, 随便输一个哈哈哈,报错:
来个正经的:
没有问题:
这样我们的规范设置就差不多了。
git地址:github.com/bsuooo/vn