近期手邊有一個簡易用 vue-cli 建立的舊 Vue 2 項目,想說將其升級為 Vue 3 + Vite ,並改用 pnpm 且加上 TypeScript。這邊筆記下分段進行的心得,以及後續可以採用的事項。
內容
主要套件
升級前
- Vue 2
- vue-cli
- eslint
- prettier
- vuex
- vue-router 3
- bootstrap-vue
- node-sass
升級後
- Vue 3
- vite
- eslint
- prettier
- pinia ( vuex 的繼任者 )
- vue-router 4
- TypeScript
- unocss
第一階段 – 升級 Vue 2.7 & Vite
步驟
1. 移除下列項目: @vue/cli-plugin-babel, @vue/cli-plugin-eslint, @vue/cli-plugin-router, @vue/cli-plugin-vuex, @vue/cli-service, babel-eslint, sass-loader, vue-template-compiler, bootstrap-vue 因為 sass-loader 是 webpack 編譯時所需要的,vite 是不需要安裝的。 bootstrap-vue 當前僅支援到 Vue 2.6,所以改安裝原生 Bootstrap 5 + @popperjs/core 即可
2. 將 eslintConfig 的設定移出,在根目錄新增一個檔案 .eslintrc.cjs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
module.exports = { root: true, env: { browser: true, es2022: true, node: true, }, parser: 'vue-eslint-parser', extends: [ 'eslint-config-prettier', 'eslint:recommended', 'plugin:vue/essential', '@vue/eslint-config-prettier', 'prettier', ], rules: { 'eslint-disable-next-line': 'off', 'no-console': process.env.NODE_ENV === 'production' ? 2 : 0, 'vue/multi-word-component-names': 'off', }, } |
3. 新增以下項目: vue, Bootstrap, @popperjs/core, @vitejs/plugin-vue2, @vue/eslint-config-prettier, sass, vue-template-compiler 其中 vue-template-compiler 和 vue 的版本必須要對齊,否則會報錯
4. 將原先的 scripts 指令改成如下: 由於改用 pnpm,所以 lint 的規則統一先用 eslint 過完再執行 prettier
1 2 3 4 5 6 7 8 |
{ "dev": "vite", "build": "vite build", "serve": "vite preview", "lint": "pnpm eslint && pnpm prettier", "prettier": "prettier --write .", "eslint": "eslint \"./**/*.{ts,js,d.ts,vue}\" --fix" } |
5. 在根目錄新增 .prettierrc.cjs 和 .prettierignore
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 |
// .prettierrc.cjs module.exports = { semi: false, tabWidth: 2, printWidth: 100, singleQuote: true, trailingComma: 'all', jsxSingleQuote: false, bracketSpacing: true, } // .prettierignore .local .output.js /dist/* /public/* /build/* **/*.svg **/*.sh README.md /node_modules/** pnpm-lock.yaml |
6. 將 index.html 搬出 public 資料夾,改放到根目錄下。如果內容有保留 webpack 的填入值,就將其修改掉
7. 移除 vue.config.js,改新增 vite.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import path from 'path' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue2' export default defineConfig({ base: process.env.NODE_ENV === 'production' ? '/CV-Resume/' : '/', plugins: [vue()], server: { port: 8080, }, resolve: { alias: { '@': path.resolve('./src'), }, extensions: ['.js', '.ts', '.vue'], }, }) |
8. 在根目錄用指令 rm -rf node_modules package-lock.json pnpm-lock.yaml 給移除掉,再用 pnpm install 重新安裝一次
9. 由於 vite 不支援 require 動態載入的寫法,就算是圖片,都要用 import image from ‘圖片位置’ 的寫法改寫
10. 執行 pnpm dev ,這樣就算初步升級完成了
第二階段 – 升級 Vue 3
步驟
1. 移除下列項目: @vitejs/plugin-vue2 , vue, vue-router, vuex, browserslist vite 是無法使用 browserslist 設定的
2. 安裝以下項目: @vitejs/plugin-vue, vue, vue-router, pinia
3.改寫 main.js 的內容,重點如下:
1 2 3 4 5 6 |
import { createApp } from 'vue' import router from '@/router' import { createPinia } from 'pinia' const app = createApp(App) app.use(createPinia()).use(router).mount('#app') |
4. 改寫原先的 vuex 內容 getters 改直接取用 state 的狀態、mutations 可直接併入到 actions
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 |
// Vuex before import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { windowWidth: 0, windowHeight: 0, }, getters: { windowWidth: (state) => state.windowWidth, windowHeight: (state) => state.windowHeight, }, mutations: { setWindowWidth(state, value) { state.windowWidth = value }, setWindowHeight(state, value) { state.windowHeight = value }, }, actions: {}, modules: {}, }) // in *.vue import { mapGetters } from 'vuex' ...mapGetters(['windowWidth', 'windowHeight']) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Pinia after import { defineStore } from 'pinia' export default defineStore({ id: 'app', state: () => ({ windowWidth: 0, windowHeight: 0, }), actions: { setWindowWidth(value) { this.windowWidth = value }, setWindowHeight(value) { this.windowHeight = value }, }, }) // in *.vue import { mapState } from 'pinia' import appStore from '@/store' ...mapState(appStore, ['windowWidth', 'windowHeight']) |
5. Vue Router 改用 v4 的寫法,變化不大。可參考官網指南修改
6. *.vue 檔案若有用到 destroyed() 要改成 unmounted()
7. .eslint 的 extends 要調整為 ‘plugin:prettier/recommended’