美文网首页vue 好吧
从 0 搭建 Vite 3 + Vue 3 前端工程化项目

从 0 搭建 Vite 3 + Vue 3 前端工程化项目

作者: 元宇宙编程 | 来源:发表于2023-06-05 09:15 被阅读0次

    Vue 3 正式版已经发布有一段时间了,随着 Vite 脚手架注定成为下一代前端工具链,许多用户都想基于 Vite 来构建 Vue 项目,如果想基于 Vite 构建 Vue 3 项目,社区模板完全满足您的需求,如果想构建 Vite 3 + Vue 3 + JavaScript 项目,那社区模板不太能满足您的需求,因为社区模板提供 Vue 3 项目几乎是基于 Vite 2 + TypeScript 构建,对于不熟悉 TypeScript 语言的用户不是很友好,因此接下来从 0 开始手把手带大家搭建一套规范的 Vite 3 + Vue 3 + JavaScript 前端工程化项目环境。

    本文章篇幅较长,从以下几个方面展开:

    • 基础搭建
    • 代码规范
    • 提交规范
    • 自动部署
    技术栈
    • ⚡️ Vite 3[2] - 构建工具(就是快!)
    • 🖖 Vue 3[3] - 渐进式 JavaScript 框架
    • 🚦 Vue Router[4] - 官方路由管理器
    • 📦 Pinia[5] - 值得你喜欢的 Vue Store
    • 💻 TDesign[6] - TDesign 适配桌面端的组件库
    • 🎨 Less[7] - CSS 预处理器
    • 🔗 Axios[8] - 一个基于 promise 的网络请求库,可以用于浏览器和 node.js
    • 🧰 Husky[9] + Lint-Staged[10] - Git Hook 工具
    • 🛡️ EditorConfig[11] + ESLint[12] + Prettier[13] + Stylelint[14] - 代码规范
    • 🔨 Commitizen[15] + Commitlint[16] - 提交规范
    • 💡 GitHub Actions[17] - 自动部署
    基础搭建

    确保你安装了最新版本的 Node.js[18],然后在命令行中运行以下命令:

    # npm 6.x
    npm create vite@latest vite-vue-js-template --template vue
    
    # npm 7+, extra double-dash is needed:
    npm create vite@latest vite-vue-js-template -- --template vue
    
    # yarn
    yarn create vite vite-vue-js-template --template vue
    
    # pnpm
    pnpm create vite vite-vue-js-template --template vue
    

    这一指令将会安装并执行 create-vite,它是一个基本模板快速启动项目工具。

    在项目被创建后,通过以下步骤安装依赖并启动开发服务器:

    # 打开项目
    cd <your-project-name>
    
    # 安装依赖
    npm install
    
    # 启动项目
    npm run dev
    
    Vite 基础配置

    Vite 配置文件 vite.config.js 位于项目根目录下,项目启动时会自动读取。

    本项目针对公共基础路径、自定义路径别名、服务器选项、构建选项等做了如下基础配置:

    import { defineConfig } from 'vite';
    import { resolve } from 'path';
    import vue from '@vitejs/plugin-vue';
    export default defineConfig({
    base: './',
    plugins: [
      vue(),
    ],
    resolve: {
      alias: {
        '@': resolve(__dirname, './src') ,
      },
    },
    server: {
      // 是否开启 https
      https: false,
      // 端口号
      port: 3000,
      // 监听所有地址
      host: '0.0.0.0',
      // 服务启动时是否自动打开浏览器
      open: true,
      // 允许跨域
      cors: true,
      // 自定义代理规则
      proxy: {},
    },
    build: {
      // 设置最终构建的浏览器兼容目标
      target: 'es2015',
      // 构建后是否生成 source map 文件
      sourcemap: false,
      //  chunk 大小警告的限制(以 kbs 为单位)
      chunkSizeWarningLimit: 2000,
      // 启用/禁用 gzip 压缩大小报告
      reportCompressedSize: false,
      },
     });
    
    规范目录结构
     ├── dist/
     └── src/
       ├── api/                       // 接口请求目录
       ├── assets/                    // 静态资源目录
       ├── common/                    // 通用类库目录
       ├── components/                // 公共组件目录
       ├── router/                    // 路由配置目录
       ├── store/                     // 状态管理目录
       ├── style/                     // 通用样式目录
       ├── utils/                     // 工具函数目录
       ├── views/                     // 页面组件目录
       ├── App.vue
       ├── main.js
    ├── tests/                         // 单元测试目录
    ├── index.html
    ├── jsconfig.json                  // JavaScript 配置文件
    ├── vite.config.js                 // Vite 配置文件
    └── package.json
    
    集成 Vue Router 路由工具
    安装依赖
    npm i vue-router@4
    
    创建路由配置文件

    在 src/router 目录下新建 index.js 文件与 modules 文件夹

    └── src/
            ├── router/
                ├── modules/  // 路由模块
                ├── index.js  // 路由配置文件
    

    关于路由表,建议根据功能的不同来拆分到 modules 文件夹中,好处是:

    • 方便后期维护

    • 减少 Git 合并代码冲突可能性

        export default [
      {
        path: '/',
        name: 'home',
        component: () => import('@/views/HomeView.vue'),
      },
      {
       path: '/about',
       name: 'about',
       component: () => import('@/views/AboutView.vue'),
       },
      ];
      
        import { createRouter, createWebHistory } from 'vue-router';
        import baseRouters from './modules/base';
        const routes = [...baseRouters];
        const router = createRouter({
        history: createWebHistory(import.meta.env.BASE_URL),
        routes,
       scrollBehavior() {
        return {
         el: '#app',
         top: 0,
         behavior: 'smooth',
           };
         },
       });
      
       export default router;
      

    根据路由配置的实际情况,需要在 src 下创建 views 目录,用来存储页面组件。

    挂载路由配置

    在 main.js 文件中挂载路由配置

     import { createApp } from 'vue';
     import App from './App.vue';
     import router from './router';
     createApp(App).use(router).mount('#app');
    
    集成 Pinia 全局状态管理工具
    • 安装依赖

        npm i pinia
      
    创建仓库配置文件

    在 src/store 目录下新建 index.js 文件与 modules 文件夹

    └── src/
       ├── store/
            ├── modules/  // 仓库模块
            ├── index.js  // 仓库配置文件
    
     import { defineStore } from 'pinia';
     export const useCounterStore = defineStore('counter', {
     state: () => ({
       count: 1,
     }),
     actions: {
      accumulate() {
        this.count++;
      },
     },
    });
    
    
     import { createPinia } from 'pinia';
     const store = createPinia();
     export default store;
     export * from './modules/counter';
    

    开发中需要将不同功能所对应的状态,拆分到不同的 modules,好处如同路由模块一样。

    挂载 Pinia 配置

    在 main.js 文件中挂载 Vuex 配置

    import { createApp } from 'vue';
    import App from './App.vue';
    import store from './store';
    import router from './router';
    createApp(App).use(router).use(store).mount('#app');
    
    集成 TDesign Vue Next 组件库
    安装依赖
     npm i tdesign-vue-next
    
    基础使用
     import { createApp } from 'vue';
     import TDesign from 'tdesign-vue-next';
     // 引入组件库全局样式资源
     import 'tdesign-vue-next/es/style/index.css';
     const app = createApp(App);
     app.use(TDesign);
    
    按需引入

    使用 unplugin-vue-components 和 unplugin-auto-import 来实现自动导入:

      npm install unplugin-vue-components unplugin-auto-import -D
    

    在 Vite 对应的配置文件 vite.config.js 添加上述插件:

    import AutoImport from 'unplugin-auto-import/vite';
    import Components from 'unplugin-vue-components/vite';
    import { TDesignResolver } from 'unplugin-vue-components/resolvers';
    
    export default {
      plugins: [
       AutoImport({
        resolvers: [TDesignResolver({
          library: 'vue-next'
       })],
       }),
       Components({
         resolvers: [TDesignResolver({
           library: 'vue-next'
         })],
       }),
      ],
     };
    
    集成 Axios HTTP 工具
    安装依赖
     npm i axios
    
    请求配置

    在 utils 目录下创建 request.js 文件,配置好适合自己业务的请求拦截和响应拦截:

      └── src/
                ├── api  // 接口
           ├── utils/
                ├── request.js  // axios 请求库二次封装
    
      import axios from 'axios';
      // 创建请求实例
      const instance = axios.create({
        baseURL: '/api',
       // 指定请求超时的毫秒数
        timeout: 1000,
       // 表示跨域请求时是否需要使用凭证
       withCredentials: false,
      });
    
     // 前置拦截器(发起请求之前的拦截)
      instance.interceptors.request.use(
       (config) => {
        /**
         * 在这里一般会携带前台的参数发送给后台,比如下面这段代码:
         * const token = getToken()
         * if (token) {
         *  config.headers.token = token
         * }
         */
        return config;
       },
      (error) => {
         return Promise.reject(error);
        },
     );
    
      // 后置拦截器(获取到响应时的拦截)
     instance.interceptors.response.use(
       (response) => {
    /**
     * 根据你的项目实际情况来对 response 和 error 做处理
     * 这里对 response 和 error 不做任何处理,直接返回
     */
       return response;
      },
      (error) => {
      const { response } = error;
      if (response && response.data) {
        return Promise.reject(error);
      }
      const { message } = error;
      console.error(message);
      return Promise.reject(error);
      },
     );
    
     // 导出常用函数
    /**
      * @param {string} url
      * @param {object} data
      * @param {object} params
      */
     export function post(url, data = {}, params = {}) {
       return instance({
       method: 'post',
       url,
       data,
       params,
       });
     }
    
    /**
      * @param {string} url
      * @param {object} params
     */
     export function get(url, params = {}) {
       return instance({
        method: 'get',
        url,
        params,
      });
    }
    
    /**
      * @param {string} url
      * @param {object} data
      * @param {object} params
      */
     export function put(url, data = {}, params = {}) {
          return instance({
           method: 'put',
           url,
           params,
           data,
       });
      }
    
     /**
      * @param {string} url
      * @param {object} params
      */
     export function _delete(url, params = {}) {
      return instance({
      method: 'delete',
      url,
      params,
      });
     }
    
    export default instance;
    

    之后在 api 文件夹中以业务模型对接口进行拆分,举个例子,将所有跟用户相关接口封装在 User 类中,此类称作用户模型。

    在 User 类中比如有登录、注册、获取用户信息等方法,如果有业务逻辑变动,只需要修改相关方法即可。

     import { post } from '@/utils/request';
     export default class User {
      /**
       * 登录
      * @param {String} username 用户名
      * @param {String} password 密码
      * @returns
      */
      static async login(username, password) {
       return post('/login', {
        username,
         password,
       });
      }
     }
    

    把每个业务模型独立成一个 js 文件,声明一个类通过其属性和方法来实现这个模型相关的数据获取,这样可以大大提升代码的可读性与可维护性。

    模拟演示

    在需要使用接口的地方,引入对应的业务模型文件,参考如下:

     <script>
     import User from '@/api/user';
     export default {
      data() {
        return {
          username: '',
          password: '',
       };
     },
     methods: {
     async login() {
       const res = await User.login(this.username, this.password);
       console.log(res);
     },
     },
    };
    </script>
    
    集成 CSS 预处理器 Less

    本项目使用 CSS 预处理器 Less,直接安装为开发依赖即可。

    Vite 内部已帮我们集成了相关的 loader,不需要额外配置。

    安装依赖
      npm i less -D
    
    如何使用

    在 <style></style> 样式标签中引用 lang="less" 即可。

     <style lang="less"></style>
    

    CSS 命名规范推荐 BEM 命名规范

    全局样式

    在 src/style 目录下创建 variables.less 全局样式文件:

     └── src/
         ├── style/
             ├── variables.less  // 全局样式文件
    

    在 vite.config.js 配置文件中新增CSS 预处理器相关配置即可实现 less 全局样式:

    import { resolve } from 'path';
    export default defineConfig({
    css: {
      preprocessorOptions: {
        less: {
          modifyVars: {
            hack: `true; @import (reference) "${resolve('src/style/variables.less')}";`,
          },
          math: 'strict',
          javascriptEnabled: true,
           },
         },
      },
    });
    
    样式穿透

    在 Vue3 中,改变了以往样式穿透的语法,如果继续使用 ::v-deep、/deep/、>>> 等语法的话,会出现一个警告,下面是新的语法:

    /* 深度选择器 */
     :deep(selector) {
        /* ... */
     }
    
    /* 插槽选择器 */
    :slotted(selector) {
       /* ... */
     }
    
    /* 全局选择器 */
    :global(selector) {
     /* ... */
    }
    

    至此,一个基于 JavaScript + Vite3 + Vue3 + Vue Router + Pinia + Axios + Less 的前端项目开发环境搭建完毕。

    接下来增加代码规范约束、提交规范约束、单元测试、自动部署等,让其更完善、更健壮。

    代码规范

    随着前端应用逐渐变得大型化和复杂化,在同一个项目中有多个人员参与时,每个人的前端能力程度不等,他们往往会用不同的编码风格和习惯在项目中写代码,长此下去,势必会让项目的健壮性越来越差。解决这些问题,理论上讲,口头约定和代码审查都可以,但是这种方式无法实时反馈,而且沟通成本过高,不够灵活,更关键的是无法把控。不以规矩,不能成方圆,我们不得不在项目使用一些工具来约束代码规范。

    本文讲解如何使用 EditorConfig + ESLint + Prettier + Stylelint 组合来实现代码规范化。

    这样做带来好处:

    • 解决团队之间代码不规范导致的可读性差和可维护性差的问题。
    • 解决团队成员不同编辑器导致的编码规范不统一问题。
    • 提前发现代码风格问题,给出对应规范提示,及时修复。
    • 减少代码审查过程中反反复复的修改过程,节约时间。
    • 自动格式化,统一编码风格,从此和脏乱差的代码说再见。

    EditorConfig 主要用于统一不同 IDE 编辑器的编码风格。

    在项目根目录下添加 .editorconfig 文件:

     # 表示是最顶层的 EditorConfig 配置文件
       root = true
     # 表示所有文件适用
      [*]
     # 缩进风格(tab | space)
      indent_style = space
     # 控制换行类型(lf | cr | crlf)
      end_of_line = lf
    # 设置文件字符集为 utf-8
      charset = utf-8
    # 去除行首的任意空白字符
      trim_trailing_whitespace = true
    # 始终在文件末尾插入一个新行
      insert_final_newline = true
    # 表示仅 md 文件适用以下规则
     [*.md]
     max_line_length = off
     trim_trailing_whitespace = false
    # 表示仅 ts、js、vue、css 文件适用以下规则
     [*.{ts,js,vue,css}]
     indent_size = 2
    

    很多 IDE 中会默认支持此配置,但是也有些不支持,如:VSCode、Atom、Sublime Text 等。具体列表可以参考官网,如果在 VSCode 中使用需要安装 EditorConfig for VS Code 插件。

    集成 ESLint 配置

    ESLint 是针对 EScript 的一款代码检测工具,它可以检测项目中编写不规范的代码,如果写出不符合规范的代码会被警告。

    由此我们就可以借助于 ESLint 强大的功能来统一团队的编码规范。

    安装依赖
    • ESLint - ESLint 本体

    • eslint-define-config - 改善 ESLint 规范编写体验

    • eslint-plugin-vue - 适用于 Vue 文件的 ESLint 插件

    • eslint-config-airbnb-base - Airbnb JavaScript 风格指南

    • eslint-plugin-import - 使用 eslint-config-airbnb-base 时必须安装的前置插件

    • vue-eslint-parser - 使用 eslint-plugin-vue 时必须安装的 ESLint 解析器

         npm i eslint eslint-define-config eslint-config-airbnb-base eslint-plugin-import eslint-plugin-vue vue-eslint-parser -D
      
    安装插件

    Visual Studio Code 编辑器使用 ESLint 配置需要下载插件 ESLint 。

    JetBrains 系列编辑器(WebStorm、IntelliJ IDEA 等)则不用额外安装插件。

    创建 ESLint 配置文件

    在项目根目录创建 .eslintrc.js 文件,并填入以下内容:

      const { defineConfig } = require('eslint-define-config');
     module.exports = defineConfig({
      root: true,
      env: {
       browser: true,
       node: true,
       jest: true,
       es6: true,
      },
     plugins: ['vue'],
     parser: 'vue-eslint-parser',
     parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    allowImportExportEverywhere: true,
     ecmaFeatures: {
      jsx: true,
       },
    },
     extends: [
     'airbnb-base',
     'eslint:recommended',
     'plugin:vue/vue3-essential',
     'plugin:vue/vue3-recommended',
     'plugin:prettier/recommended',
     ],
     rules: {
    // 禁止使用多余的包
    'import/no-extraneous-dependencies': 0,
    // 确保在导入路径内一致使用文件扩展名
    'import/extensions': 0,
    // 确保导入指向可以解析的文件/模块
    'import/no-unresolved': 0,
    // 首选默认导出导入/首选默认导出
    'import/prefer-default-export': 0,
    // 要求使用 let 或 const 而不是 var
    'no-var': 'error',
    // 禁止使用 new 以避免产生副作用
    'no-new': 1,
    // 禁止变量声明与外层作用域的变量同名
    'no-shadow': 0,
    // 禁用 console
    'no-console': 0,
    // 禁止标识符中有悬空下划线
    'no-underscore-dangle': 0,
    // 禁止在可能与比较操作符相混淆的地方使用箭头函数
    'no-confusing-arrow': 0,
    // 禁用一元操作符 ++ 和 --
    'no-plusplus': 0,
    // 禁止对 function 的参数进行重新赋值
    'no-param-reassign': 0,
    // 禁用特定的语法
    'no-restricted-syntax': 0,
    // 禁止在变量定义之前使用它们
    'no-use-before-define': 0,
    // 禁止直接调用 Object.prototypes 的内置属性
    'no-prototype-builtins': 0,
    // 禁止可以在有更简单的可替代的表达式时使用三元操作符
    'no-unneeded-ternary': 'error',
    // 禁止重复模块导入
    'no-duplicate-imports': 'error',
    // 禁止在对象中使用不必要的计算属性
    'no-useless-computed-key': 'error',
    // 强制使用一致的缩进
    indent: ['error', 2],
    // 强制使用骆驼拼写法命名约定
    camelcase: 0,
    // 强制类方法使用 this
    'class-methods-use-this': 0,
    // 要求构造函数首字母大写
    'new-cap': 0,
    // 强制一致地使用 function 声明或表达式
    'func-style': 0,
    // 强制一行的最大长度
    'max-len': 0,
    // 要求 return 语句要么总是指定返回的值,要么不指定
    'consistent-return': 0,
    // 强制switch要有default分支
    'default-case': 2,
    // 强制剩余和扩展运算符及其表达式之间有空格
    'rest-spread-spacing': 'error',
    // 要求使用 const 声明那些声明后不再被修改的变量
    'prefer-const': 'error',
    // 强制箭头函数的箭头前后使用一致的空格
     'arrow-spacing': 'error',
    },
    overrides: [
    {
      files: ['*.vue'],
      rules: {
        // 要求组件名称总是多个单词
        'vue/multi-word-component-names': 0,
      },
    },
    ],
    });
    

    关于更多配置项信息,请前往 ESLint 官网查看

    创建 ESLint 过滤规则

    在项目根目录添加一个 .eslintignore 文件,内容如下:

    dist
    node_modules
    !.prettierrc.js
    
    集成 Prettier 配置
     npm i prettier -D
    

    安装插件

    Visual Studio Code 编辑器使用 Prettier 配置需要下载插件 Prettier - Code formatter 。

    JetBrains 系列编辑器(WebStorm、IntelliJ IDEA 等)则不用额外安装插件,可直接使用 Prettier 配置。

    创建 Prettier 配置文件

    Prettier 支持多种格式的配置文件[34],比如 .json、.yml、.yaml、.js等。

    在项目根目录创建 .prettierrc.js 文件,并填入以下内容:

     module.exports = {
      // 一行最多 120 字符
      printWidth: 120,
     // 使用 2 个空格缩进
     tabWidth: 2,
    // 不使用缩进符,而使用空格
     useTabs: false,
     // 行尾需要有分号
      semi: true,
     // 使用单引号
     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
     endOfLine: 'lf',
     // 格式化嵌入的内容
     embeddedLanguageFormatting: 'auto',
     // html, vue, jsx 中每个属性占一行
     singleAttributePerLine: false,
    };
    

    关于更多配置项信息,请前往 Prettier 官网查看

    创建 Prettier 过滤规则

    在项目根目录添加一个 .prettierignore 文件,内容如下:

    ## OS
    .DS_Store
    .idea
    .editorconfig
     pnpm-lock.yaml
    .npmrc
    
    # Ignored suffix
    *.log
    *.md
    *.svg
    *.png
    *.ico
    *ignore
    
    ## Local
    .husky
    ## Built-files
    .cache
     dist
    
    解决 Prettier 和 ESLint 冲突

    本项目中的 ESLint 配置使用了 Airbnb JavaScript 风格指南校验,其规则之一是代码结束后面要加分号,而在 Prettier 配置文件中加了代码结束后面不加分号配置项,从而冲突了。

    解决两者冲突问题,需要用到 eslint-plugin-prettier 和 eslint-config-prettier。

    • eslint-plugin-prettier 将 Prettier 的规则设置到 ESLint 的规则中
    • eslint-config-prettier 关闭 ESLint 中与 Prettier 中会发生冲突的规则
      最后形成优先级:Prettier 配置规则 > ESLint 配置规则
    安装依赖
       npm i eslint-plugin-prettier eslint-config-prettier -D
    
    修改 ESLint 配置文件

    修改 .eslintrc.js 文件,在 extends 中添加 plugin:prettier/recommended 规则(此规则一定要加在最后)。

     module.exports = {
      extends: [
        'airbnb-base',
        'eslint:recommended',
       'plugin:vue/vue3-essential',
       'plugin:vue/vue3-recommended',
       'plugin:prettier/recommended'
      ],
    }
    

    Visual Studio Code 在 settings.json 设置文件中,增加以下代码:

    {
      "editor.codeActionsOnSave": {
      "source.fixAll": true,
       "source.fixAll.eslint": true
      }
    }
    
    集成 Stylelint 配置

    Stylelint 是一个强大、先进的 CSS 代码检查器(linter),可以帮助你规避 CSS 代码中的错误并保持一致的编码风格。

    安装依赖
    • Stylelint - Stylelint 本体

    • stylelint-config-prettier - 关闭 Stylelint 中与 Prettier 中会发生冲突的规则

    • stylelint-config-standard - Stylelint 官方推荐规则

    • stylelint-config-recommended-vue - 检验 vue 文件中的样式

    • stylelint-order - CSS 属性顺序规则插件

      npm i stylelint stylelint-config-prettier stylelint-config-standard stylelint-config-recommended-vue stylelint-order -D
      
    安装插件

    Visual Studio Code 编辑器使用 Stylelint 配置需要下载插件 Stylelint 。

    JetBrains 系列编辑器(WebStorm、IntelliJ IDEA 等)则不用额外安装插件。

    创建 Stylelint 配置文件

    在项目根目录创建 .stylelintrc.js 文件,并填入以下内容:

    module.exports = {
     root: true,
     defaultSeverity: 'error',
     extends: [
       'stylelint-config-standard',
       'stylelint-config-prettier'
     ],
     plugins: ['stylelint-order'],
      rules: {
    // 不允许未知函数
    'function-no-unknown': null,
    // 指定类选择器的模式
    'selector-class-pattern': null,
    // 禁止空源码
    'no-empty-source': null,
    // 指定字符串使用单引号
    'string-quotes': 'single',
    // 禁止未知的@规则
    'at-rule-no-unknown': [
      true,
      {
        ignoreAtRules: [
          'tailwind',
          'apply',
          'variants',
          'responsive',
          'screen',
          'function',
          'if',
          'each',
          'include',
          'mixin',
        ],
      },
    ],
    // 指定@规则名的大小写
    'at-rule-name-case': 'lower',
    // 指定缩进
    indentation: [
      2,
      {
        severity: 'warning',
      },
    ],
    // 禁止未知的伪类选择器
    'selector-pseudo-class-no-unknown': [
      true,
      {
        ignorePseudoClasses: ['global'],
      },
    ],
    // 禁止未知的伪元素选择器
    'selector-pseudo-element-no-unknown': [
      true,
      {
        ignorePseudoElements: ['v-deep'],
      },
    ],
    'order/properties-order': [
      'position',
      'top',
      'right',
      'bottom',
      'left',
      'z-index',
      'display',
      'justify-content',
      'align-items',
      'float',
      'clear',
      'overflow',
      'overflow-x',
      'overflow-y',
      'margin',
      'margin-top',
      'margin-right',
      'margin-bottom',
      'margin-left',
      'padding',
      'padding-top',
      'padding-right',
      'padding-bottom',
      'padding-left',
      'width',
      'min-width',
      'max-width',
      'height',
      'min-height',
      'max-height',
      'font-size',
      'font-family',
      'font-weight',
      'border',
      'border-style',
      'border-width',
      'border-color',
      'border-top',
      'border-top-style',
      'border-top-width',
      'border-top-color',
      'border-right',
      'border-right-style',
      'border-right-width',
      'border-right-color',
      'border-bottom',
      'border-bottom-style',
      'border-bottom-width',
      'border-bottom-color',
      'border-left',
      'border-left-style',
      'border-left-width',
      'border-left-color',
      'border-radius',
      'text-align',
      'text-justify',
      'text-indent',
      'text-overflow',
      'text-decoration',
      'white-space',
      'color',
      'background',
      'background-position',
      'background-repeat',
      'background-size',
      'background-color',
      'background-clip',
      'opacity',
      'filter',
      'list-style',
      'outline',
      'visibility',
      'box-shadow',
      'text-shadow',
      'resize',
      'transition',
      ],
      },
     }
    
    创建 Stylelint 过滤规则

    在项目根目录添加一个 .stylelintignore 文件,内容如下:

     # .stylelintignore
     # 旧的不需打包的样式库
     *.min.css
    
     # 其他类型文件
    *.js
    *.jpg
    *.woff
    
    # 测试和打包目录
    /test/
    /dist/*
    /public/*
    public/*
    /node_modules/
    
    启用 Vue 文件支持

    Stylelint v14 版本默认不支持 vue 文件中的 style 代码自动检测

    安装依赖

    stylelint-config-html - 解析 vue 文件
    postcss-html - 使用 stylelint-config-html 依赖的模块
    postcss-less - 对 less 文件进行解析

    npm i stylelint-config-html postcss-html postcss-less -D
    

    修改 Stylelint 配置文件
    修改 .stylelintrc.js 文件,添加如下配置:

    module.exports = {
      overrides: [
     {
      files: ['*.vue', '**/*.vue', '*.html', '**/*.html'],
      extends: ['stylelint-config-html'],
      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'],
       },
       ],
    };
    

    修改 Visual Studio Code 工作区配置
    Visual Studio Code 在 settings.json 设置文件中,增加以下代码:

     {
       "stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"]
     }
    
    集成 husky 和 lint-staged

    在项目中已集成 ESLint 和 Prettier,在编码时,这些工具可以对代码进行实时校验,在一定程度上能有效规范所写代码,但有些人可能觉得这些限制很麻烦,从而选择视“提示”而不见,依旧按自己编程风格来写代码,或者干脆禁用掉这些工具,开发完成就直接把代码提交到了仓库,日积月累,ESLint 也就形同虚设。

    所以,还需要做一些限制,让没通过 ESLint 检测和修复的代码禁止提交,从而保证仓库代码都是符合规范的。

    为了解决这个问题,需要用到 Git Hook,在本地执行 git commit 的时候,就对所提交的代码进行 ESLint 检测和修复(即执行 eslint --fix),如果这些代码没通过 ESLint 规则校验,则禁止提交。

    配置 husky

    注意:本项目使用 husky 6.x 版本,6.x 版本配置方式跟之前版本有较大差异,当发现配置方法不一致时,一切以 husky 官网为准。

    使用 husky-init 命令快速在项目初始化 husky 配置:

    # 初始化仓库
     git init
    
     # 初始化
     npx husky-init
    
    # 安装依赖
     npm install
    

    husky 包含很多 hook(钩子),常用有:pre-commit、commit-msg。

    使用 pre-commit 来触发 ESLint 命令,修改 .husky/pre-commit 文件触发命令:

    eslint --fix ./src --ext .vue,.js,.ts
    

    pre-commit hook 文件作用是:当执行 git commit -m "xxx" 时,会先对 src 目录下所有的 .vue、.js、.ts 文件执行 eslint --fix 命令,如果 ESLint 通过,成功 commit,否则终止 commit。

    但是又存在一个问题:有时候明明只改动了一两个文件,却要对所有的文件执行 eslint --fix。

    假如这是一个历史项目,在中途配置了 ESLint 规则,那么在提交代码时,也会对其他未修改的“历史”文件都进行检查,可能会造成大量文件出现 ESLint 错误,显然这不是我们想要的结果。

    所以只需要用 ESLint 修复此次写的代码,而不去影响其他的代码,此时需要借助 lint-staged 工具。

    配置 lint-staged

    lint-staged 一般结合 husky 来使用,它可以让 husky 的 hook 触发的命令只作用于 git 暂存区的文件,而不会影响到其他文件。

    安装依赖
     npm i lint-staged -D
    
    新增配置

    在 package.json 里增加 lint-staged 配置项:

     {
      "lint-staged": {
       "*.{js,jsx,ts,tsx}": [
        "prettier --write",
        "eslint --fix"
      ],
    "*.vue": [
      "prettier --write",
      "eslint --fix",
      "stylelint --fix"
    ],
    "*.{html,vue,vss,sass,less}": [
      "prettier --write",
      "stylelint --fix"
    ],
    "package.json": [
      "prettier --write"
    ],
    "*.md": [
      "prettier --write"
      ]
      },
     }
    
    修改触发命令

    修改 .husky/pre-commit 文件触发命令为:

    npx lint-staged
    

    经过以上配置之后,就可以在每次提交之前对所有代码进行格式化,保证线上代码的规范性。

    提交规范

    多人协作项目中,在提交代码环节,也存在一种情况:不能保证每个人对提交信息的准确描述,因此会出现提交信息紊乱、风格不一致的情况。

    如果 git commit 的描述信息精准,在后期维护和 Bug 处理时会变得有据可查,项目开发周期内还可以根据规范的提交信息快速生成开发日志,从而方便我们追踪项目和把控进度。

    Commit Message 格式规范

    commit message 由 Header、Body、Footer 组成。

     <Header>
    
     <Body>
    
     <Footer>
    
    Header

    Header 部分包括三个字段 type(必需)、scope(可选)和 subject(必需)。

     <type>(<scope>): <subject>
    
    type

    type 用于说明 commit 的提交类型(必须是以下几种之一)。

    scope

    scope 用于指定本次 commit 影响的范围。

    scope 依据项目而定,例如在业务项目中可以依据菜单或者功能模块划分,如果是组件库开发,则可以依据组件划分。

    subject

    subject 是本次 commit 的简洁描述,长度约定在 50 个字符以内,通常遵循以下几个规范:

    • 用动词开头,第一人称现在时表述,例如:change 代替 changed 或 changes
    • 第一个字母小写
    • 结尾不加句号(.)
    Body

    body 是对本次 commit 的详细描述,可以分成多行。

    跟 subject 类似,用动词开头,body 应该说明修改的原因和更改前后的行为对比。

    Footer

    如果本次提交的代码是突破性的变更或关闭缺陷,则 Footer 必需,否则可以省略。

    • 突破性的变更

    当前代码与上一个版本有突破性改变,则 Footer 以 BREAKING CHANGE 开头,后面是对变动的描述、以及变动的理由。

    • 关闭缺陷

    如果当前提交是针对特定的 issue,那么可以在 Footer 部分填写需要关闭的单个 issue 或一系列 issues。

    参考例子
    • feat

    feat(browser): onUrlChange event (popstate/hashchange/polling)

    Added new event to browser:

    • forward popstate event if available
    • forward hashchange event if popstate not available
    • do polling when neither popstate nor hashchange available

    Breaks $browser.onHashChange, which was removed (use onUrlChange instead)

    集成 cz-git 实现规范提交

    一款工程性更强,轻量级,高度自定义,标准输出格式的 commitizen 适配器
    官方网站:cz-git

    安装依赖
     npm install -D cz-git
    
    指定适配器

    修改 package.json 文件,添加 config 指定使用的适配器

     {
       "scripts": {},
       "config": {
        "commitizen": {
          "path": "node_modules/cz-git"
        }
       }
     }
    
    自定义配置(可选)

    cz-git 与 commitlint 进行联动给予校验信息,所以可以编写于 commitlint 配置文件之中。

    例如:(⇒ 配置模板)

     /** @type {import('cz-git').UserConfig} */
    module.exports = {
     extends: ['@commitlint/config-conventional'],
     rules: {},
     prompt: {
      useEmoji: false,
      emojiAlign: 'center',
      allowCustomIssuePrefixs: false,
      allowEmptyIssuePrefixs: false,
      },
    };
    
    全局使用

    全局安装的好处在于:在任何项目下都可以利用 cz 或 git cz 命令启动命令行工具,生成标准化 commit message

    安装全局依赖
    npm install -g cz-git commitizen
    
    全局配置适配器类型
    echo '{ "path": "cz-git" }' > ~/.czrc
    
    自定义配置(可选)

    方式一: 编辑 ~/.czrc 文件以 json 形式添加配置,例如:

    {
      "path": "cz-git",
      "useEmoji": true
    }
    

    方式二:与 commitlint 配合,在 $HOME 路径下创建配置文件 (↓ 配置模板)

    集成 commitlint 验证规范提交

    在“代码规范”章节中提到,尽管制定了规范,但在多人协作的项目中,总有些人依旧我行我素。

    因此提交代码这个环节,也增加一个限制:只让符合 Angular 规范的 commit message 通过。

    此功能需借助 @commitlint/config-conventional 和 @commitlint/cli 工具来实现。

    安装
    • @commitlint/cli - Commitlint 本体

    • @commitlint/config-conventional - 通用提交规范

      npm i @commitlint/cli @commitlint/config-conventional -D
      
    配置

    在项目根目录创建 commitlint.config.js 文件,并填入以下内容:

    module.exports = {
       extends: ['@commitlint/config-conventional']
     }
    

    使用 husky 命令在 .husky 目录下创建 commit-msg 文件,并在此执行验证命令:

     npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
    
    自动部署

    本章节将介绍如何使用 CI(Continuous Integration 持续集成)服务来完成项目部署工作。

    常见的 CI 工具有 GitHub Actions、GitLab CI、Travis CI、Circle CI 等。

    本项目使用 GitHub Actions 来完成这一操作。

    参考链接:GitHub Actions 入门教程
    创建 GitHub 仓库

    因为 GitHub Actions 只对 GitHub 仓库有效,所以创建 GitHub 仓库来托管项目代码。

    • master 分支存储项目源代码
    • gh-pages 分支存储打包后的静态文件
    创建 GitHub Token

    创建一个有 repo 和 workflow 权限的 GitHub Token

    注意:新生成的 Token 只会显示一次。

    添加 Actions secret

    将上述创建的 Token 添加到 GitHub 仓库中的 Secrets 里,并将这个新增的 secret 命名为 VITE_VUE_DEPLOY 。

    步骤:仓库 -> Settings -> Secrets -> Actions -> New repository secret。

    注意:新创建的 secret VITE_VUE_DEPLOY 在 Actions 配置文件中要用到,两个地方需保持一致!

    修改 package.json

    打开 package.json 文件,新增 homepage 字段,表示该应用发布后的根目录(参见官方文档)。

    "homepage": "https://[username].github.io/github-actions-demo",

    上面代码中,将 [username] 替换成你的 GitHub 用户名,参见范例。

    创建 Actions 配置文件

    (1)在项目根目录下创建 .github 目录。

    (2)在 .github 目录下创建 workflows 目录。

    (3)在 workflows 目录下创建 deploy.yml 文件。

    name: Vite Vue Deploy
    
    on:
    push:
    # master 分支有 push 时触发
    branches: [master]
    
     jobs:
     deploy:
    # 指定虚拟机环境
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [14.x, 16.x]
    
    steps:
      - name: Checkout
        # 拉取 GitHub 仓库代码
        uses: actions/checkout@v3
    
      - name: Use Node.js ${{ matrix.node-version }}
        # 设定 Node.js 环境
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
    
      - name: Install
        # 安装依赖
        run: npm install
    
      - name: Build
        # 打包
        run: npm run build
    
      - name: Deploy
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          # 部署打包目录
          folder: dist
          # 密钥名
          token: ${{ secrets.VITE_VUE_DEPLOY }}
          # 分支
          branch: gh-pages
    

    项目git仓库: https://github.com/ElanYoung/vite-vue-js-starter-template

    相关文章

      网友评论

        本文标题:从 0 搭建 Vite 3 + Vue 3 前端工程化项目

        本文链接:https://www.haomeiwen.com/subject/tegsjdtx.html