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

2,477 阅读6分钟

前言

公司原先的大型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

本文只是简单实战,以下文章有相应介绍

初始化项目

基础目录结构

  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的编辑器插件,编码时提供提示,并配置保存时自动格式化 image.png
image.png
修改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项目并引用公用模块

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