這是一份保姆級Vue3+Vite實戰教程

語言: CN / TW / HK

寫在前面

很長時間沒有更新文章了,由於這次簽約專欄不能和之前的專欄重複,外加最近又有很多小夥伴問我 Vue3 在實戰中的注意事項和技巧,我想了想,決定寫一個 Vue3 實戰專欄,我理解的項目實戰,就是大家在看到這篇文章的時候,我剛創建好項目,然後目前碼字的我就是在一邊寫項目一邊寫文章。

在剛剛開始接觸前端的時候就一直想寫一個工具大全的網站,一直沒閒下來寫,正好湊着這個機會搞一下,那這個過程中可以隨時會遇到一些問題,我們就以項目開發中最平常的角度去解決這些問題,一個項目從想法到落地,從產生問題再到解決問題,這一切會有太多的不可預知,也正貼合我們實際工作中開發項目。

那我們來介紹下要做的這個項目。

日常工作生活中,總會用到一些小工具,每次想要使用一些工具時,標準流程是百度、谷歌搜索 免費XXX網站 ,然後在搜索列表中一個一個的點擊查看是否免費,遇到好用的可能會收藏一下網站,但是下次再使用此類工具的時候,大傢什麼樣子我不知道,但是我自己通常不會去收藏夾找這個工具網站,而是接着百度、谷歌開啟循環,隨之而來的就是收藏的工具網站越來越多,五花八門。

那都已經做這麼久程序員了,為什麼不自己開發一個工具類的聚合網站呢?需求自己決定,想用啥寫啥,於是,這個我自己都不知道要未來都會寫些什麼的工具聚合網站就成了這個專欄的實戰項目。

那我們會做一些什麼工具呢?

如上所説,我自己都不知道這個項目要未來都會寫些什麼工具,當然我們還是有些目標的,因為有很多常用工具,像圖片處理中壓縮、格式轉換、合成、裁切、水印、隱式水印?像文件處理中格式轉換、預覽、編輯?像顏色處理中格式轉換、對比色、互補色、中差色、臨近色生成?像編碼轉換、加密解密、正則可視化、在線 Markdown?甚至你看完這篇文章在評論區留言我想要一個 XXX 工具,然後我看到了,可能就將是下一篇要寫的。你也可以自己寫工具 PR 到項目,採用的話我也會參考實現去出文章教程。

那我們可以在這個項目中學到什麼呢?

首先,很多同學還沒用過 Vue3 以及 Vite,這部分同學可以學習一下 Vue3 生態在實戰中一些使用。

其次,已經在使用 Vue3 的同學,也可以學習一下 Vue3 生態在實戰中的一些技巧。

當然,之後我們寫各種各樣的工具,一定會觸及到很多知識點,你以為寫個顏色工具只會講代碼怎麼實現?不,預想中應該是要把 RGBHEXRGBAHSLHSLAHSVHSB對比色互補色中差色臨近色等等等等這些色彩相關理論説一下的,直接捲到設計崗,從此和 UI 小姐姐們説話挺直腰板,告別程序員審美。你以為寫個正則可視化只是簡單寫個工具?不,預想中寫工具只是幌子,應該是一片大家其樂融融一塊學正則的畫面,邊學邊用可 Copy 的正則可視化工具才是我們的目標。

既然是工具網站為了方便使用我們肯定是要寫瀏覽器插件的,後續也能學到一個基礎的瀏覽器插件開發的過程。

最後,希望我不會太監(斷更),那這麼隨意的項目做下去很大可能是一塊見證代碼屎山的形成,但這重要嗎?不重要,重要的是能從中汲取經驗、思路和開發技巧。

此文主要介紹項目初始化的一些準備工作,那你以為這篇文章只是簡單搭建一個項目?沒錯,它確實是,但也會涉及到方方面面,鑑於實戰類的文章新同學可能很多,所以我儘可能的寫的詳細。

所以,你被唬住了嗎?據不知名人士(正是在下)透露,點個贊再看有助於全文完整閲讀。

創建項目

創建一個 Vue3+Vite 項目

首先我們要創建一個 Vue3+Vite 項目,目前 Vue 官方創建項目時默認就是 Vite 構建了,所以直接按照官網來就可以,如下:

確保你安裝了最新版本的 Node.js,然後在命令行中運行以下命令

```bash npm init vue@latest

or

pnpm create vue@latest ```

PS: 我這邊使用的是 pnpm ,它的優缺點我就不説了,大家自行百度吧,不過後面所有的命令中我都會寫 npmpnpm 兩種,大家想用啥都無所謂的,工具而已,但是 pnpm 真的很香。

這一指令將會安裝並執行 create-vue,它是 Vue 官方的項目腳手架工具。你將會看到一些諸如 TypeScript 和測試支持之類的可選功能提示,我們的選擇如下:

```bash ✔ Project name(項目名): toolsdog ✔ Add TypeScript(添加TS)? : No ✔ Add JSX Support(添加JSX支持)? : No ✔ Add Vue Router for Single Page Application development(添加Vue-router)? : Yes ✔ Add Pinia for state management(添加狀態管理Pinia)? : Yes ✔ Add Vitest for Unit testing(為單元測試添加Vitest)? : No ✔ Add Cypress for both Unit and End-to-End testing(為單元測試與端到端測試添加Cypress)? : No ✔ Add ESLint for code quality(為代碼質量添加ESLint)? : Yes ✔ Add Prettier for code formatting(為代碼格式添加Prettier)? : Yes

Scaffolding project in ./tooldog... Done. ```

OK,解釋一下

沒有使用 TS 只是單純的不太喜歡 TS,雖然有很多優點,但是個人認為它是一種束縛,大家想用的話選個 Yes 也可以,我們這裏選了 No

JSX 如果要使用的話,不如直接使用 React,所以我們選了 No

做項目 VueRouter 必選,不解釋。

狀態管理也是必選,目前官方都不推薦 Vuex 而是 Pinia 了,後續大家用起來也是逃不過真香定律的。

Unit(單元測試)和 E2E(端到端測試),做組件庫之類的是需要搞的,但一般對做項目來説,會很少留給我們寫 UnitE2E 的時間,所以我們先不選了,後續有時間寫再單獨安裝(沒有這個可能 🤥)。

最後的 ESLintPrettier,一個保證質量,一個保證風格,必選,我們都選擇 Yes 就好了。

這裏都很基礎,沒有什麼特殊要説的,不過我留意到很多新手前端甚至很多有些經驗的前端都搞不懂 ESLintPrettier 的區別,所以這裏我們單獨提一下。

2022年了,搞清楚 ESLint 和 Prettier 吧

先看 ESLint,它是一個 Lint 工具,Lint 工具專注於檢測並修復錯誤。

ESLint 不僅能夠檢測代碼中的錯誤,而且在許多情況下,可以為我們自動糾正錯誤。我們可以通過安裝 ESlint 的相關插件,在各種 IDE 編譯器下進行應用,通過實時檢測代碼格式問題或者是語法問題,可以使得程序員在編碼時犯更少的錯誤,當然也可以通過命令行或者插件去自動修復問題。説白了,ESLint 這種 Lint 工具它是一個基本的靜態代碼分析器,使用 Lint 工具不會使我們的代碼免受任何業務邏輯缺陷的影響,反而它會確保我們的代碼在語法上準確並遵循一些最佳實踐。

再來看 Prettier,它就是一個代碼格式化工具,代碼格式化工具並不會校驗代碼中的語法錯誤,而是在代碼易讀性上面下功夫。

Prettier 翻譯過來是漂亮,其實意思就很明顯了,就是讓你的代碼更漂亮,核心就是格式化代碼,確保我們的代碼遵守一些一致的格式化規則,比如像製表符寬度、單雙引號、尾隨逗號、行尾分號等等。這樣的格式化規則可以確保我們的代碼即使由不同的開發人員開發,或者是在不同的編輯器中也能保持一致,以此來保證整個項目中代碼風格的一致性。

所以,為了滿足程序的標準化,減少由於手動排版代碼帶來的時間消費,我們通常會將 ESLint 和 Prettier 一起應用,同時處理代碼語法錯誤和代碼風格格式化。它們兩個的核心是並不衝突的,可能有人會問,我配置的 ESLint 和 Prettier 怎麼經常衝突?

舉個例子,我們在 ESLint 配置了一個代碼規則,禁止代碼尾部使用分號,但是如果我們項目中還用了 Prettier 做代碼格式化,並且 Prettier 中配置了代碼末尾自動加分號的規則,那就涼了,只要你在代碼末尾使用了分號,ESLint 檢測到就會給你警告(具體是報錯還是警告基於你的 Lint 配置),那一般 ESLint 會默認自動給我們修復這個簡單警告去掉代碼後面分號,但是這個時候 Prettier 在格式化代碼的時候檢測到沒有分號就會再給我們加上分號。。。

所以,即使有衝突,衝突的也是我們自己的配置,而不是ESLint 、 Prettier 本身有衝突,這點我們在配置的時候注意一下就好了。

如果看到這裏還有人覺得這兩個東西功能重複,用一個就好了。。。那你可能需要再看一次上文內容並且好好思考下這兩個東西的核心是什麼,他們只是在配置規則上少量重複,有一點點交集罷了。

畢竟 Prettier 不能為你檢測因為摸魚而產生的代碼上的一些小問題,ESLint 也不能讓你整個團隊的代碼風格保持一致,不是嗎?

把項目跑起來

跑一下項目

上面我們初始化好了項目,那接下來先來啟起來項目:

```bash

移動到項目根目錄

cd toolsdog

安裝依賴

npm install

啟動項目

npm run dev

or

cd toolsdog pnpm install pnpm dev ```

如果你的項目跑起來了,打開瀏覽器,應該就可以看到下面界面:

當然,還有一些同學是啟不起來的,估計很多的報錯是這個:

js Error: Cannot find module 'node:url'

這是因為我們創建的項目下載的包裏用了 node 較高版本的語法,比如

js // vite.config.js 中引入 node url 模塊時使用了 'node:url' // 詳見:https://nodejs.org/dist/latest-v16.x/docs/api/url.html#url import { fileURLToPath, URL } from 'node:url'

Vue 官方文檔上明確説了開始項目之前,請確保安裝了最新版本的 NodeJS,我們的 node 版本要在 v16+ ,所以出現這種問題你的電腦 node 版本可能有些老了,趕快 node -v 查看一下自己電腦的 node 版本吧!

PS: 對於經驗不多的同學,可能認為換個版本太麻煩,所以,下面還是簡單介紹下切換 node 版本包括切換 npm 鏡像源,這是很基礎的常識,新同學要敲黑板了。

nvm管理&切換Node版本

切換不同版本的 node 對前端來説是很常見的事情(比如那個可惡的 node-sass,就不支持 node16+ 。。。),如果每次都刪除重裝,那也太麻煩了,我們可以直接使用 nvm 工具去管理多個版本的 node,想使用哪個版本,安裝好直接切換使用即可。

Windows 同學安裝 nvm

使用 win 的同學需注意,安裝 nvm 之前需要先卸載掉 node,所以安裝前可以先查看下當前本機 node 版本,下載好 nvm 後再通過 nvm 安裝上這個版本 node,防止突然換了其他版本 node 後對當前電腦上的項目造成一些影響。

使用 win 的同學安裝起來可以很簡單,打開 nvm-windows,找到最新版本。

如上圖

bash nvm-noinstall.zip # 綠色免安裝版,使用時需進行配置 nvm-setup.zip # 全自動安裝版,推薦使用

新手同學建議直接下載一鍵自動安裝版就行,想挑戰一下自己,也可以下載綠色免安裝版本,不過需要自己配置一些環境變量(希望不會有這種大聰明,有簡單的方式就用簡單的嘛)。

下載下來 nvm-setup.zip 解壓後,直接雙擊一路 next 安裝即可,需要注意安裝時選擇安裝地址,只要你選的安裝地址目錄沒有中文和空格,一般不會出現問題的。

安裝好後,打開 cmd 輸入 nvm 回車顯示 nvm 幫助命令提示即安裝成功!

Mac 同學安裝 nvm

Mac 同學如果裝了 brew,那直接使用它安裝即可

bash brew install nvm

如果沒有 brew,使用官方 sh 腳本安裝也可以,查看官方最新版腳本

bash curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash

當然,無論你用那種安裝,安裝好了之後都得去配置環境變量。

寫環境變量前我們需要創建一下 .nvm 文件

bash mkdir ~/.nvm

可能我們安裝 nvm 時自動創建了 .nvm 文件,但有些不會自動創建,mkdir 一下更安全,如果已經存在了,就會報該文件已存在,無傷大雅。

然後是寫入環境變量。

brew 安裝方式需要寫入的環境變量:

bash export NVM_DIR="$HOME/.nvm" [ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh" # This loads nvm [ -s "/usr/local/opt/nvm/etc/bash_completion.d/nvm" ] && . "/usr/local/opt/nvm/etc/bash_completion.d/nvm" # This loads nvm bash_completion

腳本安裝方式需要寫入的環境變量:

bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

我們需要把上述對應的環境變量配置寫入配置文件中,mac 的配置文件有 2 個,分別是 .bash_profile & .zshrc ,那它們有什麼區別呢?

.bash_profile.zshrc 文件均在 根目錄下。

當我們修改 .bash_profile 配置文件,運行 source ~/.bash_profile 重新加載配置文件後,此配置文件只在當前窗口生效,電腦一重啟就無了。

而我們修改 .zshrc 配置文件 ,運行 source ~/.zshrc 重新加載配置文件後,這個配置是永久生效的,因為我們的電腦每次重啟時都會自動去執行一次 source ~/.zshrc 命令。

一般 mac 用户都會在 ~/.zshrc 文件末尾添加一句 source ~/.bash_profile 命令,這其實就是為了確保 .bash_profile 中的修改也可以隨着.zshrc 配置文件的運行而永久生效。

所以,你如果也在 ~/.zshrc 文件末尾寫了執行 ~/.bash_profile 的命令,那你在寫環境變量時,寫到任意一個配置文件裏都可以,否則的話就老老實實在 ~/.zshrc 文件寫入環境變量吧!!!

我們直接在終端通過 vim 去編輯配置文件

bash vim ~/.zshrc

不同的安裝方式去 copy 上面對應的環境變量配置,寫入到配置文件就行了。

寫入成功後,按 esc 鍵,然後輸入 :wq 保存並退出 vim 修改,此為 vim 命令,不懂的同學自行 Google

最後重新加載配置文件

bash source ~/.zshrc

注意需要重啟終端哦,重啟後終端輸入 nvm 回車顯示 nvm 幫助命令提示即安裝成功!

nvm 常用命令

```bash nvm ls-remote # 查看node所有版本 nvm install node # 安裝最新node可用版本 nvm version/nvm current # 查看當前nvm使用node版本 nvm list available # 查看可安裝node版本 nvm list/nvm ls # 查看已安裝版本 nvm install # 安裝指定node版本 nvm uninstall # 卸載指定node版本 nvm use # 切換使用指定版本node nvm use [version] [arch] # 切換指定node版本和位數 nvm reinstall-packages # 在當前版本node環境下,重新全局安裝指定版本號的npm包

nvm on # 打開nodejs控制 nvm off # 關閉nodejs控制 nvm alias # 給不同的版本號添加別名 nvm unalias # 刪除已定義別名 nvm proxy # 查看設置與代理 nvm node_mirror [url] # 設置setting.txt中的node_mirror,如果不設置的默認是 https://nodejs.org/dist/ nvm npm_mirror [url] # 設置setting.txt中的npm_mirror,如果不設置的話默認的是: https://github.com/npm/npm/archive/. nvm root [path] # 設置和查看root路徑 ```

如上, nvm 安裝完成後我們查看下 node 版本,然後安裝上想要使用的 node 版本就可以了,那針對我們這次 Vue3+Vite 項目,需要使用到 node16+ 版本,那麼我們可以直接選擇安裝 16+ 大版本中最新最穩定的小版本,即 v16.17.0 (Latest LTS: Gallium)

之前還有同學問我 LatestLTSGallium 這些都是啥意思,這。。。好吧,給新同學們解釋下。。

軟件工程中,我們對一個項目的整個生命週期是沒有一套常規定義的,所以不同的項目用的標識是有區別的,到如今,大致項目用的其實也差不多了,比較常用的幾個我簡單列了,如下:

bash Dev # 開發版,頻繁出新功能,另外還修復了一些Bug和不穩定因素 Alpha # 軟件或系統的內部測試版本,會有不少Bug,僅內部人員使用瀏覽器 Beta # 軟件或系統的測試版本,這一版本一般是在Alpha版本後,會有不少新功能,同時也有很多Bug Gamma # 軟件或系統接近於成熟的版本,只須要作一些小的改進就能發行測試 RC # 發行候選版本,和Beta版最大的差別在於Beta階段會一直加入新的功能,但是到了RC版本,幾乎不會加入新功能,主要在於除錯。RC版本是最終發放給用户的最接近正式版的版本,發行後改正bug就是正式版,正式版之前的最後一個測試版。 Release # 正式發佈版本,最終交付用户使用的一個版本,該版本也稱為標準版,也可用符號 ® 表示 GA # 也代表正式發佈版本,這個版本也是正式版本,國外大多都是用GA來説明Release版本 Stable # 穩定版,在開源軟件中,都有stable版,就是開源軟件的最終發行版,此版本一般基於Beta版,已知Bug都被修復,一般情況下更新較慢 LTS # 長期支持版,這一版本會持續進行支持,最早用在 Ubuntu

所以,LTS 就是長期支持版,在 node 中它代表此版本會長期進行支持,很穩定,放心使用的意思。當然,這麼多標識是沒有必要死記硬背的,記住個大概就行,有看到不懂就萬能 Coogle 嘛。

Latest 就是字面理解的最新版本的意思。

最後的 Gallium 其實就是 node 發版對應的一個代號,這個就比較隨意了,就是個情懷,比如大家耳熟能詳的 Vue ,扒一扒發版記錄,它的每次發版都有代號:

bash Vue3.0 # One Piece:海賊王 Vue2.7 # Naruto:火影忍者 Vue2.6 # Macross:超時空要塞 Vue2.5 # Level E:靈異E接觸 Vue2.4 # Kill la Kill:斬服少女 Vue2.3 # JoJo's Bizarre Adventure:JoJo的奇妙冒險 Vue2.2 # Initial D:頭文字D Vue2.1 # Hunter X Hunter:全職獵人 Vue2.0 # Ghost in the Shell:攻殼機動隊 Vue1.0 # Evangelion:新世紀福音戰士 Vue0.12 # Dragon Ball:龍珠 Vue0.11 # Cowboy Bebop:星際牛仔 Vue0.10 # Blade Runner:銀翼殺手 Vue0.9 # Animatrix:黑客帝國動畫版

所以,你瞭解了嗎?如果你運行項目報了上述錯誤,那麼在安裝並使用上高版本 node 之後,重啟編輯器再次運行項目,應該就可以看到啟動成功了!

nrm管理&切換鏡像源

除了管理 node 版本外,npm 鏡像源的管理在開發中也是比較常用的,那假如你沒有翻出牆的話,可能安裝某些依賴會很慢甚至失敗,你可以嘗試切換一下 npm 鏡像源,或者你的公司有 npm 私服,你也可以設置一個公司私服的源地址,使用 nrm 能夠很好的管理和切換這些源

全局安裝

bash npm install -g nrm

當你安裝完成後,可以使用 nrm ls 命令查看當前可用的源

如上,這是我電腦 nrm 管理的鏡像源列表,最後一個是我公司內網的所以打碼了,除了最後一個都是安裝 nrm 自帶的,你可以使用 nrm use <registry> 命令很方便的去切換源,npm 默認就是列表中名為 npm 的源,如果你下載不下來一些工具,可以切換為 taobao 源,當然安裝完成後最好切回來,因為除了 npm 源,其他源在下載某些包時,都可能會出現一些莫名的問題。

常用命令

```bash nrm -h /nrm -help # 查看 nrm 幫助(相關命令、信息) nrm -V # 查看當前 nrm 版本 nrm ls # 查看當前 nrm 中可用的鏡像源地址 nrm current # 查看當前使用鏡像源

nrm use # 切換為某個鏡像源 registry-鏡像源名 nrm add # 添加一個鏡像源 registry-鏡像源名 url-鏡像源地址 nrm del # 刪除一個鏡像源 nrm test # 測試該鏡像源下載響應時間 ```

PS: 當然還有像 yrm 等其他管理源的工具,但工具不在多,而是夠用就行。

讓項目更健壯

瞭解項目中每一個文件的作用

到此我們已經初步創建並啟動了項目,其實很多人只關注代碼開發相關的文件,並不會去糾結項目中和核心開發無關配置文件的作用,這是不對的,我們應該對自己的項目做到極致掌控,瞭解項目中每一個文件每一行代碼對項目的作用,接下來就來一起看看我們創建的項目中所有文件的作用吧!

在初始化創建項目時,默認創建了很多子文件(一些組件、樣式文件等等),我們先把不需要的項目無關文件刪乾淨,需要我們處理的無用文件都在 src 文件夾下:

  • 刪除 src/views 下所有文件
  • 刪除 src/stores 下所有文件
  • 刪除 src/components 下所有文件
  • 刪除 src/assets 下所有文件

清除乾淨之後,我們在 src/views 文件夾下新建一個 HomePage.vue 文件,隨便寫點東西:

```html

```

然後修改一下 router/index.js 路由文件,把之前刪掉頁面的路由幹掉,加上 HomePage 頁面的路由

```js import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', name: 'HomePage', component: () => import('@/views/HomePage.vue') } ] })

export default router ```

再來修改一下項目根組件 src/App.vue 的內容,把無用的刪了,只留下面內容即可

```html

```

最後,項目入口文件裏,有一行 css 樣式的引入,引入的樣式文件我們已經刪了,所以,把這行代碼刪除掉

```js import { createApp } from 'vue' import { createPinia } from 'pinia'

import App from './App.vue' import router from './router'

// 刪除掉,css文件已經刪除過了 // import './assets/main.css'

const app = createApp(App)

app.use(createPinia()) app.use(router)

app.mount('#app') ```

ok,處理好之後我們就會得到一個很乾淨的項目了,如果你的步驟和我一致,目前的文件目錄應該是下面這樣的,我們簡單介紹下它們的作用。

bash toolsdog ├─.vscode # vscode配置文件 | └─extensions.json # 項目推薦插件列表(可把項目中用到的vscode插件ID寫進去,跑項目時沒有安裝這些插件會推薦安裝) ├─public/ # 公共資源目錄 ├─src/ # 核心開發目錄 | ├─App.vue # 項目根組件 | ├─main.js # 項目入口文件 | ├─views/ # 項目視圖目錄 | | └─Home/index.vue | ├─stores/ # 統一狀態管理目錄-pinia | ├─router/ # 項目路由目錄 | | └─index.js | ├─components/ # 項目公共組件目錄 | ├─assets/ # 項目靜態資源目錄 ├─.eslintrc.cjs # eslint 配置文件 ├─.gitignore # git忽略文件 ├─.prettierrc.json # prettier 配置文件 ├─README.md # 項目説明文件 ├─index.html # html入口文件 ├─package.json # 項目配置和包管理文件 ├─vite.config.js # vite 配置文件

再次啟動項目,如果沒有問題的話,打開瀏覽器你的頁面目前就是下面這樣子

接下來我們逐步的加一些目錄、依賴和配置讓我們的項目更健壯、更好用!

安裝組件庫

一般我們開發為了省事兒都會用一個開源組件庫,我們這裏當然少不了,至於用什麼,這裏我們用字節的 arco.design ,那至於為什麼用這個,因為 ElementPlus 用膩了,嘗試下新鮮的,我也是頭一次用,組件庫嘛,用什麼都無所謂。

安裝 ArcoVue

```bash npm install --save-dev @arco-design/web-vue

or

pnpm add -D @arco-design/web-vue ```

配置按需加載

因為懶,所以我們組件使用 unplugin-vue-components 和 unplugin-auto-import 這兩款 vite 插件來開啟按需加載及自動導入,插件會自動解析模板中的使用到的組件,並導入組件和對應的樣式文件。

其實説白了,這兩個插件一個是自動幫我們引入一些組件和指令(只做 HTML 中使用的常規組件例如各種 .vue 組件的引入以及指令的自動引入),另一個是自動幫我們做一些 API 組件的自動引入(像直接在 script 中引入的必須用 API 調用的 Message 組件以及後面我們還會用它做 Vue 的一些 API 自動引入等等)

先安裝

```bash npm i unplugin-vue-components -D npm i -D unplugin-auto-import

or

pnpm add -D unplugin-vue-components pnpm add -D unplugin-auto-import ```

然後我們在 vite.config.js 文件中配置使用一下插件

```js import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue'

import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ArcoResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), AutoImport({ resolvers: [ArcoResolver()] }), Components({ resolvers: [ ArcoResolver({ sideEffect: true }) ] }) ]

// ... }) ```

可以看到上面我們在 unplugin-vue-components/resolvers 中導出了一個 ArcoResolver ,它是什麼呢?

其實,它是插件內置的解析器,像常用的組件庫(element、antd 等)自動引入的一些配置都被內置了 👉🏻 查看內置支持的組件庫解析器,我們只需要導出對應 UI庫 的解析器用就行了,如果你使用的組件庫沒有被內置,你完全可以自己寫一個,如果是通用組件庫的話,你甚至可以直接 PR 到插件 GitHub,混一個開源項目的 Contributors 玩,並不複雜,因為後面寫項目的時候應該會簡單寫到幾個解析函數,不多解釋了。

OK,現在組件庫和自動引入都做好了,先試一試,我們在 home 頁面分別用 ArcoVue 的普通按鈕 AButton 組件和全局提示 AMessage 組件試一試。

```html

```

可以看到,我們不需要自己去引入就可以隨時隨地的使用組件庫中的組件了!

配置項目內組件 & API 的自動引入

我們在使用 Vue 的過程中,每個 script 以及 js 文件中或多或少需要引入一些像 ref、reactiveVueAPI,包括 VueRouter、Pinia 等都要引入一些 API,還有我們自己寫的組件也都需要我們手動去引入使用。

那既然配置了組件庫自動引入,我們接下來也配置API、以及頁面組件的自動引入。

還是在 vite.config.js 文件中,依舊還是上面那 2 個插件,我們來寫一下配置。

```js import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue'

import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ArcoResolver } from 'unplugin-vue-components/resolvers'

// https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), AutoImport({ // 需要去解析的文件 include: [ /.[tj]sx?$/, // .ts, .tsx, .js, .jsx /.vue$/, /.vue\?vue/, // .vue /.md$/ // .md ], // imports 指定自動引入的包位置(名) imports: ['vue', 'pinia', 'vue-router'], // 生成相應的自動導入json文件。 eslintrc: { // 啟用 enabled: true, // 生成自動導入json文件位置 filepath: './.eslintrc-auto-import.json', // 全局屬性值 globalsPropValue: true }, resolvers: [ArcoResolver()] }), Components({ // imports 指定組件所在目錄,默認為 src/components dirs: ['src/components/', 'src/view/'], // 需要去解析的文件 include: [/.vue$/, /.vue\?vue/, /.md$/], resolvers: [ ArcoResolver({ sideEffect: true }) ] }) ]

// ... }) ```

如上,在 API 自動引入插件 AutoImport 中我們寫了指定要去解析的文件 include 配置,然後在 import 選項中指定了自動引入的包名,並且所有自動引入的 API 在被自動引入時會添加記錄到根目錄的 ./.eslintrc-auto-import.json 文件中,方便我們查看都自動引入了哪些東西,後面我們使用這幾個包的 API ,就不需要手動引入了,插件會幫我們在文件解析時自動引入。

同樣的,在組件自動引入插件 Components 中,我們配置了指定要去解析的文件 include 配置,然後在 import 選項中指定了自動引入的組件目錄,以後只要是在這幾個目錄下寫的組件,我們在使用時都必須要手動去引入了

ok,我們來試一下。

我們在 src/components 文件夾下新建一個 HelloWorld.vue 文件,寫上下面內容。

```html

```

然後,直接在 src/views/HomePage.vue 文件中使用 HelloWorld 組件,不要引入,如下:

```html

```

上面我們在創建的 HelloWorld 組件中使用了 Vueref API,並沒有引入它,而後在 HomePage 頁面中使用該組件也沒有引入,我們來跑一下項目。

nice!後面我們使用 VueVueRouterPiniaArcoVue 包括自建組件等等都不需要手動引入了,當然,後續你的項目中有用到其他地方你依然可以在插件中去配置!

安裝 VueUse

VueUse 大家沒用過的話可以先把它理解為一個基於 Vue 的工具庫,Vue2Vue3 都可以用,有很多實用的方法、組件包括指令,超級方便,後續我們會用到其中的一些方法,所以先裝上

安裝

```bash npm i @vueuse/core

// or

pnpm add @vueuse/core ```

配置自動引入

VueUse 不止有方法,還有組件和指令,所以我們還是需要上面兩個自動引入的插件去處理,那由於作者是一個人,解析器都內置在自動引入插件中了,所以我們直接導出用就可以了。

我們配置 VueUse 的組件和指令自動引入需要兩個解析器,還是在 vite.config.js 配置文件中引入,如下:

bash // ArcoVue、VueUse 組件和指令的自動引入解析器 import { ArcoResolver, VueUseComponentsResolver, VueUseDirectiveResolver } from 'unplugin-vue-components/resolvers'

使用的話,只需要在配置文件 plugins 模塊中之前寫過的 Components 插件中使用一下這兩個解析器就好了:

js plugins: [ Components({ // ... VueUseComponentsResolver(), VueUseDirectiveResolver() }) ]

API 方法的自動引入就很簡單了,還是配置文件中只需要在之前用過的 AutoImport 插件中添加一個 VueUse 包名配置就行了:

js plugins: [ AutoImport({ // 新增 '@vueuse/core' imports: ['vue', 'pinia', 'vue-router', '@vueuse/core'], resolvers: [ArcoResolver()] }), ]

這樣我們就可以在項目中隨時隨地的使用 VueUse 了!建議大家有時間可以去看看 VueUse 的源碼實現,也並不複雜,它有很多最佳實踐,可以給我們使用 Vue3 提供很大的幫助!

配置 ESLint 和 Prettier

那上面我們配置了自動引入,但是大家會發現,由於之前我們給項目安裝了 ESLintPrettier ,雖然還沒有進行配置,但是默認配置會給那些自動引入的 API 報紅,就比如下面這樣

還有這個

作為一個強迫症患者,這是不能存在的,所以我們配置下 ESLintPrettier ,配置之前我們先看看初始化的配置是什麼樣子

根目錄下的 .eslintrc.cjsESLint 配置,當前默認如下

```js / eslint-env node / require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = { root: true, 'extends': [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-prettier' ], parserOptions: { ecmaVersion: 'latest' } } ```

根目錄下的 .prettierrc.jsonPrettier 配置,當前默認如下

json {}

那麼如何讓我們自動引入的那些 API 不報紅呢?

那報紅這種檢測肯定是 ESLint 乾的, 還記得我們自動引入配置的那個導出文件嗎?我們所有自動引入的 API 都生成了記錄在這個文件,你只需要將它寫入 ESLint 配置的 extends 中讓 Lint 工具識別下就好了,如下

```jsx / eslint-env node / require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = { root: true, 'extends': [ // 這裏 './.eslintrc-auto-import.json', 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-prettier' ], parserOptions: { ecmaVersion: 'latest' } } ```

注意,extends 這個繼承配置的是一個數組,最終會將所有規則項進行合併,出現衝突的時候,後面的會覆蓋前面的,我們在初始化項目安裝時默認給加上去了 3 個,我們看看這三個是什麼?

  • plugin:vue/vue3-essential
    • ESLint Vue3 插件擴展
  • eslint:recommended
    • ESLint 官方擴展
  • @vue/eslint-config-prettier
    • Prettier NPM 擴展

我們把 Prettier 擴展放到最後面,原因是 Prettier 會格式化代碼,是為了保證最終代碼格式統一。

ok,保存在看看,是不是不報紅了。

那麼我們還需要配置什麼?

可能很多同學沒有用過 Vue3 ,這裏直接給大家説,由於我們接下來要使用 Vue3CompositionAPI,那 Vue3 有幾個可以直接在 <script setup> 中可用的全局 API,比如 definePropsdefineEmitsdefineExpose,如果你使用 TS,還會用到 withDefaults

那我們的 ESLint 默認是識別不了這些全局 API 的,此時需要向 ESlint 規則中添加需要辨認的全局變量。

ESLint 配置中的 globals 屬性就是讓項目在 lint 執行期間訪問額外的全局變量,簡單説就是開發者自定義的全局變量,我們依次加上這些屬性就可以了。

```js / eslint-env node / require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = { root: true, 'extends': [ './.eslintrc-auto-import.json', 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-prettier' ], // 這裏 globals: { defineEmits: "readonly", defineProps: "readonly", defineExpose: "readonly", withDefaults: "readonly", }, parserOptions: { ecmaVersion: 'latest' } } ```

如上,添加全局屬性時,readonly 代表只讀,writable 代表可寫,可寫就是可以手動覆蓋這個全局變量的意思,我們當然是不允許覆蓋了,所以全部都設置成了 readonly

我們可以看到在 .eslintrc.cjs 文件中第一行有個 /* eslint-env node */ 註釋,它是用來指定文件為 node 環境的。

作為一個比較嚴格的強迫症,這種莫名其妙的註釋是不允許出現的,OK,刪掉它,所以就報紅了:

這就是因為我們沒有去指定這個文件用 node 規則解析,其實我們不需要去在開頭寫這麼一行註釋指定文件環境,我們給 ESLint 指定一下常用環境,即 env 屬性配置,讓 ESLint 自己去匹配,我們不寫這個配置的話默認它只支持瀏覽器 browser 的規則解析,寫上環境配置,我們最終的配置文件如下:

```js require("@rushstack/eslint-patch/modern-module-resolution");

module.exports = { // 這裏 env: { // 瀏覽器環境 browser: true, // Node環境 node: true, // 啟用除了modules以外的所有 ECMAScript 6 特性 es2021: true, }, root: true, extends: [ "./.eslintrc-auto-import.json", "plugin:vue/vue3-essential", "eslint:recommended", "@vue/eslint-config-prettier", ], globals: { defineEmits: "readonly", defineProps: "readonly", defineExpose: "readonly", withDefaults: "readonly", }, parserOptions: { ecmaVersion: "latest", }, rules: { semi: ["warn", "never"], // 禁止尾部使用分號 "no-debugger": "warn", // 禁止出現 debugger }, }; ```

如上所示,我們在環境這塊配置了三個

  • browser ── 瀏覽器環境
  • node ── Node 環境
  • es6 ── 啟用除了 modules 以外的所有 ECMAScript 6 特性

都用的到,直接都開啟就好。

可能我們也都發現了,我們新增了一個 rules 屬性,如單詞字面意思,就是規則的配置,可以配置啟用一些規則及其各自的錯誤級別,那由於每個人的喜好不同,所以我沒有過多配置,只配置了 2 個。

rules 的規則配置有三種:

  • off 或 0 關閉對該規則的校驗
  • warn 或 1 啟用規則,不滿足時拋出警告,不會退出編譯進程
  • error 或 2 啟用規則,不滿足時拋出錯誤,會退出編譯進程

注意,如果某項規則,有額外的選項,可以通過數組進行傳遞,數組的第一位必須是錯誤級別,就比如我們配置的 semi 規則中的 never 就是額外配置項。

那我們就配置到這裏,後續大家按照自己的喜好在 rules 中配置一些規則就可以了。

PS: 親測安裝了 VSCodeBabel JavaScript 插件後, JS 代碼末尾如果不加分號,會導致後續代碼高亮、註釋不正常,在 VSCode 中禁用這個插件就好了,高亮錯誤展示如下:

配置完了 ESLint ,我們再來看Prettier,我這邊配置了幾個常用的,如下

json { "semi": false, "singleQuote": true, "printWidth": 80, "trailingComma": "none", "arrowParens": "avoid", "tabWidth": 2 }

  • semi 代碼結尾是否加分號
  • singleQuote 是否使用單引號
  • printWidth 超過多少字符強制換行
  • trailingComma 代碼末尾不需要逗號
  • arrowParens 單個參數的箭頭函數不加括號 x => x
  • tabWidth 使用 n 個空格縮進

Prettier 配置就比較簡單,按照文檔和喜好在 .prettierrc.json 文件中配置就可以,注意配置的時候一定要和 ESLintrules 比較一下,這裏是會發生衝突的地方,檢測和格式化規則一定要一致。

配置 SVGIcon

項目中我們多多少少會用到一些圖標,而目前 SVG 圖標是主流,所以我們配置下 SVG 圖標。

我們這裏還用到 antFu 大佬寫的 unplugin-icons 插件,它基於 iconify 圖標庫支持按需訪問上萬種圖標,當然,我們不使用圖標庫也是可以的,也可以配置自定義一些 SVG 圖標。

同時,因為此插件和上面自動引入的兩個插件都是 antFu 大佬寫的,所以,我們也可以直接為引入的 Icon 配置自動引入對應圖標組件,很方便。

安裝插件

```bash npm i -D unplugin-icons

or

pnpm add unplugin-icons -D ```

配置插件

配置之前,我們先在 src/assets 文件夾下創建一個 svg 文件夾,然後在其下面新建兩個文件夾,一個叫 home 一個叫 user,在下面隨便放 2 個 svg 文件,我們下面會給大家簡單演示怎麼配置和使用自定義的 SVG 圖標集合。

這塊詳細配置相關的就不給大家講了,因為文章 Vue3!ElementPlus!更加優雅的使用Icon 中已經詳細説過了,大家可以先去看看這便文章再來看這塊,我這邊再寫的話比較浪費時間。

整個的配置如下所示:

```js import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue'

// API自動引入插件 import AutoImport from "unplugin-auto-import/vite" // 組件自動引入插件 import Components from "unplugin-vue-components/vite" import { ArcoResolver, VueUseComponentsResolver, VueUseDirectiveResolver } from 'unplugin-vue-components/resolvers' // icon 插件 import Icons from "unplugin-icons/vite" // icon 自動引入解析器 import IconsResolver from "unplugin-icons/resolver" // icon 加載 loader import { FileSystemIconLoader } from "unplugin-icons/loaders"

// https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), AutoImport({ include: [ /.[tj]sx?$/, /.vue$/, /.vue\?vue/, /.md$/, ], imports: ["vue", "pinia", "vue-router"], eslintrc: { enabled: true, filepath: "./.eslintrc-auto-import.json", globalsPropValue: true, }, resolvers: [ArcoResolver()], }), Components({ dirs: ["src/components/", "src/view/", "@vueuse/core"], include: [/.vue$/, /.vue\?vue/, /.md$/], resolvers: [ ArcoResolver({ sideEffect: true, }), VueUseComponentsResolver(), VueUseDirectiveResolver(), // icon組件自動引入解析器使用 IconsResolver({ // icon自動引入的組件前綴 - 為了統一組件icon組件名稱格式 prefix: "icon", // 自定義的icon模塊集合 customCollections: ["user", "home"], }), ], }), // Icon 插件配置 Icons({ compiler: "vue3", customCollections: { // user圖標集,給svg文件設置 fill="currentColor" 屬性,使圖標的顏色具有適應性 user: FileSystemIconLoader("src/assets/svg/user", (svg) => svg.replace(/^<svg /, ' svg.replace(/^<svg /, '<svg fill="currentColor" ') ), }, autoInstall: true, }), ] }) ```

使用圖標庫中 Icon

打開 iconify 的官方圖標網站 icones

隨便挑幾個複製一下名字

然後我們在 HomePage 頁面中直接去按規則寫組件就行(我們上面配置了自動引入的 icon 組件前綴必須寫 <icon- ),那我們使用起來如下:

```html

```

如上,我們 copy 名字就可以直接使用,項目運行時寫完保存,項目就可以自動為我們下載這個集合的圖標並識別解析這個格式的 icon 組件

使用自定義 Icon

那如何使用我們自定義的圖標集,比如上面我們配置中自定義的 home、user 集合,我們在 home 文件夾下放了一個 copy.svg 還有一個 download.svg 文件,使用如下

```html

```

同樣,自定義的圖標我們也寫在 在 HomePage 頁面中。

最後我們來看下目前 HomePage 頁面代碼

```html

```

最終效果:

安裝 VSCode 插件 Iconify IntelliSense

這是 iconify 圖標庫的 VSCode 插件,VSCode 中搜索插件:

```js Iconify IntelliSense

// or 搜索插件ID

antfu.iconify ```

安裝之後,我們在使用圖標庫內圖標時,直接可以在 VSCode 中預覽到圖標,超級方便,如下

圖標樣式的話你可以直接在 icon 組件中添加,OK,圖標也好了!

Styles 公共樣式管理、初始化樣式

接下來我們簡單做一下 CSS 公共樣式的處理,我們在項目 src 目錄下新增一個 styles 文件夾,此文件夾我們後期可以放一些公共的樣式文件。

大家都知道,HTML 標籤是有默認樣式的,一般我們在寫項目時都會直接清除掉這個默認樣式,也就是做個重置。

那相較於 Eric Merer 原版的清楚樣式文件,Normalize.css 它在默認的 HTML 元素樣式上提供了跨瀏覽器的高度一致性,是一種現代的、為 HTML5 準備的優質替代方案,所以我們直接使用它就好了。

下載 Normalize.cssStyles 文件夾下,當然你也可以直接 npm 安裝它,不過我比較喜歡直接下載下來這個文件。

下載下來之後直接在 main.js 最上面引入一下就行了,如下

```js import { createApp } from "vue" import { createPinia } from "pinia" // 這裏 import "@/styles/normalize.css"

import App from "./App.vue" import router from "./router"

const app = createApp(App)

app.use(createPinia()) app.use(router)

app.mount("#app") ```

其他的公共 css 文件我們用到的時候也可以這樣引入一下就可以了。

配置 UnoCSS

CSS 這塊,我們的原則是能簡單就簡單,所以我們基於 ACSS 即原子化的 CSS 框架來做。

不瞭解 原子化 的同學建議先看下這篇文章 「前端工程四部曲」模塊化的前世今生(下)

Tailwind CSS 大家應該都知道, WindiCSS 呢,算是他的一個超集,本來我想用 WindiCSS 的,但是 WindiCSS 作者們都不咋維護了,然後 UnoCSS 又這麼便捷,配置文件都不需要寫,直接引入 Vite 插件和對應的預設就可以了,So,上 UnoCSS。。。

UnoCSS,官方説它是一個按需原子 CSS 引擎,它默認提供了流行實用程序優先框架 Tailwind CSSWindi CSSBootstrapTachyon 等的通用超集,如果你習慣這些框架,依舊可以按照熟悉的方式寫,無縫銜接。

不用不知道,用了是真香啊,當然,肯定是有人不喜歡原子化 CSS 的,不喜歡不用,畢竟就是寫 CSS 的方式不一樣而已,我這邊也不會做很多配置,你甚至可以用原生 CSS

安裝

```bash npm install --save-dev unocss @unocss/preset-uno @unocss/preset-attributify @unocss/transformer-directives

or

pnpm i -D unocss @unocss/preset-uno @unocss/preset-attributify @unocss/transformer-directives ```

如上,我們裝了 4 個包

配置

還是在 Vite 插件配置中,也就是 vite.config.js 文件中配置

```js import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue'

// ...

// Unocss 插件 import Unocss from 'unocss/vite' // Unocss 默認預設 import presetUno from '@unocss/preset-uno' // Unocss 屬性模式預設 import presetAttributify from '@unocss/preset-attributify' // Unocss 指令轉換插件 import transformerDirective from '@unocss/transformer-directives'

// https://vitejs.dev/config/ export default defineConfig({ plugins: [ // ...

// 新增一個 Unocss 插件配置
Unocss({
  // 預設
  presets: [presetUno(), presetAttributify()],
  // 指令轉換插件
  transformers: [transformerDirective()],
  // 自定義規則
  rules: []
}),

]

// ... }) ```

OK,就這麼簡單。

使用

在使用之前我們先在入口文件 main.js 中一下 UnoCSScss 文件:

```js import { createApp } from 'vue' import { createPinia } from 'pinia' import '@/styles/normalize.css'

// 導入Unocss樣式 import 'uno.css'

// ... ```

基礎使用如下:

html <button class="bg-blue-400 hover:bg-blue-500 text-sm text-white font-mono font-light py-2 px-4 rounded border-2 border-blue-200 dark:bg-blue-500 dark:hover:bg-blue-600"> Button </button>

如果你對這些原子化樣式不太熟悉的話,直接打開樣式查詢地址 https://uno.antfu.me/

輸入對應 CSS 樣式去搜就可以了,如下:

當然,我是不建議你這麼做的,因為個人覺得不太好用,感覺好像不太完善,既然我們用的預設支持 Tailwind / WindiCSS ,所以,我建議大家直接去看看這兩個文檔,瞭解一個大概,按照這兩個東西的寫法來就可以,有啥不會的去這兩個的文檔裏搜

那推薦最好是直接去看 WindiCSS 使用文檔,因為作者是一個人嘛,如下,直接搜對應 CSS 看怎樣使用就可以了

然後在項目中直接使用就行了,真丫機智!!!

我們上面安裝了 @unocss/preset-attributify 屬性預設,所以我們也可以使用屬性模式,可以將實用程序分為多個屬性,這樣寫:

```html <button bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600" text="sm white" font="mono light" p="y-2 x-4" border="2 rounded blue-200"

Button ```

肯定有人覺得原子化 CSS 全寫在 HTML 中,太多的話,看上去眼花繚亂很不爽,那所以我們還安裝了指令轉換器插件 @unocss/transformer-directives 就是為了解決這個問題了。

它允許我們使用 @apply指令在 style 中寫原子化 CSS

```html

```

安裝 VSCode 插件 UnoCSS

我們安裝一下 UnoCSS 官方的 VSCode 插件,VSCode 擴展中搜索:

```js UnoCSS

// or 搜索ID

antfu.unocss ```

安裝之後,就可以在編輯器中看到我們寫的原子化對應的 CSS 樣式了,如下:

當然 UnoCSS 還有很多功能,這裏不過多描述了,有興趣文檔看一看,後面寫項目的過程中也會逐步的去介紹。

如果我們是剛開始使用,肯定會不習慣,但是,只要堅持幾天,直接真香警告!畢竟,一切都是為了簡單,一切都是為了省事兒,一切都為了少寫代碼!!!

Utils、Hooks、API 管理

我們在項目 src 目錄下添加一個 utils 文件夾,此文件夾用於存放我們項目中用到的一些公共方法文件。

同樣的,我們在項目 src 目錄下添加一個 hooks 文件夾,此文件夾用於存放我們項目中用到的一些 hooks 文件,因為我們用 Vue3CompsitionAPI,後面用多了自然會有很多 hooks 文件,針對一些公用的,我們統一管理在此文件夾下。

平常我們做項目,一般和請求相關的文件都統一放在一個文件夾下,所以我們在項目 src 目錄下添加一個 api 文件夾,用於存放和請求相關的文件,因為項目性質,所以我們應該暫時用不到請求後端接口,那這邊 api 文件的一些配置以及 axios 的封裝甚至 API Mock 配置這裏都先不展開説了,回頭我會寫好這塊代碼提交到 GitHub ,後面有需要的話會寫一篇 axios 封裝相關的文章來單獨介紹這塊。

其他 Vite 配置

先來説環境的配置,先放個官方文檔壓壓驚

OK,我們在 env 目錄下新建下面 3 個文件

  • .env 所有模式下都會加載
  • .env.development 只在開發模式下加載
  • .env.production 只在生產模式下加載

.env 文件在所有模式下都會加載,所以這裏我們可以寫一些所有環境都通用的環境變量,如下:

```bash

所有環境都會加載

項目標識代碼

VITE_APP_CODE="TOOLSDOG"

項目名

VITE_APP_NAME="工具狗"

項目描述

VITE_APP_DESCRIPTION="你用的到的工具,這裏都有!" ```

注意,我們在 Vite 中配置的環境變量默認只有以 VITE_ 開頭的配置,才會暴露給客户端,我們才能在項目中獲取到。

開發模式 .env.development 配置

```bash

開發環境加載

環境標識

VITE_APP_ENV="development"

公共基礎路徑

VITE_BASE="/"

代理URL路徑

VITE_BASE_URL ="/api"

模擬數據接口路徑

VITE_BASE_MOCK_URL ="/mock-api"

服務端接口路徑

VITE_BASE_SERVER_URL = "..."

打包是否使用Mock

VITE_APP_PRODMOCK=false ```

那生產環境除了環境標識 VITE_APP_ENV 和開發模式標識不同,其他配置項應儘量保持一致,只是配置項的內容不同而已,不一一的展示了。

接下來修改下 package.json 腳本命令如下

json { "scripts": { "serve": "vite --mode development", "build": "vite build --mode production", "preview": "vite preview --port 8081", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" } }

上面腳本中我們給啟動命令搞成了

```json npm run serve

// or

pnpm serve ```

serve 腳本命令配置中,我們還傳了一個 mode,其實這個 mode 就是對應我們的環境文件 .env.[mode]

開發環境默認 mode 就是 development,生產環境默認 mode 就是 development,所以腳本命令這裏我不傳 mode 也可以,但是如果大家把開發環境文件由 .env.development 改成 .env.dev,那腳本中 mode 就得傳 —-mode devbuild 時也是一樣的道理,如果有其他環境,那腳本命令傳入對應的 mode 就可以了。

如果想要在 vite.config.js 文件中獲取對應運行 mode 環境變量的配置,我們可以使用 viteloadEnv API

VitedefineConfig 方法也可以接收一個返回配置對象的回調函數,回調函數的參數裏我們可以拿到運行腳本命令時傳入的 mode 值,從而使用 loadEnv 方法去在 Vite 配置文件中獲取對應 mode 下的環境變量,如下:

```js // export default defineConfig({}) 修改

export default defineConfig(({mode}) => { return {} }) ```

那其他一些基礎配置就不一一説明了,大家可以直接看 Vite 官方文檔

目前我們的配置如下:

```js / * @LastEditors: isboyjc * @Description: Vite 項目配置 * @Date: 2022-09-17 14:35:02 * @LastEditTime: 2022-09-23 01:56:21 * @Author: isboyjc / import { fileURLToPath, URL } from 'node:url'

import { defineConfig, loadEnv } from 'vite' import vue from '@vitejs/plugin-vue'

// API自動引入插件 import AutoImport from 'unplugin-auto-import/vite' // 組件自動引入插件 import Components from 'unplugin-vue-components/vite' // ArcoVue、VueUse 組件和指令自動引入解析器 import { ArcoResolver, VueUseComponentsResolver, VueUseDirectiveResolver } from 'unplugin-vue-components/resolvers' // icon 插件 import Icons from 'unplugin-icons/vite' // icon 自動引入解析器 import IconsResolver from 'unplugin-icons/resolver' // icon 加載 loader import { FileSystemIconLoader } from 'unplugin-icons/loaders' // Unocss 插件 import Unocss from 'unocss/vite' // Unocss 默認預設 import presetUno from '@unocss/preset-uno' // Unocss 屬性模式預設 import presetAttributify from '@unocss/preset-attributify' // Unocss 指令插件 import transformerDirective from '@unocss/transformer-directives'

// https://vitejs.dev/config/ export default defineConfig(({ mode }) => { const viteEnv = loadEnv(mode, './')

return { base: viteEnv.VITE_BASE, server: { host: '0.0.0.0', port: '8080', open: true, // 端口占用直接退出 strictPort: true // 本地服務 CORS 是否開啟 // cors: true, // proxy: { // [viteEnv.VITE_BASE_URL]: { // target: viteEnv.VITE_BASE_SERVER_URL, // // 允許跨域 // changeOrigin: true, // rewrite: path => path.replace(viteEnv.VITE_BASE_URL, '/') // } // } }, build: { outDir: 'dist', assetsDir: 'static/assets', // sourcemap: true, // 規定觸發警告的 chunk 大小,消除打包大小超過500kb警告 chunkSizeWarningLimit: 2000, // 靜態資源打包到dist下的不同目錄 rollupOptions: { output: { chunkFileNames: 'static/js/[name]-[hash].js', entryFileNames: 'static/js/[name]-[hash].js', assetFileNames: 'static/[ext]/[name]-[hash].[ext]' } } }, resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, plugins: [ vue(), // 使用Unocss Unocss({ // 預設 presets: [presetUno(), presetAttributify()], // 指令轉換插件 transformers: [transformerDirective()], // 自定義規則 rules: [] }), AutoImport({ include: [ /.[tj]sx?$/, // .ts, .tsx, .js, .jsx /.vue$/, /.vue\?vue/, // .vue /.md$/ // .md ], imports: ['vue', 'pinia', 'vue-router', '@vueuse/core'], // 生成相應的自動導入json文件。 // eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals eslintrc: { enabled: true, filepath: './.eslintrc-auto-import.json', // Default ./.eslintrc-auto-import.json globalsPropValue: true // Default true, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable') }, resolvers: [ArcoResolver()] }), Components({ // imports 指定組件所在位置,默認為 src/components dirs: ['src/components/', 'src/view/'], include: [/.vue$/, /.vue\?vue/, /.md$/], resolvers: [ ArcoResolver({ sideEffect: true }), VueUseComponentsResolver(), VueUseDirectiveResolver(), IconsResolver({ // icon自動引入的組件前綴 - 為了統一組件icon組件名稱格式 prefix: 'icon', // 自定義的icon模塊集合 customCollections: ['user', 'home'] }) ] }), Icons({ compiler: 'vue3', customCollections: { // user圖標集,給svg文件設置fill="currentColor"屬性,使圖標的顏色具有適應性 user: FileSystemIconLoader('src/assets/svg/user', svg => svg.replace(/^<svg /, ' svg.replace(/^<svg /, '<svg fill="currentColor" ') ) }, autoInstall: true }) ] } }) ```

那項目配置文件暫時就到這裏了,後期寫項目還會用到一些東西,我們到時候再配置。

添加 Config 配置

上面説了,環境變量默認以 VITE_ 開頭的配置,才會暴露給客户端,我們也寫了幾個 VITE_ 開頭的配置,所以在項目運行時,我們可以直接 import.meta.env.VITE_XXX 去查看配置,但是這樣太麻煩了,所以我們寫一個統一的配置文件去獲取環境變量,包括項目後期的一些全局配置也可以寫裏面

項目 src 目錄下新建 config/config.js 文件,寫入下面文件:

```js / * @LastEditors: isboyjc * @Description: 全局config配置文件 * @Date: 2022-09-17 14:35:02 * @LastEditTime: 2022-09-17 14:35:02 * @Author: isboyjc /

// 獲取環境變量 const ENV = import.meta.env // 配置文件 let config = {} // 默認配置文件 const configSource = { appCode: ENV.VITE_APP_CODE, // 項目標識代碼 projectCode: ${ENV.VITE_APP_CODE}_${ENV.VITE_APP_ENV}, // 項目名 projectName: ENV.VITE_APP_NAME, // 項目描述 projectDesc: ENV.VITE_APP_DESCRIPTION, // 資源base地址 base: ENV.VITE_BASE, // 接口代理URL路徑 baseUrl: ENV.VITE_BASE_URL, // 模擬數據接口路徑 mockBaseUrl: ENV.VITE_BASE_MOCK_URL, // 服務端接口路徑 serverUrl: ENV.VITE_BASE_SERVER_URL }

/* * @Author isboyjc * @Date 2022-09-17 14:35:02 * @description 設置全局配置 * @param {Object} cfg 配置項 * @return {Object} 新的全局配置 config / const setConfig = cfg => { config = Object.assign(config, cfg) return config }

/ * @Author isboyjc * @Date 2022-09-17 14:35:02 * @description 重置全局配置 * @param {} * @return {Object} 全局默認配置 configSource / const resetConfig = () => { config = { ...configSource } return config } resetConfig()

/* * @Author isboyjc * @Date 2022-09-17 14:35:02 * @description 獲取全局配置 * @param {String} key 配置項,支持 'a.b.c' 的方式獲取 * @return {Object} 新的全局配置 config / const getConfig = key => { if (typeof key === 'string') { const arr = key.split('.') if (arr && arr.length) { let data = config arr.forEach(v => { if (data && typeof data[v] !== 'undefined') { data = data[v] } else { data = null } }) return data } } if (Array.isArray(key)) { const data = config if (key && key.length > 1) { let res = {} key.forEach(v => { if (data && typeof data[v] !== 'undefined') { res[v] = data[v] } else { res[v] = null } }) return res } return data[key] } return { ...config } }

export { getConfig, setConfig, resetConfig } ```

上面代碼不復雜,所以不過多解釋了,介紹下為什麼用這種方式,而不是直接寫一個對象導出,其實是因為有次寫項目有用到了動態修改全局配置的需求,所以就把全局配置項獲取寫成動態的了。

我們寫入配置時,只需要在 configSource 對象中寫入就可以了,項目中使用起來的話如下:

```js import { getConfig, setConfig, resetConfig } from "@/config/config.js"

// 獲取配置 getConfig("a") getConfig("a.b") getConfig("a.b.c")

// 動態設置 setConfig({ ... })

// 重置配置 resetConfig() ```

配置 VSCode 推薦擴展插件

打開項目根目錄的 .vscode/extensions.json 文件如下:

json { "recommendations": [ "vue.volar", "vue.vscode-typescript-vue-plugin" ] }

這是創建項目時默認存在的擴展插件推薦配置,此文件的作用上面也介紹過了,就是個擴展推薦,數組裏是 VSCode 的擴展插件 ID,你在根目錄打開此項目時,如果編輯器沒有安裝這兩個插件,VSCode 就會在右下角自動提示你去安裝插件。

那我們沒有使用 TS 直接幹掉 vue.vscode-typescript-vue-plugin 這一項。

我們想要添加一個插件到推薦裏,可以複製插件 ID 寫到此配置中,也可以直接點擊添加到工作區建議,如下:

回顧一下上文,我們一共裝了 2 個插件

bash Iconify IntelliSense UnoCSS

那我這裏把這兩個插件的 ID (注意是 ID 不是插件名字)都寫進推薦列表裏了:

json { "recommendations": [ "vue.volar", "antfu.iconify", "antfu.unocss" ] }

大家如果克隆項目使用 VSCode 啟動,就會提示你去安裝這些插件了。

項目協同

創建 GIT 代碼倉庫

GitHub 創建倉庫,倉庫名為 toolsdog,開源許可選擇 MIT

為項目綁定遠程倉庫

先在本地倉庫初始化一下 git

bash git init

Copy 一下倉庫地址,給本地項目關聯遠程倉庫,入下:

bash git remote add origin [email protected]:isboyjc/toolsdog.git

然後首次提交一下代碼,就 OK 了!

由於項目一直在開發中,所以我給當前分支提交打了個標記,大家無需拉取主分支代碼,直接下載當前標記的代碼就和文中代碼一致了,地址如下 👇🏻

項目 GitHub 地址

最後

簡單寫個小項目,沒有配置太多東西,像一般來説我們構建工作流都會用 GitHook 工具在提交時去檢測代碼,那目前礙於文章篇幅加上眼下就我自己開發,所以也沒配置,後期都會補充,不要着急,此項目大家僅供參考,照搬不可取,汲取對自身有用的就可以了,有什麼不足之處也請指出,如果你想學習下 Vue3,可以跟着一塊來敲一敲,不喜勿噴!如果您覺得文章不錯,記得 點贊 ,歡迎關注 Vue3 實戰專欄

本文為稀土掘金技術社區首發簽約文章,14天內禁止轉載,14天后未獲授權禁止轉載,侵權必究!