Vue3 + TypeScript + Pinia 搭建一套企業級的開發腳手架

從我最初接觸vue3版本到現在已經有一年的時間。由于 vue3.2 版本的發布,<script setup&amp;amp;gt; 的實驗性標志已經去掉,已經陸陸續續有不少公司開始使用 vue3.2開發項目了。這篇文章就來幫助大家如何快速使用 vue3.xtypeScriptvite 搭建一套企業級的開發腳手架 。廢話不多說,直接上手開搞。文章最后有項目地址!!!

搭建前準備

  1. Vscode: 前端人必備寫碼神器
  2. Chrome:對開發者非常友好的瀏覽器(反正我是很依賴它的)
  3. Nodejs&npm:配置本地開發環境,安裝 Node 后你會發現 npm 也會一起安裝下來
  4. Vue.js devtools:瀏覽器調試插件
  5. Vue Language Features (Volar):Vscode 開發 vue3 必備插件,提供語法高亮提示,非常好用
  6. Vue 3 Snippets:vue3 快捷輸入

Vue2 與 Vue3 的區別

Vue3由于完全由TS進行重寫,在應用中對類型判斷的定義和使用有很強的表現。同一對象的多個鍵返回值必須通過定義對應的接口(interface)來進行類型定義。要不然在 ESLint 時都會報錯。

vue2 的雙向數據綁定是利用 ES5 的一個 API Object.definePropert()對數據進行劫持 結合 發布訂閱模式的方式來實現的。Vue3 中使用了 es6ProxyAPI對數據代理。

Vue3支持碎片(Fragments)

Vue2Vue3 最大的區別: Vue2使用Options APIVue3 使用的Composition API

生命周期鉤子變化:

Vue2 ~~~~~~~~~~~ vue3
beforeCreate  -> setup()
created       -> setup()
beforeMount   -> onBeforeMount
mounted       -> onMounted
beforeUpdate  -> onBeforeUpdate
updated       -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed     -> onUnmounted
activated     -> onActivated
deactivated   -> onDeactivated

介紹 vite

Vite:下一代前端開發與構建工具

  • 極速的開發服務器啟動
  • ?? 輕量快速的熱模塊重載(HMR)
    ? - 豐富的功能
  • 自帶優化的構建
  • 通用的插件接口

Vite (法語意為 “迅速”,發音 /vit/)是一種全新的前端構建工具,它極大地改善了前端開發體驗。

它主要由兩部分組成

  • 一個開發服務器,它基于 原生 ES模塊 提供了 豐富的內建功能,如速度快到驚人的 模塊熱更新(HMR)。
    一套構建指令,它使用 Rollup打包你的代碼,并且它是預配置的,可以輸出用于生產環境的優化過的靜態資源。
  • Vite 意在提供開箱即用的配置,同時它的 插件 API 和 JavaScript API 帶來了高度的可擴展性,并有完整的類型支持。

使用 vite 快速創建腳手架

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

1. 第一步: 在需要創建項目文件目錄下打開 cmd 運行以下命令
# npm 6.x
npm init @vitejs/app vite_vue3_ts --template

# npm 7+, 需要額外的雙橫線:
npm init @vitejs/app vite_vue3_ts -- --template

# yarn
yarn create @vitejs/app vite_vue3_ts --template
  1. 這里我采用 yarn來安裝

    1638941494(1).png

  2. 選擇 vue回車 => vue-ts回車

1638941564(1).png
  1. 打開項目文件夾,安裝依賴,啟動項目
# 進入項目文件夾
cd 到你的項目文件夾
# 安裝依賴
yarn
# 啟動
yarn dev
1638941893(1).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

注意: 如果 eslint安裝報錯:

image.png

可以嘗試運行以下命令:

yarn config set ignore-engines true

運行成功后再次執行 eslint安裝命令

項目下新建 .eslintrc.js

配置 eslint 校驗規則:

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',
  },
}

項目下新建 .eslintignore

# eslint 忽略檢查 (根據項目需要自行添加)
node_modules
dist

prettier 支持

# 安裝 prettier
yarn add prettier --dev

解決 eslint 和 prettier 沖突

解決 ESLint中的樣式規范和 prettier中樣式規范的沖突,以 prettier的樣式規范為準,使 ESLint 中的樣式規范自動失效

# 安裝插件 eslint-config-prettier
yarn add eslint-config-prettier --dev

項目下新建 .prettier.js

配置 prettier格式化規則:

module.exports = {
  tabWidth: 2,
  jsxSingleQuote: true,
  jsxBracketSameLine: true,
  printWidth: 100,
  singleQuote: true,
  semi: false,
  overrides: [
    {
      files: '*.json',
      options: {
        printWidth: 200,
      },
    },
  ],
  arrowParens: 'always',
}

項目下新建 .prettierignore

# 忽略格式化文件 (根據項目需要自行添加)
node_modules
dist

package.json 配置:

{
  "script": {
    "lint": "eslint src --fix --ext .ts,.tsx,.vue,.js,.jsx",
    "prettier": "prettier --write ."
  }
}

上面配置完成后,可以運行以下命令測試下代碼檢查個格式化效果:

# eslint 檢查
yarn lint
# prettier 自動格式化
yarn prettier

配置 husky + lint-staged

使用husky+ lint-staged助力團隊編碼規范, husky&lint-staged 安裝推薦使用 mrm, 它將根據 package.json 依賴項中的代碼質量工具來安裝和配置 husky 和 lint-staged,因此請確保在此之前安裝并配置所有代碼質量工具,如 PrettierESlint

首先安裝 mrm

npm i mrm -D --registry=https://registry.npm.taobao.org

husky是一個為 git 客戶端增加 hook的工具。安裝后,它會自動在倉庫中的 .git/ 目錄下增加相應的鉤子;比如 pre-commit 鉤子就會在你執行 git commit 的觸發。

那么我們可以在 pre-commit 中實現一些比如 lint 檢查單元測試代碼美化等操作。當然,pre-commit階段執行的命令當然要保證其速度不要太慢,每次 commit 都等很久也不是什么好的體驗。

lint-staged,一個僅僅過濾出 Git 代碼暫存區文件(被 git add 的文件)的工具;這個很實用,因為我們如果對整個項目的代碼做一個檢查,可能耗時很長,如果是老項目,要對之前的代碼做一個代碼規范檢查并修改的話,這可能就麻煩了呀,可能導致項目改動很大。

所以這個lint-staged,對團隊項目和開源項目來說,是一個很好的工具,它是對個人要提交的代碼的一個規范和約束

安裝 lint-staged

mrm安裝 lint-staged 會自動把 husky一起安裝下來

npx mrm lint-staged

安裝成功后會發現 package.json 中多了一下幾個配置:

1638942775(1).png

因為我們要結合 prettier代碼格式化,所有修改一下配置:

"husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.{js,jsx,vue,ts,tsx}": [
      "yarn lint",
      "prettier --write",
      "git add"
    ]
  }

好了,到這里代碼格式化配置基本大功告成了!!!

配置文件引用別名 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'),
    },
  },
})

修改 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"]
}

配置 css 預處理器 scss

雖然 vite原生支持less/sass/scss/stylus,但是你必須手動安裝他們的預處理器依賴

安裝

yarn add dart-sass --dev
yarn add sass --dev

配置全局 scss 樣式文件

src/assets 下新增 style 文件夾,用于存放全局樣式文件

新建 main.scss, 設置一個用于測試的顏色變量 :

$test-color: red;

如何將這個全局樣式文件全局注入到項目中呢?配置 Vite即可:

css:{
    preprocessorOptions:{
      scss:{
        additionalData:'@import "@/assets/style/mian.scss";'
      }
    }
  },
組件中使用

不需要任何引入可以直接使用全局scss定義的變量

.test{
  color: $test-color;
}

路由

# 安裝路由
yarn add vue-router@4

src文件下新增 router文件夾 => router.ts 文件,內容如下:

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    name: 'Login',
    component: () => import('@/pages/login/Login.vue'), // 注意這里要帶上 文件后綴.vue
  },
]

const router = createRouter({
  history: createWebHistory(),
  routes,
})

export default router

修改入口文件 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')

到這里路由的基礎配置已經完成了,更多配置信息可以查看 vue-router 官方文檔:

vue-router: https://next.router.vuejs.org/zh/guide/
vue-router4.x 支持 typescript,配置路由的類型是 RouteRecordRaw,這里 meta可以讓我們有更多的發揮空間,這里提供一些參考:

  • title:string; 頁面標題,通常必選。
  • icon?:string; 圖標,一般配合菜單使用。
  • auth?:boolean; 是否需要登錄權限。
  • ignoreAuth?:boolean; 是否忽略權限。
  • roles?:RoleEnum[]; 可以訪問的角色
  • keepAlive?:boolean; 是否開啟頁面緩存
  • hideMenu?:boolean; 有些路由我們并不想在菜單中顯示,比如某些編輯頁面。
  • order?:number; 菜單排序。
  • frameUrl?:string; 嵌套外鏈。

這里只提供一些思路,每個項目涉及到的業務都會存在些差異,這里就不作詳細講解了,根據自己業務需求做配置即可。

統一請求封裝

使用過 vue2.x 的同學應該對 axios 很熟悉了,這里我們直接使用 axios 做封裝:

# 安裝 axios
yarn add axios
# 安裝 nprogress 用于請求 loading
# 也可以根據項目需求自定義其它 loading
yarn add nprogress
# 類型聲明,或者添加一個包含 `declare module 'nprogress'
yarn add @types/nprogress --dev

實際使用中可以根據項目修改,比如RESTful api中可以自行添加put和delete請求,ResType也可以根據后端的通用返回值動態的去修改

新增 service 文件夾,service 下新增 http.ts 文件以及 api 文件夾:


1638944111(1).png

http.ts : 用于axios封裝

//http.ts
import axios, { AxiosRequestConfig } from 'axios'
import NProgress from 'nprogress'

// 設置請求頭和請求路徑
axios.defaults.baseURL = '/api'
axios.defaults.timeout = 10000
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
axios.interceptors.request.use(
  (config): AxiosRequestConfig<any> => {
    const token = window.sessionStorage.getItem('token')
    if (token) {
      //@ts-ignore
      config.headers.token = token
    }
    return config
  },
  (error) => {
    return error
  }
)
// 響應攔截
axios.interceptors.response.use((res) => {
  if (res.data.code === 111) {
    sessionStorage.setItem('token', '')
    // token過期操作
  }
  return res
})

interface ResType<T> {
  code: number
  data?: T
  msg: string
  err?: string
}
interface Http {
  get<T>(url: string, params?: unknown): Promise<ResType<T>>
  post<T>(url: string, params?: unknown): Promise<ResType<T>>
  upload<T>(url: string, params: unknown): Promise<ResType<T>>
  download(url: string): void
}

const http: Http = {
  get(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start()
      axios
        .get(url, { params })
        .then((res) => {
          NProgress.done()
          resolve(res.data)
        })
        .catch((err) => {
          NProgress.done()
          reject(err.data)
        })
    })
  },
  post(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start()
      axios
        .post(url, JSON.stringify(params))
        .then((res) => {
          NProgress.done()
          resolve(res.data)
        })
        .catch((err) => {
          NProgress.done()
          reject(err.data)
        })
    })
  },
  upload(url, file) {
    return new Promise((resolve, reject) => {
      NProgress.start()
      axios
        .post(url, file, {
          headers: { 'Content-Type': 'multipart/form-data' },
        })
        .then((res) => {
          NProgress.done()
          resolve(res.data)
        })
        .catch((err) => {
          NProgress.done()
          reject(err.data)
        })
    })
  },
  download(url) {
    const iframe = document.createElement('iframe')
    iframe.style.display = 'none'
    iframe.src = url
    iframe.onload = function () {
      document.body.removeChild(iframe)
    }
    document.body.appendChild(iframe)
  },
}
export default http

api: 項目中接口做統一管理,按照模塊來劃分

api文件下新增 login文件夾,用于存放登錄模塊的請求接口,login 文件夾下分別新增login.ts types.ts :

login.ts:

import http from '@/service/http'
import * as T from './types'

const loginApi: T.ILoginApi = {
    login(params){
        return http.post('/login', params)
    }

}
export default loginApi

types.ts:

export interface ILoginParams {
    userName: string
    passWord: string | number
}
export interface ILoginApi {
    login: (params: ILoginParams)=> Promise<any>
}

至此,一個簡單地請求封裝完成了!!!!

除了自己手動封裝 axios ,這里還推薦一個 vue3 的請求庫: VueRequest,非常好用,下面來看看 VueRequest有哪些比較好用的功能吧!!!

  • 所有數據都具有響應式
  • 輪詢請求
  • 自動處理錯誤重試
  • 內置請求緩存
  • 節流請求與防抖請求
  • 聚焦頁面時自動重新請求
  • ?? 強大的分頁擴展以及加載更多擴展
  • 完全使用 Typescript 編寫,具有強大的類型提示
  • ?? 兼容 Vite
  • 輕量化
  • 開箱即用

是不是很強大

官網鏈接: https://www.attojs.com/

狀態管理 pinia

由于 vuex 4 對 typescript 的支持讓人感到難過,所以狀態管理棄用了 vuex 而采取了 pinia. pinia 的作者是 Vue 核心團隊成員
尤大好像說 pinia可能會代替 vuex,所以請放心使用。

  • id是必要的,它將所使用 store 連接到 devtools。
  • 創建方式:new Vuex.Store(...)(vuex3)createStore(...)(vuex4)
  • 對比于 vuex3 ,state 現在是一個函數返回對象
  • 沒有mutations,不用擔心,state 的變化依然記錄在 devtools 中。
# 安裝
yarn add pinia@next

main.ts 中增加

# 引入
import { createPinia } from "pinia"
# 創建根存儲庫并將其傳遞給應用程序
app.use(createPinia())

src 文件夾下新增 store 文件夾,接在在 store 中新增 main.ts

創建 store, mian.ts :

import { defineStore } from 'pinia'

export const useMainStore = defineStore({
  id: 'mian',
  state: () =>({
    name: '超級管理員'
  })
})

組建中獲取 store :

<template>
  <div>{{mainStore.name}}</div>
</template>

<script setup lang="ts">
import { useMainStore } from "@/store/mian"

const mainStore = useMainStore()

</script>

getters 用法介紹

Pinia 中的 getter 與 Vuex 中的 getter 、組件中的計算屬性具有相同的功能
store=> mian.ts

import { defineStore } from 'pinia'

export const useMainStore = defineStore({
  id: 'mian',
  state: () => ({
    name: '超級管理員',
  }),
  // getters
  getters: {
    nameLength: (state) => state.name.length,
  }
})

組件中使用:

<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>

actions

這里與 Vuex有極大的不同,Pinia 僅提供了一種方法來定義如何更改狀態的規則,放棄 mutations 只依靠 Actions,這是一項重大的改變。

PiniaActions 更加的靈活:

  • 可以通過組件或其他 action調用
  • 可以從其他 storeaction 中調用
  • 直接在 store 實例上調用
  • 支持同步或異步
  • 有任意數量的參數
  • 可以包含有關如何更改狀態的邏輯(也就是 vuex 的 mutations 的作用)
  • 可以 $patch方法直接更改狀態屬性
import { defineStore } from 'pinia'

export const useMainStore = defineStore({
  id: 'mian',
  state: () => ({
    name: '超級管理員',
  }),
  getters: {
    nameLength: (state) => state.name.length,
  },
  actions: {
    async insertPost(data:string){
      // 可以做異步
      // await doAjaxRequest(data);
      this.name = data;
    }
  },
})

環境變量配置

vite提供了兩種模式:具有開發服務器的開發模式(development)和生產模式(production)

項目根目錄新建:.env.development :

NODE_ENV=development

VITE_APP_WEB_URL= 'YOUR WEB URL'

項目根目錄新建:.env.production :

NODE_ENV=production

VITE_APP_WEB_URL= 'YOUR WEB URL'

組件中使用:
console.log(import.meta.env.VITE_APP_WEB_URL)

配置package.json:

打包區分開發環境和生產環境

"build:dev": "vite build --mode development",
"build:pro": "vite build --mode production",

使用組件庫 Naive UI(也可以根據自己的技術棧選擇)

組件庫選擇,這里我們選擇 Naive UI 至于為什么選擇它?我可以直接說尤大大推薦的嗎?

# 安裝 組件庫
yarn add naive-ui
# 安裝 字體
yarn add vfonts

如何使用

import { NButton } from "naive-ui"
<n-button>naive-ui</n-button>

全局配置 Config Provider

全局化配置設置內部組件的主題、語言和組件卸載于其他位置的 DOM 的類名。

<n-config-provider :locale="zhCN" :theme="theme">
    <!-- 容器 -->
</n-config-provider>

Vite 常用基礎配置

基礎配置

運行 代理打包 配置

server: {
    host: '0.0.0.0',
    port: 3000,
    open: true,
    https: false,
    proxy: {}
},

生產環境去除 console debugger

build:{
  ...
  terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
  }
}

生產環境生成 .gz 文件

開啟 gzip可以極大的壓縮靜態資源,對頁面加載的速度起到了顯著的作用。

使用vite-plugin-compression可以 gzipbrotli 的方式來壓縮資源,這一步需要服務器端的配合,vite 只能幫你打包出.gz 文件。此插件使用簡單,你甚至無需配置參數,引入即可。

# 安裝
yarn add --dev vite-plugin-compression

plugins 中添加:

import viteCompression from 'vite-plugin-compression'

// gzip壓縮 生產環境生成 .gz 文件
viteCompression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: 'gzip',
      ext: '.gz',
    }),

最終 vite.config.ts

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
//@ts-ignore
import viteCompression from 'vite-plugin-compression'

// https://vitejs.dev/config/
export default defineConfig({
  base: './', //打包路徑
  plugins: [
    vue(),
    // gzip壓縮 生產環境生成 .gz 文件
    viteCompression({
      verbose: true,
      disable: false,
      threshold: 10240,
      algorithm: 'gzip',
      ext: '.gz',
    }),
  ],
  // 配置別名
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
  },
  css:{
    preprocessorOptions:{
      scss:{
        additionalData:'@import "@/assets/style/mian.scss";'
      }
    }
  },
  //啟動服務配置
  server: {
    host: '0.0.0.0',
    port: 8000,
    open: true,
    https: false,
    proxy: {}
  },
  // 生產環境打包配置
  //去除 console debugger
  build: {
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
      },
    },
  },
})

常用插件

可以查看官方文檔:https://vitejs.cn/plugins/

至此一個完整的項目框架已經初步成型,可以愉快的開始業務開發了!

非常推薦使用的 hooks 庫:VueUsehttps://vueuse.org/

感興趣的可以了解一下

碼云地址: https://gitee.com/fengzhongzhuifeng/type-script-vue3-vite.git

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評論 6 546
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,814評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,779評論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,109評論 1 330
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,287評論 0 291
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,799評論 1 338
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,515評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,750評論 1 375
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,933評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,492評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,703評論 2 380

推薦閱讀更多精彩內容