前言

公司原先的大型web vue2项目运用lerna搭配yarn的workspaces实现的monorepo架构,年前leader要求要将vue2升级到vue3。
经过技能选型,最终确认了一个计划,并得到leader的肯定。后忙活了一段时间,成功将项目技能栈给升级了。最近不必加班,在家无事便想着将个人博客后台按monorepo办法再建立个玩并简略记录下。

目的:创立一个大型后台办理系统根底架构
所运用到的相关技能栈:

  • 包办理:pnpm天然支撑monorepo,依靠下载迅速,还节省空间…
  • 构建东西: vite新一代的构建东西,开发基于原生ESM加载,启动更快,热更新响应快…
  • 框架: vue3Composition Api、Proxy、Diff优化…
  • 组件库:Element Plus
  • 风格相关:ESLint + Stylelint + Prettier + husky + lint-staged

本文仅仅简略实战,以下文章有相应介绍

  • pnpm介绍
  • vite介绍
  • ESLint介绍
  • Stylelint介绍
  • husky + lint-staged 提交前履行代码查看

初始化项目

根底目录结构

  1. 初始化git仓库 git init
  2. 初始化package.json pnpm init
  3. 创立pnpm-workspace.yaml文件,界说作业区目录。(我把一些共用的库直接放到外层,项目放到projects文件夹下。这个可按个人或团队习惯装备,比如也将共用库放到一个文件下)
    packages:
       # 项目包目录,各项目在这下面创立
       - 'projects/*'
       # 共用组件目录
       - 'components'
       # 共用款式,主题相关
       - 'styles'
       # 东西库,一些公共办法,比如axios封装
       - 'utils'
       # 请求相关,各项目都会用到公共api,比如用户,共用图片上传
       - 'apis'
       # 扫除test相关
       - '**/test/*'
    
  4. 依据以上界说的作业区目录,在项目根目录下创立projectscomponentsstylesutilsapis文件夹

代码风格一致

个人主张,可依据项目类型装备格局化东西。
1,假如项目都是相同的,能够直接在根目录下装备一份即可,各项目下不必再装备。
2,如项目品种多(vue2,vue3,react,node..)能够在根目录装备共用同享装备,各项目下承继该装备再依据各自项目本身状况更改。

装备ESLint + Prettier

  1. 装置pnpm add eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-prettier eslint-config-prettier prettier eslint-plugin-vue @vue/eslint-config-prettier @vue/eslint-config-typescript -Dw
  2. 根目录创立以下装备文件以及内容如下
    • .esintrc.js:根底eslint装备,支撑ts,结合prettier
        /* eslint-env node */
        require('@rushstack/eslint-patch/modern-module-resolution')
        module.exports = {
          root: true,
          env: {
            browser: true,
            node: true,
            es2021: true,
          },
          extends: [
            'eslint:recommended',
            'plugin:@typescript-eslint/recommended',
            'plugin:prettier/recommended',
            // eslint-config-prettier 的缩写,覆盖抵触的eslint规矩
            // plugin:prettier/recommended内部extends装备了prettier规矩,
            // 测试过这儿不装备prettier也行,需求注意的是prettier规矩放最终
            'prettier',
          ],
          parserOptions: {
            ecmaVersion: 12,
            sourceType: 'module',
            ecmaFeatures: {
              jsx: true,
            },
          },
          plugins: [
            // eslint-plugin-prettier 缩写
            // plugin:prettier/recommended内部plugins装备了prettier插件,
            // 测试过这儿不装备prettier也行
            'prettier'
          ],
          rules: {},
          globals: {},
        }
      
    • eslintrc.vue3.js:vue3项目的eslint装备,作业区内的vue3项目可都引证此装备
      /* eslint-env node */
        require('@rushstack/eslint-patch/modern-module-resolution')
        module.exports = {
          root: true,
          extends: [
            './.eslintrc.js',
            'plugin:vue/vue3-recommended',
            '@vue/eslint-config-typescript',
            // 如需跳过prettier改成'@vue/eslint-config-prettier/skip-formatting',
            '@vue/eslint-config-prettier',
          ],
          plugins: [
            // eslint-plugin-vue 缩写
            // plugin:vue/vue3-recommended->basse内部plugins装备了vue插件,
            // 同样这儿不装备vue也行
            'vue'
          ],
        }
      
    • .prettierrc.js
      module.exports = {
        // 一行最多 120 字符..
        printWidth: 120,
        // 运用 2 个空格缩进
        tabWidth: 2,
        // 不运用缩进符,而运用空格
        useTabs: false,
        // 行尾是否需求分号
        semi: false,
        // 运用单引号
        singleQuote: true,
        // 目标的 key 仅在必要时用引号
        quoteProps: 'as-needed',
        // jsx 不运用单引号,而运用双引号
        jsxSingleQuote: false,
        // 末尾需求有逗号
        trailingComma: 'all',
        // 大括号内的首尾需求空格
        bracketSpacing: true,
        // jsx 标签的反尖括号需求换行
        jsxBracketSameLine: false,
        // 箭头函数,只要一个参数的时分,也需求括号
        arrowParens: 'always',
        // 每个文件格局化的范围是文件的全部内容
        rangeStart: 0,
        rangeEnd: Infinity,
        // 不需求写文件最初的 @prettier
        requirePragma: false,
        // 不需求主动在文件最初插入 @prettier
        insertPragma: false,
        // 运用默认的折行标准
        proseWrap: 'preserve',
        // 依据显示款式决议 html 要不要折行
        htmlWhitespaceSensitivity: 'css',
        // vue 文件中的 script 和 style 内不必缩进
        vueIndentScriptAndStyle: false,
        // 换行符运用 lf 可选值"<auto|lf|crlf|cr>"
        endOfLine: 'auto',
      };
      
    • .eslintignore .prettierignore
      node_modules/*
      dist/*
      asset/*
      *.d.ts
      
  3. package.json增加履行脚本
    {
       "scripts":{
           // ...
           "lint": "eslint . --fix"
           "prettier": "prettier --write \"**/*.{vue,js,jsx,ts,tsx}\"",
       }
    }
    

装备Stylelint + Prettier

Stylelint 和 ESLint的装备是极为类似的,

  1. 装置pnpm add stylelint stylelint-config-standard stylelint-config-standard-scss stylelint-config-standard-vue stylelint-config-prettier stylelint-order stylelint-prettier -Dw
  2. 根目录创立装备文件
    • stylelint.config.js
      module.exports = {
         extends: [
           'stylelint-config-standard-scss',
           'stylelint-config-standard-vue/scss',
           'stylelint-prettier/recommended',
           'stylelint-config-prettier',
         ],
         plugins: ['stylelint-order', 'stylelint-prettier'],
         rules: {
           'order/properties-order': [
             'display',
             'position',
             'float',
             'top',
             'right',
             'bottom',
             'left',
             'z-index',
             'width',
             'height',
             'max-width',
             'max-height',
             'min-width',
             'min-height',
             'padding',
             'padding-top',
             'padding-right',
             'padding-bottom',
             'padding-left',
             'margin',
             'margin-top',
             'margin-right',
             'margin-bottom',
             'margin-left',
             'margin-collapse',
             'margin-top-collapse',
             'margin-right-collapse',
             'margin-bottom-collapse',
             'margin-left-collapse',
             'overflow',
             'overflow-x',
             'overflow-y',
             'clip',
             'clear',
             'font',
             'font-family',
             'font-size',
             'font-smoothing',
             'osx-font-smoothing',
             'font-style',
             'font-weight',
             'line-height',
             'letter-spacing',
             'word-spacing',
             'color',
             'text-align',
             'text-decoration',
             'text-indent',
             'text-overflow',
             'text-rendering',
             'text-size-adjust',
             'text-shadow',
             'text-transform',
             'word-break',
             'word-wrap',
             'white-space',
             'vertical-align',
             'list-style',
             'list-style-type',
             'list-style-position',
             'list-style-image',
             'pointer-events',
             'cursor',
             'background',
             'background-color',
             'border',
             'border-radius',
             'content',
             'outline',
             'outline-offset',
             'opacity',
             'filter',
             'visibility',
             'size',
             'transform',
           ],
         },
       }
      
    • .stylelintignore
      node_modules/*
      dist/*
      public/*
      
  3. package.json增加履行脚本
    {
       "scripts":{
           // ...
           "lint:css": "stylelint **/*.{vue,css,sass,scss} --fix",
       }
    }
    

装置装备编辑器(vscode)插件

装置eslintstylelint的编辑器插件,编码时提供提示,并装备保存时主动格局化

pnpm + vite + vue3 + ESLint + Stylelint + TypeScript搭建monorepe项目

pnpm + vite + vue3 + ESLint + Stylelint + TypeScript搭建monorepe项目

修正settings.json文件

  // settings.json
  {
      // ...
      "editor.codeActionsOnSave": {
          "source.fixAll.eslint": true, 
          "source.fixAll.stylelint": true,
      },
      "stylelint.validate": [ "css", "sass", "scss", "vue"]
  }

husky + lint-staged 规范提交信息,履行格局校验

  1. 需求是一个git仓库
  2. 装置pnpm add husky lint-staged @commitlint/config-conventional @commitlint/cli -Dw
  3. 创立.husky文件夹(履行husky装置指令 pnpx husky install
  4. 增加钩子
    pre-commit: pnpx husky add .husky/pre-commit "npx lint-staged"
    commit-msg: pnpx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
  5. 修正packages.json,装备提交前需求履行的脚本。

    预提交场景中不应该运用--fix,因为假如它修正了某些问题,则 linting 会经过,但这些修正将不会暂存(因此不会包含在提交中)
    默认正告是不会阻挠提交的,要想正告也也阻挠提交可增加cli参数--max-warnings=0

    {
       "scripts": {
          "lint": "eslint . --max-warnings=0",
          "lint:fix": "eslint . --fix",
          "lint:css": "stylelint **/*.{vue,css,sass,scss} --max-warnings=0",
          "lint:css:fix": "stylelint **/*.{vue,css,sass,scss} --fix",
          "prettier": "prettier --write \"**/*.{vue,js,jsx,ts,tsx}\"",
          "prettier:fix": "prettier --write \"**/*.{vue,js,jsx,ts,tsx}\""
       },
       "lint-staged": { 
           "*.{vue,js,jsx,ts,tsx}": [ "npm run lint", "npm run prettier" ], 
           "*.{vue,css,sass,scss}": [ "npm run lint:css" ] 
       }
    }
    
  6. 项目根目录新建commitlint.config.js装备文件,规范提交信息。参阅装备如下
    // commitlint.config.js
    module.exports = {
      extends: ['@commitlint/config-conventional'],
      rules: {
        /**
         装备含义
          name: [ 
            等级( 0: disable,1: warning, 2: error ), 
            收效与否( always, never ),
            值
          ]
         */
        'type-enum': [
          2,
          'always',
          [
            'upd', // 更新某功用
            'feat', // 新增功用(feature)
            'fix', // 修正补丁(bug)
            'refactor', // 代码重构,未新增任何功用和修正任何 bug
            'docs', // 修订文档
            'style', // 仅调整空格、格局缩进等(不改动代码逻辑的变动)
            'test', // 测试用例的增加/修正
            'perf', // 优化相关,改善性能和体会的修正
            'chore', // 构建进程和辅助东西的变动
            'merge', // 兼并分支或抵触等
            'revert', // 回滚到上一个版本
            'build',  //改动构建流程,新增依靠库、东西等(例如 webpack、maven 修正)
            'ci' //主动化流程装备修正
          ],
        ],
        '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],
      },
    }
    

—– 目前为止,根底的项目结构和代码风格装备已完成,接下来将持续完善以下内容——-

  • axios封装
  • 共用接口
  • 共用办法
  • 创立vue3项目并引证共用模块

如有不对的地方还请体谅,欢迎指出~