日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
一篇學(xué)會(huì)如何使用Vite重構(gòu)Vue3項(xiàng)目

前言

截止發(fā)文時(shí)間,vite正式版已經(jīng)發(fā)布快2年時(shí)間了,vue3也發(fā)布到3.2版本了,它的周邊設(shè)施基本上已經(jīng)齊活了。也是時(shí)候再次重構(gòu)下我那個(gè)vue3.0的開源項(xiàng)目了。

為青縣等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及青縣網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、青縣網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

本篇文章就記錄下我的重構(gòu)過(guò)程,歡迎各位感興趣的開發(fā)者閱讀本文。

環(huán)境搭建

1年多前,我用Vue Cli 4.5構(gòu)建的此項(xiàng)目,有關(guān)此項(xiàng)目的更多細(xì)節(jié)請(qǐng)移步我的另一篇文章使用Vue3重構(gòu)Vue2項(xiàng)目。同樣的,從CLI遷移到Vite仍然是在package.json中添加vite的依賴項(xiàng),在項(xiàng)目中添加它的配置文件。

此次項(xiàng)目構(gòu)建還加入了volta的相關(guān)配置,對(duì)此感興趣的開發(fā)者請(qǐng)移步:強(qiáng)大的JavaScript工具管理器Volta

新增vite相關(guān)依賴項(xiàng)

我們打開package.json,找到devDependencies字段,移除CLI相關(guān)的依賴,添加vite相關(guān)的依賴,如下所示:

  • +綠色標(biāo)識(shí)代表新增
  • -紅色標(biāo)識(shí)代表移除
{
"dependencies": {
- "compression-webpack-plugin": "^5.0.1",
},
"devDependencies": {
+ "@vitejs/plugin-vue": "^3.0.0",
+ "vite": "^3.0.0",
+ "vue-tsc": "^0.38.4",
+ "@types/node": "^18.6.3",
- "sass-loader": "^8.0.2",
- "@vue/cli-plugin-babel": "~4.5.0",
- "@vue/cli-plugin-eslint": "~4.5.0",
- "@vue/cli-plugin-router": "~4.5.0",
- "@vue/cli-plugin-typescript": "~4.5.0",
- "@vue/cli-plugin-vuex": "~4.5.0",
- "@vue/cli-service": "~4.5.0",
- "@vue/compiler-sfc": "^3.0.0-0"
-
}
}

隨后,我們找到scripts字段,修改項(xiàng)目的運(yùn)行與構(gòu)建命令。

{
"scripts": {
"serve": "vite --open",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
}
}

vite3.x版本要求node版本必須大于14.18.0,因此我們需要在engines字段中做一下提示,如下所示:

{
"engines": {
"npm": "please-use-yarn",
"yarn": ">= 1.0.0",
"node": ">= 14.18.0"
}
}

除了上述配置外,我們還需要在項(xiàng)目的根目錄創(chuàng)建.npmrc文件,寫入下述內(nèi)容:

engine-strict = true

配置完成后,我們執(zhí)行在終端執(zhí)行yarn install安裝依賴即可。

在上述配置中,我們還強(qiáng)制設(shè)置了yarn作為項(xiàng)目的包管理工具,如果項(xiàng)目開發(fā)成員使用了npm install則不會(huì)開始安裝依賴并提示其使用yarn來(lái)安裝依賴。

添加vite配置文件

在vite中,index.html已經(jīng)從public文件夾遷移到項(xiàng)目的根目錄下了,官方文檔對(duì)此的解釋為:在開發(fā)期間 Vite 是一個(gè)服務(wù)器,而 index.html 是該 Vite 項(xiàng)目的入口文件。

有關(guān)此變更的詳細(xì)解釋請(qǐng)移步:index.html 與項(xiàng)目根目錄

接下來(lái),我們?cè)陧?xiàng)目的根目錄創(chuàng)建index.html文件(將public目錄下的文件刪除)

  • 引入靜態(tài)文件時(shí)不需要使用%PUBLIC_URL%?作為占位符,可以直接寫/來(lái)訪問(wèn),vite會(huì)將其解析到public根目錄下
  • 通過(guò)

    注意:如果你的項(xiàng)目比較復(fù)雜,有多個(gè)入口,那么就將index.html文件放到對(duì)應(yīng)入口的根目錄下。

    最后,我們創(chuàng)建vite.config.ts文件,配置代碼如下所示:

    • 設(shè)置開發(fā)環(huán)境的端口號(hào)
    • 設(shè)置路徑別名
    • 設(shè)置打包后base地址以及打包輸出目錄
    import { defineConfig } from "vite";
    import { resolve } from "path";
    import vue from "@vitejs/plugin-vue";
    const IS_PRODUCTION = process.env.NODE_ENV === "production";

    export default defineConfig({
    plugins: [vue()],
    server: {
    host: true,
    port: 8020,
    proxy: {}
    },
    resolve: {
    // 設(shè)置路徑別名
    alias: {
    "@": resolve(__dirname, "./src"),
    "*": resolve("")
    }
    },
    base: IS_PRODUCTION ? "/chat-system" : "./",
    define: {
    "process.env": {}
    },
    build: {
    outDir: resolve(__dirname, "dist")
    }
    });

    注意:我的項(xiàng)目配置比較簡(jiǎn)單,它只有一個(gè)入口,打包后只會(huì)部署到生產(chǎn)環(huán)境。如果你的項(xiàng)目較為復(fù)雜,也不必太過(guò)擔(dān)心,你的應(yīng)用場(chǎng)景vite也是支持的,按照文檔進(jìn)行相關(guān)的配置就好,如下所示:

    • 自定義構(gòu)建
    • 多頁(yè)面應(yīng)用模式
    • 環(huán)境變量和模式

    當(dāng)你的項(xiàng)目有多個(gè)入口時(shí),期望通過(guò)不同命令來(lái)啟動(dòng)不同項(xiàng)目時(shí),你可以使用yarn的--cwd指令來(lái)指定其運(yùn)行時(shí)的工作目錄。

    例如:你有兩個(gè)入口,那么就在src目錄下創(chuàng)建兩個(gè)文件夾:**A、B **。A和B中分別有自己的index.html、main.ts以及package.json文件(配置start、build命令,傳入不同的參數(shù)來(lái)啟動(dòng)/構(gòu)建不同入口的項(xiàng)目)

    根目錄的package.json中你就可以配置啟動(dòng)/構(gòu)建命令為:

    {
    "scripts": {
    "dev:A": "yarn --cwd ./src/A run start",
    "dev:B": "yarn --cwd ./src/B run start",
    "build:A": "yarn --cwd ./src/A run build",
    "build:B": "yarn --cwd ./src/B run build",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview"
    },
    }

    最后,我們以A入口為例,列舉下package.json文件中的配置:

    {
    "name": "A",
    "version": "1.0.0",
    "main": "index.js",
    "license": "MIT",
    "scripts": {
    "start": "vite serve --config ../../vite.config-A.ts --mode development",
    "build": "vue-tsc --noEmit && vite build --config ../../vite.config-A.ts --mode production"
    }
    }

    升級(jí)Vue周邊依賴項(xiàng)

    vue3.2的單文件組件引入了setup規(guī)范,它可以讓代碼變得更簡(jiǎn)潔,可以使用純 TypeScript 聲明 props 和拋出事件,有著更好的運(yùn)行時(shí)性能。這些優(yōu)點(diǎn)讓我有了升級(jí)vue版本的動(dòng)力,之前的3.0版本寫起來(lái)很臃腫,需要return一大堆東西,甚是麻煩。

    打開package.json文件作出下述變動(dòng):

    • 更新了vue、router、vuex的版本號(hào)
    • 新增了vueuse包,這是一個(gè)基于 Composition API 的實(shí)用函數(shù)集合,封裝了一些常用的功能(實(shí)時(shí)獲取鼠標(biāo)位置、防抖、節(jié)流、獲取客戶端系統(tǒng)主題等),可以避免一些重復(fù)性的工作內(nèi)容,大大提升開發(fā)效率。
    {
    "dependencies": {
    - "vue": "^3.0.0-0",
    - "vue-class-component": "^8.0.0-0"
    - "vue-router": "^4.0.0-0",
    - "vuex": "^4.0.0-0",
    + "vue": "^3.2.37",
    + "vue-router": "^4.1.3",
    + "vuex": "^4.0.2",
    + "@vueuse/components": "^8.9.2",
    + "@vueuse/core": "^8.9.2"
    }
    }

    最后執(zhí)行yarn install即可完成整個(gè)環(huán)境的搭建,本章節(jié)重構(gòu)完成后的完整文件請(qǐng)移步:

    • .npmrc
    • index.html
    • package.json
    • vite.config.ts

    經(jīng)驗(yàn)分享

    本章節(jié)就跟大家分享下,我切到新環(huán)境后做的一些優(yōu)化點(diǎn)以及遇到的問(wèn)題和解決方案。

    本章節(jié)修改到的文件,完整文件代碼如下:

    • package.json
    • tsconfig.json

    require不存在

    一切準(zhǔn)備就緒后,按下了項(xiàng)目啟動(dòng)按鈕,很快啊,651ms項(xiàng)目就啟動(dòng)了,不愧是vite速度就是快,嘴角瘋狂上揚(yáng)。

    瀏覽器加載完項(xiàng)目后,我傻眼了,我的登陸界面呢?順勢(shì)打開控制臺(tái),發(fā)現(xiàn)報(bào)錯(cuò)require is not defined。

    解決方案

    打開Login.vue文件后,發(fā)現(xiàn)我用require導(dǎo)入了一些圖片文件,在VueCLI環(huán)境下的require會(huì)交給webpack處理。在vite中是不存在的,那么我們就需要查看vite是怎么處理靜態(tài)文件了。

    翻了下文檔后,在靜態(tài)資源處理章節(jié)發(fā)現(xiàn)他有兩種處理方法:

    • 通過(guò)import語(yǔ)句直接導(dǎo)入圖片
    • 通過(guò)new URL來(lái)導(dǎo)入圖片

    我打算將所有組件都重構(gòu)為setup形式,因此直接使用import方式來(lái)導(dǎo)入圖片可以保持組件的一致性,可以大大提升可讀性。

    我們寫個(gè)簡(jiǎn)單的demo來(lái)嘗試下,如下所示:





    已經(jīng)可以正確解析出圖片的路徑了。

    注意:本文不會(huì)過(guò)多講解setup的語(yǔ)法,對(duì)此不了解的開發(fā)者請(qǐng)移步:?jiǎn)挝募M件 - script setup

    new URL方式可以用來(lái)引入一個(gè)動(dòng)態(tài)資源,例如:你有一份json配置文件,里面描述了圖片的文件名,這些圖片是放在項(xiàng)目中的,他們的訪問(wèn)前綴都一樣,此時(shí)你就可以通過(guò)遍歷json文件通過(guò)此方式來(lái)引入這些圖片。

    vue相關(guān)模塊不存在

    我試圖從vue的包中導(dǎo)入shallowRef時(shí),編輯器報(bào)錯(cuò): TS2305: Module 'xxx' has no exported member 'shallowRef'. 。

    解決方案

    經(jīng)過(guò)一番排查后,是因?yàn)轫?xiàng)目typescript版本是3.x,跟3.2版本的vue不兼容,需要將其升級(jí)至4.x版本。

    打開package.json文件,作出如下所示的修改,重新執(zhí)行yarn install命令即可。

    {
    "devDependencies": {
    - "typescript": "~3.9.3",
    + "typescript": "~4.7.4",
    }
    }

    setup中的變量警告未被使用

    當(dāng)我在setup中聲明了一個(gè)函數(shù)或者導(dǎo)入了一個(gè)文件,在template中已經(jīng)使用了,但是他卻報(bào)錯(cuò)ESLint: 'xx' is assigned a value but never used.(@typescript-eslint/no-unused-vars)

    解決方案

    在 eslint-plugin-vue 插件的Issues中看到有人遇到了跟我同樣的問(wèn)題,在v9.0.0: regression in unused variables in script setup中我找到了解決方案。

    我們需要升級(jí)下@vue/eslint-config-typescript和eslint-plugin-vue的版本號(hào),如下所示:

    {
    "devDependencies": {
    "@vue/eslint-config-typescript": "^11.0.0",
    "eslint-plugin-vue": "^9.0.0"
    }
    }

    隨后在eslint的配置文件中,添加parser屬性,重新執(zhí)行yarn install命令即可。

    module.exports = {
    + parser: 'vue-eslint-parser'
    }

    模塊隔離

    Vite 使用 esbuild 來(lái)轉(zhuǎn)譯 TypeScript,并受限于單文件轉(zhuǎn)譯的限制,因此需要在ts的配置文件中將isolatedModules屬性設(shè)置為true。

    {
    "compilerOptions": {
    "isolatedModules": true
    }
    }

    process不存在

    在路由配置文件中,我們需要從process中獲取BASE_URL,此時(shí)編輯器報(bào)錯(cuò): TS2591: Cannot find name 'process'. Do you need to install type definitions for node? Try npm i --save-dev @types/node and then add 'node' to the types field in your tsconfig.

    解決方案

    由于vite中已經(jīng)沒(méi)有process了,需要用import.meta來(lái)代替,那么上述的路由配置文件就應(yīng)該改為:

    const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL), // 地址欄不帶#
    routes
    });

    無(wú)法導(dǎo)入json文件

    在表情面板模塊,我將每個(gè)表情都放入了json文件中。在vite中引入文件需要使用import,改了寫法后,發(fā)現(xiàn)它報(bào)錯(cuò):Cannot find module 'xx.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.

    解決方案

    我們需要在ts的配置文件中添加resolveJsonModule屬性,如下所示:

    {
    "compilerOptions": {
    + "resolveJsonModule": true
    }
    }

    使用vite提供的對(duì)象

    當(dāng)我想使用vite所提供的glob屬性時(shí),發(fā)現(xiàn)編輯器報(bào)錯(cuò): TS2339: Property 'glob' does not exist on type 'ImportMeta'.

    解決方案也很簡(jiǎn)單,我們只需要在ts的配置文件中添加vite/client即可,如下所示:

    {
    "compilerOptions": {
    "types": [
    + "vite/client"
    ]
    }
    }

    獲取全局屬性

    當(dāng)我們使用一些第三方庫(kù)的時(shí)候它會(huì)在globalProperties掛載一些方法,當(dāng)在ts+setup環(huán)境下使用時(shí),會(huì)出現(xiàn)類型無(wú)法推導(dǎo)問(wèn)題,如下所示:

    第三方庫(kù)提供了一個(gè)$connect方法

    我們通過(guò)proxy來(lái)訪問(wèn)

    他會(huì)出現(xiàn)報(bào)錯(cuò): TS2339: Property 'xx' does not exist on type 'ComponentPublicInstance{}, {}, {}, {}, {}, {}, {}, {}, false, ComponentOptionsBase >'.

    解決方案

    我們可以在type目錄下新建一個(gè)global文件夾,在這里存放一些我們擴(kuò)展出來(lái)的全局方法。

    如下所示,我們:

    • 創(chuàng)建了一個(gè)useCurrentInstance方法
    • 將globalProperties屬性暴露出去
    import { ComponentInternalInstance, getCurrentInstance } from "vue";
    export default function useCurrentInstance() {
    const { appContext } = getCurrentInstance() as ComponentInternalInstance;
    const proxy = appContext.config.globalProperties;
    return {
    proxy
    };
    }

    我們?cè)诮M件中使用暴露出來(lái)的proxy即可,如下所示:

    無(wú)法識(shí)別NodeJS類型

    我們?cè)诮osetinterval和setTimeout指定類型時(shí),會(huì)用到NodeJS模塊,會(huì)出現(xiàn)報(bào)錯(cuò):ESLint: 'NodeJS' is not defined.(no-undef)。

    這個(gè)問(wèn)題的解決方案是:打開eslint的配置文件在globals對(duì)象中添加NodeJS選項(xiàng),如下所示:

    {
    globals: {
    NodeJS: true
    }
    }

    除了將類型聲明為NodeJS.Timeout外,我們還可以將其聲明為number類型,但是需要攜帶window前綴(window.setinterval/window.setTimeout)

    管理靜態(tài)資源

    當(dāng)我們?cè)诮M件中使用import導(dǎo)入很多靜態(tài)資源時(shí),組件看起來(lái)會(huì)很雜亂。此時(shí)我們可以將其按照功能類型進(jìn)行拆分。我的做法如下:

    • 在src下創(chuàng)建resource文件夾
    • 根據(jù)功能類型創(chuàng)建ts文件,將其導(dǎo)出
    import defaultAvatar from "@/assets/img/login/LoginWindow_BigDefaultHeadImage@2x.png";
    import defaultLoginBtnIcon from "@/assets/img/login/icon-enter-undo@2x.png";
    import loginUndo from "@/assets/img/login/icon-enter-undo@2x.png";
    import loginBtnHover from "@/assets/img/login/icon-enter-hover@2x.png";
    import loginBtnDown from "@/assets/img/login/icon-enter-down@2x.png";

    export {
    defaultAvatar,
    defaultLoginBtnIcon,
    loginUndo,
    loginBtnHover,
    loginBtnDown
    };

    分離模版與邏輯代碼

    我的項(xiàng)目中有一個(gè)很復(fù)雜的組件,有上千行代碼,去年我用CompositionAPI優(yōu)化了一版,將組件中所有的方法都拆分成了一個(gè)個(gè)獨(dú)立的ts文件,做到了邏輯代碼與模版代碼分離,模版需要什么方法我就通過(guò)import導(dǎo)入進(jìn)來(lái),最后return給模版。

    在拆分出來(lái)的文件中,是沒(méi)有辦法訪問(wèn)vue提供的一些內(nèi)置屬性的,比如:defineProps、defineEmits、getCurrentInstance。因此我想了一個(gè)奇妙的方法:將這些無(wú)法訪問(wèn)的屬性都存起來(lái)。具體的做法請(qǐng)移步我另一篇文章:使用Vue3的CompositionAPI來(lái)優(yōu)化代碼量-創(chuàng)建InitData.ts文件

    適配方案

    vue3.2的setup語(yǔ)法糖支持import進(jìn)來(lái)的方法都能在模版中直接使用,那我們的組件又可以精簡(jiǎn)下了,我花了億點(diǎn)點(diǎn)時(shí)間對(duì)其進(jìn)行了適配。

    之前我們想獲取組件的emit需要從context中拿,props聲明并從setup函數(shù)的參數(shù)中獲取,如下所示:

    現(xiàn)在我們就不用這么麻煩了,直接通過(guò)defineProps、defineEmits獲取即可,如下所示:

    此組件重構(gòu)后的完整代碼請(qǐng)移步:

    • message-display.vue
    • EventMonitoring.ts

    項(xiàng)目地址

    至此,項(xiàng)目的重構(gòu)工作就結(jié)束了。本文重構(gòu)好的項(xiàng)目代碼地址:


    當(dāng)前題目:一篇學(xué)會(huì)如何使用Vite重構(gòu)Vue3項(xiàng)目
    文章轉(zhuǎn)載:http://www.5511xx.com/article/dpedecp.html