背景
最近要做一個(gè)新項(xiàng)目,打算用 vite 來(lái)搭建項(xiàng)目。畢竟最近 vite 很火,vite 也可以說(shuō)代表著未來(lái),可以學(xué)習(xí)一下。
本文主要記錄整個(gè)項(xiàng)目的搭建過(guò)程。
腳手架
直接用 vite 官方文檔 提供的命令來(lái)初始化整個(gè)項(xiàng)目,框架選擇 React ,加上 ts 類型提示。整個(gè)過(guò)程沒(méi)有踩到坑,很順暢。
組件庫(kù)
組件庫(kù)使用字節(jié)開源的 arco-design。原因是以前一直用的 arco-desigin,對(duì)它比較熟悉 (提過(guò)PR),而且 oncall 也能及時(shí)響應(yīng)。
css
tailwind,推薦使用,沒(méi)有用過(guò)的一定要試一下??!
tailwind css 是現(xiàn)代工程化框架里把原子css做到極致的css框架,它將大部分css屬性封裝成語(yǔ)義化的類,使用者的關(guān)注點(diǎn)從寫css到使用tailwind類名,極大的減少了代碼量。
優(yōu)點(diǎn):
降低為類命名的精力——如何為div起一個(gè)語(yǔ)義化的類名是開發(fā)者經(jīng)常遇到的問(wèn)題,使用tailwind之后,大部分情況下都能直接使用 tailwind 類名而無(wú)需開發(fā)者關(guān)注如何起名,這對(duì)大部分開發(fā)者都是喜聞樂(lè)見(jiàn)的事。
大大減少CSS代碼量。
樣式跟著元素走,方便刪除。tailwind是內(nèi)聯(lián)在元素上,元素如果需要?jiǎng)h除,css也會(huì)跟著刪除。
缺點(diǎn):原子類太多,需要花費(fèi)時(shí)間去記憶和查閱官方文檔。
如果你是VSCode使用者,VSCode有tailwind插件提示。

請(qǐng)求
請(qǐng)求使用 fetch,使用 React hooks 庫(kù) swr 來(lái)管理請(qǐng)求的狀態(tài),包括返回的數(shù)據(jù),error狀態(tài)等。
舉個(gè)??:
import useSWR from 'swr'
function Profile() {
const { data, error } = useSWR('/api/user', fetcher)
if (error) return <div>failed to load</div>
if (!data) return <div>loading...</div>
return <div>hello {data.name}!</div>
}
swr 對(duì)接口狀態(tài)進(jìn)行了封裝,在內(nèi)部維護(hù)了數(shù)據(jù)的狀態(tài),使開發(fā)者不在需要去自行維護(hù)這些狀態(tài)。
當(dāng)然,swr 的能力不止這些,還有像條件請(qǐng)求、自動(dòng)重新請(qǐng)求、緩存等功能。
狀態(tài)管理
新項(xiàng)目狀態(tài)管理舍棄了 redux,原因是太繁瑣,不好用。
接入了輕量級(jí)的 unstated-next ,使用很簡(jiǎn)單,源碼也才40行,很容易理解原理。
項(xiàng)目目錄
-src
-assets
-components
-constant
-hooks
-pages
-services
-routes.ts
-App.tsx
-main.css
-main.tsx
路由配置
新增 routes.ts 文件,所有頁(yè)面的路由都集中在 routes.ts 配置。
import YourComponent from '@pages/YourComponent'
const routesConfig = [
{
path: '/',
component: YourComponent
},
]
export default routesConfig
把頁(yè)面布局以及路由都集中到 App.tsx 中:
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import routerConfig from '@/routes'
import Layout from '@/components/Layout'
import Header from '@/components/Header';
import { Notification } from '@arco-design/web-react'
import userContainer, { useUser } from '@/hooks/useUser';
import { Spin } from '@arco-design/web-react'
import './main.css';
import "@arco-design/web-react/dist/css/arco.css";
function App() {
const { isLoading, isError } = useUser();
if (isLoading) {
return <Spin dot />
}
if (isError) {
Notification.error({
title: '請(qǐng)重新登錄',
content: '正在重新加載',
})
return null;
}
return (
<BrowserRouter basename='mlbb'>
<userContainer.Provider>
<Header />
<div className="flex">
<Layout />
<div className="bg-slate-200 flex-1 p-5 h-screen overflow-hidden">
<Routes>
{
routerConfig.map((route) => {
const { path, component: Component} = route
return (
<Route key={route.path} path={path} element={<Component />} />
)
})
}
</Routes>
</div>
</div>
</userContainer.Provider>
</BrowserRouter>
)
}
export default App;
在 App.tsx 里面,可以判斷當(dāng)前用戶是否登錄,如果沒(méi)有登錄則提示登錄及展示登錄頁(yè)。
由于筆者是在 sso 登錄,已經(jīng)在接口層面做了判斷,如果沒(méi)有登錄會(huì)直接在接口層打開 sso 登錄頁(yè)。
整個(gè)頁(yè)面的布局如下:

渲染
在 main.tsx 渲染 App
import ReactDOM from 'react-dom/client'
import App from './App';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<App />
)
問(wèn)題
整個(gè)流程還是比較順暢的,唯一遇到的問(wèn)題是在 接入 sso 之后,如果本地啟動(dòng)還是用 localhost去訪問(wèn),則 sso 無(wú)法訪問(wèn),這就需要把頁(yè)面通過(guò)域名來(lái)訪問(wèn),然后代理到本地。
而 vite 默認(rèn)是無(wú)法通過(guò)ip去訪問(wèn)的,需要在 vite.config.ts 配置 host :
