• Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架


    Vue2 与 Vue3 的区别

    • Vue3由于完全由TS进行重写,在应用中对类型判断的定义和使用有很强的表现。同一对象的多个键返回值必须通过定义对应的接口(interface)来进行类型定义。要不然在 ESLint 时都会报错。
    • Vue2 与 Vue3 最大的区别: Vue2 使用Options API而 Vue3 使用的Composition API
    介绍 vite
    • 💡 极速的开发服务器启动
    • ⚡️ 轻量快速的热模块重载(HMR)
    • 🛠️ 丰富的功能
    • 📦 自带优化的构建
    • 🔩 通用的插件接口
    • 🔑 完全类型化的 API
    • Vite (法语意为 “迅速”,发音 /vit/)是一种全新的前端构建工具,它极大地改善了前端开发体验。
    使用 vite 快速创建脚手架

    兼容性注意:Vite 需要 Node.js 版本 >= 12.0.0。

    1. 第一步: 在需要创建项目文件目录下打开 cmd 运行以下命令
      # npm 6.x
      npm init vite@latest my-vue-app --template vue
    
      # npm 7+, 需要额外的双横线:
      npm init vite@latest my-vue-app -- --template vue
    
      # yarn
      yarn create vite my-vue-app --template vue
    
      # pnpm
      pnpm create vite my-vue-app -- --template vue
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 这里采用npm方法安装
      2.png

    2. 这里选择vue-ts 然后回车
      3.png

    3. 等项目创建完之后,就可以看到结果了cd到文件夹,安装依赖,启动项目
      4.png
      5.png

    代码风格统一

    Eslint支持
    # eslint 安装
          yarn add eslint --dev
          # eslint 插件安装
          yarn add eslint-plugin-vue --dev
    
          yarn add @typescript-eslint/eslint-plugin --dev
    
          yarn add eslint-plugin-prettier --dev
    
          # typescript parser
          yarn add @typescript-eslint/parser --dev
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 项目下新建 .eslintrc.js
    module.exports = {
      root: true,
      env: {
        browser: true,
        node: true,
        es2021: true,
      },
      parser: "vue-eslint-parser",
      extends: [
        "eslint:recommended",
        "plugin:vue/vue3-recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:prettier/recommended",
        // eslint-config-prettier 的缩写
        "prettier",
      ],
      parserOptions: {
        ecmaVersion: 12,
        parser: "@typescript-eslint/parser",
        sourceType: "module",
        ecmaFeatures: {
          jsx: true,
        },
      },
      // eslint-plugin-vue @typescript-eslint/eslint-plugin eslint-plugin-prettier的缩写
      plugins: ["vue", "@typescript-eslint", "prettier"],
      rules: {
        "@typescript-eslint/ban-ts-ignore": "off",
        "@typescript-eslint/no-unused-vars": "off",
        "@typescript-eslint/explicit-function-return-type": "off",
        "@typescript-eslint/no-explicit-any": "off",
        "@typescript-eslint/no-var-requires": "off",
        "@typescript-eslint/no-empty-function": "off",
        "@typescript-eslint/no-use-before-define": "off",
        "@typescript-eslint/ban-ts-comment": "off",
        "@typescript-eslint/ban-types": "off",
        "@typescript-eslint/no-non-null-assertion": "off",
        "@typescript-eslint/explicit-module-boundary-types": "off",
        "no-var": "error",
        "prettier/prettier": "error",
        // 禁止出现console
        "no-console": "warn",
        // 禁用debugger
        "no-debugger": "warn",
        // 禁止出现重复的 case 标签
        "no-duplicate-case": "warn",
        // 禁止出现空语句块
        "no-empty": "warn",
        // 禁止不必要的括号
        "no-extra-parens": "off",
        // 禁止对 function 声明重新赋值
        "no-func-assign": "warn",
        // 禁止在 return、throw、continue 和 break 语句之后出现不可达代码
        "no-unreachable": "warn",
        // 强制所有控制语句使用一致的括号风格
        curly: "warn",
        // 要求 switch 语句中有 default 分支
        "default-case": "warn",
        // 强制尽可能地使用点号
        "dot-notation": "warn",
        // 要求使用 === 和 !==
        eqeqeq: "warn",
        // 禁止 if 语句中 return 语句之后有 else 块
        "no-else-return": "warn",
        // 禁止出现空函数
        "no-empty-function": "warn",
        // 禁用不必要的嵌套块
        "no-lone-blocks": "warn",
        // 禁止使用多个空格
        "no-multi-spaces": "warn",
        // 禁止多次声明同一变量
        "no-redeclare": "warn",
        // 禁止在 return 语句中使用赋值语句
        "no-return-assign": "warn",
        // 禁用不必要的 return await
        "no-return-await": "warn",
        // 禁止自我赋值
        "no-self-assign": "warn",
        // 禁止自身比较
        "no-self-compare": "warn",
        // 禁止不必要的 catch 子句
        "no-useless-catch": "warn",
        // 禁止多余的 return 语句
        "no-useless-return": "warn",
        // 禁止变量声明与外层作用域的变量同名
        "no-shadow": "off",
        // 允许delete变量
        "no-delete-var": "off",
        // 强制数组方括号中使用一致的空格
        "array-bracket-spacing": "warn",
        // 强制在代码块中使用一致的大括号风格
        "brace-style": "warn",
        // 强制使用骆驼拼写法命名约定
        camelcase: "warn",
        // 强制使用一致的缩进
        indent: "off",
        // 强制在 JSX 属性中一致地使用双引号或单引号
        // 'jsx-quotes': 'warn',
        // 强制可嵌套的块的最大深度4
        "max-depth": "warn",
        // 强制最大行数 300
        // "max-lines": ["warn", { "max": 1200 }],
        // 强制函数最大代码行数 50
        // 'max-lines-per-function': ['warn', { max: 70 }],
        // 强制函数块最多允许的的语句数量20
        "max-statements": ["warn", 100],
        // 强制回调函数最大嵌套深度
        "max-nested-callbacks": ["warn", 3],
        // 强制函数定义中最多允许的参数数量
        "max-params": ["warn", 3],
        // 强制每一行中所允许的最大语句数量
        "max-statements-per-line": ["warn", { max: 1 }],
        // 要求方法链中每个调用都有一个换行符
        "newline-per-chained-call": ["warn", { ignoreChainWithDepth: 3 }],
        // 禁止 if 作为唯一的语句出现在 else 语句中
        "no-lonely-if": "warn",
        // 禁止空格和 tab 的混合缩进
        "no-mixed-spaces-and-tabs": "warn",
        // 禁止出现多行空行
        "no-multiple-empty-lines": "warn",
        // 禁止出现;
        semi: ["warn", "never"],
        // 强制在块之前使用一致的空格
        "space-before-blocks": "warn",
        // 强制在 function的左括号之前使用一致的空格
        // 'space-before-function-paren': ['warn', 'never'],
        // 强制在圆括号内使用一致的空格
        "space-in-parens": "warn",
        // 要求操作符周围有空格
        "space-infix-ops": "warn",
        // 强制在一元操作符前后使用一致的空格
        "space-unary-ops": "warn",
        // 强制在注释中 // 或 /* 使用一致的空格
        // "spaced-comment": "warn",
        // 强制在 switch 的冒号左右有空格
        "switch-colon-spacing": "warn",
        // 强制箭头函数的箭头前后使用一致的空格
        "arrow-spacing": "warn",
        "no-var": "warn",
        "prefer-const": "warn",
        "prefer-rest-params": "warn",
        "no-useless-escape": "warn",
        "no-irregular-whitespace": "warn",
        "no-prototype-builtins": "warn",
        "no-fallthrough": "warn",
        "no-extra-boolean-cast": "warn",
        "no-case-declarations": "warn",
        "no-async-promise-executor": "warn",
      },
      globals: {
        defineProps: "readonly",
        defineEmits: "readonly",
        defineExpose: "readonly",
        withDefaults: "readonly",
      },
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    1. 项目下新建 .eslintignore

        # eslint 忽略检查 (根据项目需要自行添加)
        node_modules
        dist
      
      • 1
      • 2
      • 3
    prettier 支持
    # 安装 prettier
    yarn add prettier --dev
    
    • 1
    • 2
    • 解决 eslint 和 prettier 冲突
    # 安装插件 eslint-config-prettier
          yarn add eslint-config-prettier --dev
    
    • 1
    • 2
    • 项目下新建 .prettier.js
     module.exports = {
            tabWidth: 2,
            jsxSingleQuote: true,
            jsxBracketSameLine: true,
            printWidth: 100,
            singleQuote: true,
            semi: false,
            overrides: [
              {
                files: '*.json',
                options: {
                  printWidth: 200,
                },
              },
            ],
            arrowParens: 'always',
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 项目下新建 .prettierignore
    # 忽略格式化文件 (根据项目需要自行添加)
          node_modules
          dist
    
    • 1
    • 2
    • 3
    4 package.json 配置:
    
    ```js
      {
        "script": {
          "lint": "eslint src --fix --ext .ts,.tsx,.vue,.js,.jsx",
          "prettier": "prettier --write ."
        }
      }
    ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    配置 husky + lint-staged
    1. 使用husky + lint-staged助力团队编码规范,
      1. 安装插件
    npm install husky -dev
          npm install lint-staged -dev
    
    • 1
    • 2
    • husky 是一个为 git 客户端增加 hook 的工具。安装后,它会自动在仓库中的 .git/ 目录下增加相应的钩子;比如 pre-commit 钩子就会在你执行 git commit 的触发。
    • 那么我们可以在 pre-commit 中实现一些比如 lint 检查、单元测试、代码美化等操作
    • lint-staged,一个仅仅过滤出 Git 代码暂存区文件(被 git add 的文件)的工具;这个很实用,因为我们如果对整个项目的代码做一个检查,可能耗时很长,如果是老项目,要对之前的代码做一个代码规范检查并修改的话,这可能就麻烦了呀,可能导致项目改动很大。
      "husky": {
              "hooks": {
                "pre-commit": "lint-staged"
              }
            },
            "lint-staged": {
              "*.{js,jsx,vue,ts,tsx}": [
                "yarn lint",
                "prettier --write",
                "git add"
              ]
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    配置文件引用别名 alias

    • 直接修改 vite.config.ts 文件配置:
     import { defineConfig } from 'vite'
          import vue from '@vitejs/plugin-vue'
          import path from 'path'
    
          // https://vitejs.dev/config/
          export default defineConfig({
            plugins: [vue()],
            resolve: {
              alias: {
                '@': path.resolve(__dirname, 'src'),
              },
            },
          })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 修改 tsconfig.json
    {
              "compilerOptions": {
                "target": "esnext",
                "module": "esnext",
                "moduleResolution": "node",
                "strict": true,
                "jsx": "preserve",
                "sourceMap": true,
                "resolveJsonModule": true,
                "esModuleInterop": true,
                "lib": ["esnext", "dom"],
                "baseUrl": ".",
                "paths": {
                  "@/*":["src/*"]
                }
              },
              "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    配置 css 预处理器 scss

    • 插件安装

        yarn add sass-loader --dev
        yarn add dart-sass --dev
        yarn add sass --dev
      
      • 1
      • 2
      • 3
    • 配置全局scss样式

      • 在 src/assets 下新增 style 文件夹,用于存放全局样式文件
      • 新建 main.scss, 设置一个用于测试的颜色变量 :
        $test-color: rgb(0, 4, 255);
      
      • 1
    • 全局配置

        css:{
          preprocessorOptions:{
            scss:{
              additionalData:'@import "@/assets/style/mian.scss";'
            }
          }
        },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 组件中使用

    ```css
      
    ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2345截图20220801203646.png

    路由安装使用

    • 安装路由插件

        yarn add vue-router@4
      
      • 1
    • 在 src 文件下新增 router 文件夹 => router.ts 文件,内容如下:

     import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
            const routes: RouteRecordRaw[] = [
              {
                path: '/',
                name: 'home',
                component: () => import('@/views/Home/index.vue'), // 注意这里要带上 文件后缀.vue
              },
            ];
    
            const router = createRouter({
              history: createWebHistory(),
              routes,
            });
    
            export default router;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 修改入口文件 mian.ts :
     import { createApp } from 'vue'
            import App from './App.vue'
            import router from './router/index'
    
            const app = createApp(App)
    
            app.use(router)
    
            app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 路由文档使用说明
        vue-router: https://next.router.vuejs.org/zh/guide/
      
      • 1

    状态管理 pinia

    • 由于 vuex 4 对 typescript 的支持让人感到难过,所以状态管理弃用了 vuex 而采取了 pinia. pinia 的作者是 Vue 核心团队成员

    • 安装 pinia

        yarn add pinia@next
      
      • 1
    • main.ts 中增加

        import { createPinia } from "pinia"
        # 创建根存储库并将其传递给应用程序
        app.use(createPinia())
      
      • 1
      • 2
      • 3
    • 在 src 文件夹下新增 store 文件夹,接在在 store 中新增 main.ts

        import { defineStore } from 'pinia'
        export const useMainStore = defineStore({
          id: 'mian',
          state: () =>({
            name: '群主'
          })
        })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • 组建中获取 store :

    <template>
              <div>{{mainStore.name}}</div>
            </template>
    
            <script setup lang="ts">
            import { useMainStore } from "@/store/mian"
    
            const mainStore = useMainStore()
    
            </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • getters 用法介绍
      • Pinia 中的 getter 与 Vuex 中的 getter 、组件中的计算属性具有相同的功能
     import { defineStore } from 'pinia'
            export const useMainStore = defineStore({
              id: 'mian',
              state: () => ({
                name: '群主',
              }),
              getters: {
                nameLength: (state) => state.name.length,
              }
          })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 组件中使用
    <template>
              <div>用户名:{{ mainStore.name }}<br />长度:{{ mainStore.nameLength }}</div>
              <hr/>
              <button @click="updateName">修改store中的name</button>
            </template>
    
            <script setup lang="ts">
            import { useMainStore } from '@/store/mian'
    
            const mainStore = useMainStore()
    
            const updateName = ()=>{
              // $patch 修改 store 中的数据
              mainStore.$patch({
                name: '名称被修改了,nameLength也随之改变了'
              })
            }
            </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    环境变量配置
    • vite 提供了两种模式:具有开发服务器的开发模式(development)和生产模式(production)
      1. 项目根目录新建:.env.development :

        NODE_ENV=development
        VITE_APP_WEB_URL= 'https://www.baidu.com'
      
      • 1
      • 2
    • 项目根目录新建:.env.production :

        NODE_ENV=production
        VITE_APP_WEB_URL= 'https://www.baidu.com'
      
      • 1
      • 2
    • 使用方式

      mport.meta.env.VITE_APP_WEB_URL

    • 打包区分开发环境和生产环境

        "build:dev": "vue-tsc --noEmit && vite build --mode development",
        "build:pro": "vue-tsc --noEmit && vite build --mode production",
      
      • 1
      • 2

      6.png

    • 通过以上的流程,我们就可以搭建一个企业级专业的脚手架模板

  • 相关阅读:
    Android开发第二课
    每天一个设计模式之过滤器模式(Filter/Criteria Pattern)
    设计模式(五)设计原则part2
    10个Reduce函数的使用小技巧
    docker bash: vi: command not found 修改文件无法使用 vi yum的方法
    加速释放传统企业业务潜力,S2B2B商城建设方案引领电商模式新风向
    java数据结构与算法刷题-----LeetCode26:删除有序数组中的重复项
    [2022 杭电多校5] Count Set (生成函数 分治NTT)
    C++知识点2:把数据写进switch case结构,和写进json结构,在使用上有什么区别
    Typescript笔记:Number对象
  • 原文地址:https://blog.csdn.net/Govern66/article/details/127931287