# monorepo **Repository Path**: binary106/mono ## Basic Information - **Project Name**: monorepo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-11-06 - **Last Updated**: 2025-12-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 规范层面的统一化管理 ## 工作台配置 - 新建pnpm-workspace.yaml文件 ```yaml packages: - packages/* - apps/* ``` - 执行命令 ```js // 在根目录下init --workspace-root === -w pnpm --workspace-root init ``` - 锁定版本 ```json // packages.json "engines": { "node": ">=22.15.0", "npm": ">=10.9.2", "pnpm": ">=10.11.0" } // 新建.npmrc engine-strict=true ``` ## ts配置 - 安装ts ```js pnpm add typescript @types/node -Dw ``` - 新增tsconfig.json tsc --init -w ```json { "compilerOptions": { "module": "nodenext", "target": "esnext", "types": [], "sourceMap": true, "declaration": true, "declarationMap": true, "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "strict": true, "jsx": "react-jsx", "verbatimModuleSyntax": true, "isolatedModules": true, "noUncheckedSideEffectImports": true, "moduleDetection": "force", "skipLibCheck": true }, "include": ["**/*"], "exclude": ["node_modules", "dist"] } ``` ## prettier配置 - 安装prettier ```js // prettier检查代码格式(空格,分号),eslint检查代码质量(debugger,console.log),commitlint检查git提交的信息(feat) pnpm add prettier -Dw ``` - 新建prettier.config.js ```js // 只能使用js文件 export default { experimentalTernaries: false, // 三元运算 true:?在条件后 false:?和结果同行 printWidth: 80, // 一行代码宽度换行 tabWidth: 2, // 制表符宽度 useTabs: true, // 缩进使用制表符不使用空格 semi: true, // 末尾添加分号 singleQuote: true, // 使用单引号为不是双引号 quoteProps: 'as-needed', // 对象属性引号 as-needed consistent preserve jsxSingleQuote: false, // jsx中使用单引号而不是双引号 trailingComma: 'none', // 末尾逗号 all es5 none bracketSpacing: true, // 使用括号间距 bracketSameLine: false, // html闭合标签箭头>不要单独放一行 arrowParens: 'always', // 箭头函数单参数省略括号 always avoid // rangeStart: 0 格式化代码时,选取文件的一部分,从第几个字符开始 只能加命令中 不能加配置中 // rangeEnd: Infinity 格式化代码时,选取文件的一部分,从第几个字符结束 // parser解析器,会根据文件自动选择 无需配置 requirePragma: false, // true: 文件顶部有/** @prettier/@format */才会被格式化 项目逐步使用prettier适用 insertPragma: false, // 在文件顶部插入/** @format */ 用来表示这个文件已经被格式化了 proseWrap: 'preserve', // md文件的换行always never preserve htmlWhitespaceSensitivity: 'css', // html标签之间的空格处理方式 css strict ignore vueIndentScriptAndStyle: false, // vue文件script和style内要不要缩进 endOfLine: 'crlf', // 文件结尾符号是lf crlf cr auto(lf) embeddedLanguageFormatting: 'auto', // 对非js文件内的js代码字符串也格式化 auto off singleAttributePerLine: true // html vue jsx标签内属性独占一行 }; ``` - 新建.prettierignore文件 ```yaml # 排除掉不需要校验的文件 dist node_modules .local pnpm-lock.yaml public readme.md ``` - vscode安装Prettier - Code formatter ```js // 首选项 -> 设置 // Default Formatter: Prettier - Code formatter // Format On Save: 勾选 // Format On Save Mode: file ``` - 配置package.json ```json { "scripts": { "prettier": "prettier . --write", } } ``` ## eslint配置 - 安装eslint ```js pnpm add -Dw eslint@lastest @eslint/js@latest globals typescript-eslint eslint-plugin-prettier eslint-config-prettier eslint-plugin-vue eslint-plugin-react /** * eslint: 核心库 * @eslint/js 官方定义的js校验规则 * globals 全局变量支持 window document node全局变量 * typescript-eslint ts支持 * eslint-plugin-prettier(prettier错误支持报错到eslint里) * eslint-config-prettier(eslint和prettier做兼容) * eslint-plugin-vue vue支持 * eslint-plugin-react react支持 */ ``` - 新建eslint.config.js ```js import { defineConfig, globalIgnores } from 'eslint/config'; import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; import globals from 'globals'; import pluginVue from 'eslint-plugin-vue'; import pluginReact from 'eslint-plugin-react'; import eslintConfigPrettier from 'eslint-config-prettier/flat'; const ignores = ['**/node_modules/**', '**/dist/**', '.*', '**/*.d.ts']; export default defineConfig([ globalIgnores(ignores), // 为了容易区分全局和非全局 // 通用配置 { basePath: '.', // 要使用配置的文件夹路径(包括子目录) // files: [], // 通配符匹配要使用配置的文件,不配置表示所有文件 // 通配符匹配不使用配置的文件 如果只有这个一个配置项,表示全局忽略,如果有别的任意配置项(plugins,rules)则表示局部忽略(当前配置文件目录内的同层文件) 为了区分全局和非全局,可以用globalIgnores([])表示全局 // ignores: [], // 要应用的其他配置 也可以是一个对象,再来多个配置 extends内的变量也可以放在最外层和globalIgnores同级 extends: [ eslint.configs.recommended, // 这个配置是结合tseslint使用的 ...tseslint.configs.recommended, eslintConfigPrettier ], languageOptions: { // 配置代码检查的环境 ecmaVersion: 'latest', // esma版本 默认latest sourceType: 'module', // 模块类型 module commonjs 默认module globals: {}, // 检查期间添加到全局作用域 多个配置会合并 parser: { // 解析器 包含parse()或parseForESLint()方法的对象 ...tseslint.parser }, parserOptions: {} // 将此对象传递给parser的函数 }, // 内联配置:通过这样的方式实现:/*eslint semi: error*/ linterOptions: { noInlineConfig: true, // 是否禁止内联配置 reportUnusedDisableDirectives: 'warn', // 未使用的指令严重性 reportUnusedInlineConfigs: 'warn' // 未使用的内联配置严重性 }, // processor: {}, // 包含preprocess/postprocess函数的对象 plugins: {}, rules: { // 规则 off(0) warn(1) error(2) 'array-callback-return': 2, // 数组方法的回调中强制return 'constructor-super': 2, // 类contractor中需要使用supper 'for-direction': 2, // for循环中i++需要小于某个值,i--需要大于某个值 防止死循环 'getter-return': 2, // getter中执行return 'no-async-promise-executor': 2, // 禁止使用异步函数作为promise的参数 'no-await-in-loop': 2, // 禁止在循环中使用await 'no-class-assign': 2, // 禁止对类重新赋值 'no-compare-neg-zero': 2, // 禁止对-0进行比较 'no-cond-assign': 2, // 禁止在if()括号内赋值 'no-const-assign': 2, // 禁止对const using定义的值重新赋值 'no-constant-binary-expression': 2, // if或三目使用|| &&两边都是true或false会报错 'no-constant-condition': 2, // 禁止if(true) while(1)这种100%正确或错误的用法 'no-constructor-return': 2, // 类构造函数不能返回值 'no-control-regex': 0, // 禁止正则使用ASCII码0-31之间的字符和127字符 'no-debugger': 2, // 禁止使用debugger 'no-dupe-args': 2, // 禁止函数参数重复 'no-dupe-class-members': 2, // 禁止类中定义重复的属性 'no-dupe-else-if': 2, // 禁止if-else if条件重复 'no-dupe-keys': 2, // 禁止对象key重复 'no-unused-vars': 2, // 禁止变量定义了不使用 "no-unused-vars": 2, // 变量定义了未使用 '@typescript-eslint/no-unused-vars': 2, // 兼容ts }, settings: {} // key-value的对象,规则都会使用这些信息 }, // web端(包括组件) { files: [ 'apps/app-web/**/*.{ts,js,tsx,jsx,vue}', 'packages/ui/**/*.{ts,js,tsx,jsx,vue}' ], languageOptions: { globals: { ...globals.browser } }, rules: {} }, // web-vue项目 { files: [ 'apps/app-web/vue-project/**/*.{ts,js,vue}', 'packages/ui/vue-components/**/*.{ts,js,vue}' ], extends: [...pluginVue.configs['flat/recommended']], rules: { // 'no-unused-vars': 'error', 'no-console': 'error' } }, // web-react项目 { files: [ 'apps/app-web/react-project/**/*.{ts,js,tsx,jsx}', 'packages/ui/vue-components/**/*.{ts,js,tsx,jsx}' ], plugins: { pluginReact }, languageOptions: { parserOptions: { ecmaFeatures: { jsx: true } } }, rules: { 'react/jsx-uses-react': 'error', 'react/jsx-uses-vars': 'error' } } // express ...globals.node ]); ``` - 配置package.json ```json { "scripts": { "eslint": "eslint", } } ``` ## commitlint - 安装依赖 ```js pnpm -Dw add @commitlint/cli @commitlint/config-conventional commitizen cz-git // @commitlint/cli: 核心包 提供git-cz命令 // @commitlint/config-conventional: 提交时默认的询问信息 英文 // commitizan:不需要再使用git commit -m了 提供git cz命令 // cz-git:也可以用cz-conventional-changelog库,但是cz-git配置更灵活,配置一些询问信息 ``` - 新建.gitignore ```yaml node_modules dist build .env .env.* *.log .vscode .local .git ``` - 配置package.json ```json { "scripts": { "commit": "git cz" } } // 将commitizen和cz-git关联 "config": { "commitizen": { "path": "node_modules/cz-git" } } ``` - 配置commitlint.config.js ```js import { commitTypes } from './cz.config.js'; export default { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', commitTypes.map((type) => type.value)] } }; ``` - 配置cz.config.js ```js export const commitTypes = [ { value: 'feat', name: 'feat: 🚀 新功能', emoji: '🚀' }, { value: 'fix', name: 'fix: 🐛 修复', emoji: '🐛' }, { value: 'docs', name: 'docs: 📚 文档变更', emoji: '📚' }, { value: 'style', name: 'style: 💎 代码格式', emoji: '💎' }, { value: 'refactor', name: 'refactor: 📦 重构', emoji: '📦' }, { value: 'perf', name: 'perf: 🎯 性能优化', emoji: '🎯' }, { value: 'test', name: 'test: 🧪 测试', emoji: '🧪' }, { value: 'build', name: 'build: 🛠 构建系统', emoji: '🛠' }, { value: 'ci', name: 'ci: 💚 CI配置', emoji: '💚' } ]; export default { types: commitTypes, // name是提交可见的选项,value是真实提交的选项 scopes: [ { name: '核心代码', value: 'core' }, { name: '组件', value: 'component' }, { name: '样式', value: 'ui' }, { name: '配置', value: 'config' }, { name: '接口', value: 'api' }, { name: '文档', value: 'docs' } ], messages: { type: '选择你要提交的类型:', scope: '选择涉及的模块:', customScope: '输入自定义涉及的模块:', subject: '填写提交的简短描述(20字以内):', body: '填写详细描述:\n', breaking: '列出破坏性变更(如有:功能移除等):', footerPrefixesSelect: '选择 ISSUES 类型 (可选):', footer: '关联 ISSUES(例如: #31, #34):\n', footerPrefixes: '选择关联的 ISSUES 类型:', // 额外的自定义选项 footerSubjects: '输入关联的 ISSUES 编号:', confirmCommit: '确认提交?' }, // 允许自定义范围 allowCustomScopes: true, // 允许破坏性变更的类型 只有在"feat", "fix"才会询问message.breaking allowBreakingChanges: ['feat', 'fix'], // 跳过问题message中的key skipQuestions: [], // 主题长度限制 subjectLimit: 100, // 追加分支名到提交信息 appendBranchNameToCommitMessage: false }; ``` ## lint-staged && husky - 安装依赖 ```js // lint-staged:检查暂存区,询问问题之前执行 // husky:git hooks 询问问题之后执行 2者都需要git add pnpm add -Dw lint-staged husky ``` - 配置packages.json ```json { "scripts": { "precommit": "lint-staged", // 执行git cz之前会自动找precommit命令 } } ``` - 配置.lintstagedrc.js ```js export default { // key:要检查的文件 value:要运行的命令,也可以写成node xx.js "*.{js,jsx,ts,tsx,vue}": ["prettier --write", "eslint"] } ``` - 生成pre-commit ```js npx husky init // 生成pre-commit文件, 单纯的为了防止跳过命令,直接使用git commit -m提交代码 ``` - 配置pre-commit ```yaml # 只能使用npx或npm 不能直接使用pnpm npx pnpm precommit ```