使用Vite快速構建前端React專案

xiangzhihong發表於2023-02-28

一、Vite簡介

Vite是一種面向現代瀏覽器的一個更輕、更快的前端構建工具,能夠顯著提升前端開發體驗。除了Vite外,前端著名的構建工具還有Webpack和Gulp。目前,Vite已經發布了Vite3,Vite全新的外掛架構、絲滑的開發體驗,可以和Vue3完美結合。 

相比Webpack和Gulp等構建工具,Vite有如下一些優勢:

  • Vite主要對應的應用場景是開發模式,跳過打包按需載入,因此更新的速度非常快;
  • 在大型專案上可以有效提高本地開發編譯打包的速度,解決“改一行程式碼等半天”的問題;
  • 瀏覽器解析 imports,利用了 type="module"功能,然後攔截瀏覽器發出的 ES imports 請求並做相應處理;
  • 閃電般的冷啟動速度;
  • 即時熱模組更換(熱更新);
  • 真正的按需編譯;
     

總的來說,Vite希望提供開箱即用的配置,同時它的外掛API和JavaScript API帶來了高度的可擴充性。不過,相比Vue-cli配置來說,Vite構建的專案還是有很多的配置需要開發者自己進行處理。 

Vite構建工具由兩部分組成:

  • 開發伺服器:基於原生 ES 模組提供了豐富的內建功能,如模組熱更新(HMR)。
  • 構建指令:使用 Rollup 打包程式碼,並且它是預配置的,可以輸出用於生產環境的最佳化過的靜態資源。
     

同時,在瀏覽器支援方面,Vite也區分了開發環境和生產環境:

  • 開發環境:Vite需要在支援原生 ES 模組動態匯入的瀏覽器中使用。
  • 生產環境:預設支援的瀏覽器需要支援透過指令碼標籤來引入原生 ES 模組。可以透過官方外掛 @vitejs/plugin-legacy 支援舊瀏覽器。
     

二、環境搭建

“工欲善其事,必先利其器”。首先,我們需要的是程式碼編輯器和瀏覽器,推薦VSCode和Chrome瀏覽器。其次,是安裝Node.js,如果還沒有安裝Node.js,可以從Node,js官網下載相應的安裝包並手動安裝。
 

Vite需要Node.js 12.0.0 及以上版本,如果低於這個版本,推薦安裝一下nvm工具,然後安裝多個Nodo.js版本並進行多版本切換。同時,Node.js自帶的npm和yarn映象源是在國外,因此包管理器方面我推薦使用 pnpm,或者使用下面的命令更改映象源:

pnpm config set registry https://registry.npmmirror.com/

三、初始化專案

環境搭建完成之後,接下來我們就進入到專案初始化階段。首先,在終端命令列中輸入如下的命令:

npm create vite

在執行完上面的命令後,npm 首先會自動下載create-vite這個第三方包,然後執行這個包中的專案初始化邏輯。輸入專案名稱之後按下回車,此時需要選擇構建的前端框架:

✔ Project name: vite-project
? Select a framework: › - Use arrow-keys. Return to submit.
    vanilla // 無前端框架
    vue     // 基於 Vue 
 >  react   // 基於 React
    preact  // 基於 Preact(一款精簡版的類 React 框架)
    lit     // 基於 lit(一款 Web Components 框架) 
    svelte  // 基於 Svelte

此處,我們選擇構建的框架為React。接著,執行如下命令在啟動本地專案:

cd vite-project
npm install
npm run dev

安裝完成之後,去瀏覽器中開啟http://localhost:5173/頁面就可以看到示例專案了。

image.png

很多人說,Vite是Webpack的替代工具,那Vite相比Webpack究竟有啥優勢呢。下面我們拿 基於 Webpack 的腳手架create-react-app來測試一下專案初始化到依賴安裝所花的時間對比:

image.png

四、專案入口

首先,我們開啟Vite構建的專案,專案的目錄結構如下:

.
├── index.html
├── package.json
├── src
│   ├── App.css
│   ├── App.tsx
│   ├── favicon.svg
│   ├── index.css
│   ├── logo.svg
│   ├── main.tsx
│   └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts

和其他前端工具構建的專案一樣,Vite構建的專案的入口也是index.html。也就是說,當我們訪問http://localhost:5173的時候,Vite 的 Dev Server 會自動返回這個 HTML 檔案的內容,index.html檔案的內容如下。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

可以看到,在 body 標籤中除了 id 為 root 的根節點之外,還包含了一個宣告瞭type="module"的 script 標籤。

<script type="module" src="/src/main.tsx"></script>

由於現代瀏覽器原生支援了 ES 模組規範,因此原生的 ES 語法也可以直接放到瀏覽器中執行,只需要在 script 標籤中宣告 type="module" 即可。main.tsx 的內容如下:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'


ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

看到這段程式碼,大家可能會不太理解:瀏覽器並不識別 tsx 語法,也無法直接 import css 檔案,那上面這段程式碼是如何被瀏覽器正常執行的呢?答案是,Vite 會對檔案的內容進行編譯處理,轉化成瀏覽器能夠執行的程式碼,如下圖所示。

image.png

需要說明的是,在Vite專案中,一個 import 語句即代表了一個 HTTP 請求,下面的程式碼就代表了兩個不同的請求:

import "/src/index.css";
import App from "/src/App.tsx";

五、配置檔案

和WebPack構建工具一樣,使用Vite構建的專案也需要進行一些配置才能滿足日常開發的需要,如配置啟動埠vite --port=8888。

通常,Vite的配置支援兩種方式,一是透過命令列引數,二是透過配置檔案,推薦使用配置檔案的方式來宣告。Vite 當中支援多種配置檔案型別,包括.js、.ts、.mjs三種字尾的檔案,實際專案中一般使用vite.config.ts作為配置檔案,比如:

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


// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
})

可以看到,我們在配置檔案配置了react 外掛,所以會提供 React 專案編譯和熱更新的功能。接下來,我們可以基於這個檔案進行更加豐富的配置,比如將入口檔案index.html放到src目錄下,此時就需要新增如下配置:

import { defineConfig } from 'vite'
// 引入 path 包注意兩點:
// 1. 為避免型別報錯,你需要透過 `pnpm i @types/node -D` 安裝型別
// 2. tsconfig.node.json 中設定 `allowSyntheticDefaultImports: true`,以允許下面的 default 匯入方式
import path from 'path'
import react from '@vitejs/plugin-react'
export default defineConfig({
  // 手動指定專案根目錄位置
  root: path.join(__dirname, 'src')
  plugins: [react()]
})

當我們在配置檔案中指定root引數之後,Vite 會自動從這個路徑下尋找index.html檔案,也就是說當我們啟動專案的時候,Vite會從src目錄下讀取入口檔案,從而實現上面的需求。

六、生產環境配置

在開發階段,為了加快專案的構建速度,Vite透過 Dev Server 實現了不打包的特性;而在生產環境中,Vite 依然會基於 Rollup 進行打包,並採取一系列的打包最佳化手段。 關於這一點,可以從package.json中找到答案:

"scripts": {
  // 開發階段啟動 Vite Dev Server
  "dev": "vite",
  // 生產環境打包
  "build": "tsc && vite build",
  // 生產環境打包完預覽產物
  "preview": "vite preview"
},

看到上面的指令碼,你可能會比較疑惑:為什麼在vite build命令執行之前要先執行tsc命令呢?事實上,tsc 作為 TypeScript 的官方編譯命令,可以用來編譯 TypeScript 程式碼並進行型別檢查,而這裡的作用主要是用來做型別檢查,我們可以從專案的tsconfig.json中注意到這樣一個配置。

{
  "compilerOptions": {
    // 省略其他配置
    "noEmit": true,
  },
}

雖然 Vite 提供了開箱即用的 TypeScript 以及 JSX 的編譯能力,但實際上底層並沒有實現 TypeScript 的型別校驗系統,因此需要藉助 tsc 來完成型別校驗,從而在打包前提早暴露出型別相關的問題,保證程式碼的執行沒有任何問題。
 

接下來,我們可以使用 npm run build來生成線上包,然後透過 npm run preview 命令預覽一下打包產物的執行效果。

image.png

到此,我們對Vite有了一些基本的認識:相比於Webpack等傳統構建工具,Vite利用了瀏覽器原生 ES 模組的支援,在開發階段使用Dev Server進行模組的按需載入,而不是先整體打包再進行載入,因此效率會比較高。

相關文章