从零到一搭建一个基础项目模板(一) --- 项目规范

123 阅读6分钟

项目用到的技术点: vue3.2 pnpm vite typescript pinia

一. 项目创建

执行 pnpm create vite 创建项目

pnpm create vite
Project name: basic-project
Select a framework: Vue
Select a variant: TypeScript

然后把项目跑起来

pnpm install
pnpm dev

好了,现在一个基础的项目已经完成了

二. ESLint 配置

安装 ESLint | 文件检查依赖 vue 解析器 vue-eslint-parser | 用于检查 vue 文件规范的 eslint-plugin-vue

pnpm add eslint vue-eslint-parser eslint-plugin-vue -D

在根目录下创建 .eslintrc.js 用于配置 ESlint

module.exports = {
  // ↓此项是用来告诉eslint找当前配置文件不能往父级查找
  root: true,
  // ↓指定你想启用的环境
  env: {
    browser: true,
    node: true,
    es6: true,
  },
  // ↓设置解析器
  parser: 'vue-eslint-parser',
  // ↓解析器选项
  parserOptions: {
    parser: '@typescript-eslint/parser',
    ecmaVersion: 2020,
    sourceType: 'module',
    jsxPragma: 'React',
    ecmaFeatures: {
      jsx: true,
    },
  },
  // ↓扩展项
  extends: [
    'plugin:vue/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier/recommended',
  ],
  // ↓自定义规则配置
  rules: {
    'vue/script-setup-uses-vars': 'error',
    // ↓禁止使用@ts-ignore来消除ESLint检查
    '@typescript-eslint/ban-ts-ignore': 'off',
    // ↓在函数和类方法上需要显式的返回类型
    '@typescript-eslint/explicit-function-return-type': 'off',
    // ↓禁止使用any类型
    '@typescript-eslint/no-explicit-any': 'off',
    // ↓除导入语句外,禁止使用require语句
    '@typescript-eslint/no-var-requires': 'off',
    // ↓禁止使用空函数
    '@typescript-eslint/no-empty-function': 'off',
    // ↓对自定义事件名称强制使用特定的大小写
    'vue/custom-event-name-casing': 'off',
    // ↓禁止定义前使用
    'no-use-before-define': 'off',
    // ↓在定义变量之前不允许使用变量
    '@typescript-eslint/no-use-before-define': 'off',
    // ↓禁止使用@ts-注解
    '@typescript-eslint/ban-ts-comment': 'off',
    // ↓禁止使用特定类型
    '@typescript-eslint/ban-types': 'off',
    // ↓禁止使用!后缀运算符进行非null断言
    '@typescript-eslint/no-non-null-assertion': 'off',
    // ↓在导出的函数和类的公共类方法上需要显式的返回值和参数类型
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    // ↓禁止使用未声明的变量
    '@typescript-eslint/no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      },
    ],
    'no-unused-vars': [
      'error',
      {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      },
    ],
    // ↓在函数括号前需要或不允许有空格
    'space-before-function-paren': 'off',
    // ↓强制属性顺序
    'vue/attributes-order': 'off',
    // ↓强制每个组件应位于其自己的文件中
    'vue/one-component-per-file': 'off',
    // ↓在标签的右括号之前要求或不允许换行
    'vue/html-closing-bracket-newline': 'off',
    // ↓强制每行的最大属性数
    'vue/max-attributes-per-line': 'off',
    // ↓在多行元素的内容之前和之后需要换行
    'vue/multiline-html-element-content-newline': 'off',
    // ↓在单行元素的内容之前和之后需要换行
    'vue/singleline-html-element-content-newline': 'off',
    // ↓在模板中的自定义组件上实施属性命名样式
    'vue/attribute-hyphenation': 'off',
    // ↓需要 prop 的默认值
    'vue/require-default-prop': 'off',
    'vue/require-explicit-emits': 'off',
    // ↓实施自我封闭的风格
    'vue/html-self-closing': [
      'error',
      {
        html: {
          void: 'always',
          normal: 'never',
          component: 'always',
        },
        svg: 'always',
        math: 'always',
      },
    ],
    'vue/multi-word-component-names': 'off',
  },
};

配置不需要 ESLint 校验的文件 根目录下新增 .eslintignore

`*.sh`
`node_modules`
`*.md`
`*.woff`
`*.ttf`
`.vscode`
`.idea`
`dist`
`/public`
`.husky`
`.local`
`/bin`

三. Editorconfig 编辑器统一规范

根目录下新增 .editorconfig 文件

`root = ``true`

`[*]`

`charset=utf-8`

`end_of_line=lf`

`insert_final_newline=``true`

`indent_style=space`

`indent_size=2`

`max_line_length = 100`
 

`[*.{yml,yaml,json}]`

`indent_style = space`

`indent_size = 2`


`[*.md]`

`trim_trailing_whitespace = ``false`
 

`[Makefile]`

`indent_style = tab`

四. TypeScript 规范

安装 TSLint

pnpm add @typescript-eslint/eslint-plugin @typescript-eslint/parser -D

根目录下修改 tsconfig.json 文件

{
    "compilerOptions": {
      // ↓指定ECMAScript目标版本,esnext为最新版本
      "target": "esnext",
      // ↓指定生成哪个模块系统代码,esnext为最新版本
      "module": "esnext",
      // ↓决定如何处理模块。
      "moduleResolution": "node",
      // ↓启用所有严格类型检查选项。
      "strict": true,
      "noLib": false,
      // ↓禁止对同一个文件的不一致的引用。
      "forceConsistentCasingInFileNames": true,
      // ↓允许从没有设置默认导出的模块中默认导入。这并不影响代码的输出,仅为了类型检查。
      "allowSyntheticDefaultImports": true,
      // ↓禁用函数参数双向协变检查。
      "strictFunctionTypes": false,
      // ↓在 .tsx文件里支持JSX
      "jsx": "preserve",
      // ↓解析非相对模块名的基准目录。查看 模块解析文档了解详情。
      "baseUrl": ".",
      // ↓允许编译javascript文件。
      "allowJs": true,
      // ↓生成相应的 .map文件。
      "sourceMap": true,
      "esModuleInterop": true,
      "resolveJsonModule": true,
      // ↓若有未使用的局部变量则抛错。
      "noUnusedLocals": true,
      // ↓若有未使用的参数则抛错。
      "noUnusedParameters": true,
      // ↓启用实验性的ES装饰器。
      "experimentalDecorators": true,
      // ↓编译过程中需要引入的库文件的列表。
      "lib": ["dom", "esnext"],
      // ↓要包含的类型声明文件名列表。
      "types": ["vite/client"],
      // ↓要包含的类型声明文件路径列表。
      "typeRoots": ["./node_modules/@types/", "./types"],
      "incremental": true,
      // ↓在表达式和声明上有隐含的 any类型时报错。
      "noImplicitAny": false,
      // ↓忽略所有的声明文件( *.d.ts)的类型检查。
      "skipLibCheck": true,
      "removeComments": true,
      // ↓模块名到基于 baseUrl的路径映射的列表。查看 模块解析文档了解详情。
      "paths": {
        "/@/*": ["src/*"],
        "/#/*": ["types/*"]
      }
    },
    // ↓指定一个匹配列表(属于自动指定该路径下的所有ts相关文件)
    "include": [
      "src/**/*.ts",
      "src/**/*.d.ts",
      "src/**/*.tsx",
      "src/**/*.vue",
      "types/**/*.d.ts",
      "types/**/*.ts",
      "build/**/*.ts",
      "build/**/*.d.ts",
      "vite.config.ts"
    ],
    // 指定一个排除列表(include的反向操作)
    "exclude": ["node_modules", "dist", "**/*.js"]
  }

五. Prettier 代码格式化

安装 prettier

pnpm add prettier -D

prettier 和 ESLint 有冲突 安装 eslint-plugin-prettier | eslint-config-prettier  解决冲突 将  prettier 一些规则默认关闭

pnpm add eslint-plugin-prettier eslint-config-prettier -D

根目录下新建 prettier.config.js 文件用于配置 prettier

module.exports = {
  printWidth: 100,
  semi: true,
  vueIndentScriptAndStyle: true,
  singleQuote: true,
  trailingComma: 'all',
  proseWrap: 'never',
  htmlWhitespaceSensitivity: 'strict',
  endOfLine: 'auto',
};

根目录下新建 .prettierignore 文件用于配置忽略校验的文件

/dist/*
.local
.output.js
/node_modules/**

**/*.svg
**/*.sh

/public/*

六. StyleLint css样式规范

安装 styleLint

  • stylelint 是对我们编写的样式进行检查的插件。
  • stylelint-config-standard 是 stylelint **``**扩展的检查标准库
  • stylelint-config-prettier 用来解决 prettier 冲突
  • stylelint-order 是检查样式编写顺序
  • stylelint-config-recess-order 保存时自动修复
  • stylelint-config-recommended 解决 stylelint 14 版本问题
  • stylelint-config-recommended-vue 解决 stylelint 14 版本问题
  • stylelint-config-recommended-less 解决 stylelint 14 版本问题
  • stylelint-config-html 解决 stylelint 14 版本问题
  • postcss 解析器 把 css 转换为 EsTree
  • postcss-html
  • postcss-less
pnpm add stylelint stylelint-config-standard stylelint-config-prettier stylelint-order stylelint-config-recommended stylelint-config-recommended-vue -D
pnpm add stylelint-config-recess-order stylelint-config-recommended-less stylelint-config-html postcss postcss-html postcss-less -D

在根目录下新建 stylelint.config.js 用于配置 styleLint

module.exports = {
  root: true,
  plugins: ['stylelint-order'],
  extends: ['stylelint-config-standard', 'stylelint-config-prettier'],
  customSyntax: 'postcss-html',
  rules: {
    'function-no-unknown': null,
    'selector-class-pattern': null,
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['global'],
      },
    ],
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep'],
      },
    ],
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          'tailwind',
          'apply',
          'variants',
          'responsive',
          'screen',
          'function',
          'if',
          'each',
          'include',
          'mixin',
        ],
      },
    ],
    'no-empty-source': null,
    'string-quotes': null,
    'named-grid-areas-no-invalid': null,
    'unicode-bom': 'never',
    'no-descending-specificity': null,
    'font-family-no-missing-generic-family-keyword': null,
    'declaration-colon-space-after': 'always-single-line',
    'declaration-colon-space-before': 'never',
    // 'declaration-block-trailing-semicolon': 'always',
    'rule-empty-line-before': [
      'always',
      {
        ignore: ['after-comment', 'first-nested'],
      },
    ],
    'unit-no-unknown': [true, { ignoreUnits: ['rpx'] }],
    'order/order': [
      [
        'dollar-variables',
        'custom-properties',
        'at-rules',
        'declarations',
        {
          type: 'at-rule',
          name: 'supports',
        },
        {
          type: 'at-rule',
          name: 'media',
        },
        'rules',
      ],
      { severity: 'warning' },
    ],
  },
  ignoreFiles: ['**/*.js', '**/*.jsx', '**/*.tsx', '**/*.ts'],
  overrides: [
    {
      files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
      extends: ['stylelint-config-recommended'],
      rules: {
        'keyframes-name-pattern': null,
        'selector-pseudo-class-no-unknown': [
          true,
          {
            ignorePseudoClasses: ['deep', 'global'],
          },
        ],
        'selector-pseudo-element-no-unknown': [
          true,
          {
            ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'],
          },
        ],
      },
    },
    {
      files: ['*.less', '**/*.less'],
      customSyntax: 'postcss-less',
      extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
    },
  ],
};