前端“新秀”Vite構(gòu)建實(shí)戰(zhàn) (文末抽獎(jiǎng)送書(shū))

2021年2月17日,Vite 2.0發(fā)布了,并在前端圈引起了轟動(dòng)。
引起轟動(dòng)的原因如下:
◎?去掉了打包步驟,可快速冷啟動(dòng)。
◎?可及時(shí)熱更新模塊,不會(huì)隨著模塊變多而使得熱更新變慢。
◎?真正的按需編譯。
Vite是基于瀏覽器native的ES module開(kāi)發(fā)的,基于Bundleless思想。
在了解Vite之前,需要先了解Bundle和Bundleless。Bundle和Bundleless是兩種開(kāi)發(fā)方式,自2015年ESM標(biāo)準(zhǔn)發(fā)布后,這兩種開(kāi)發(fā)方式就逐漸明確。
在日常開(kāi)發(fā)中,一般使用Webpack 對(duì)代碼進(jìn)行編譯,并打包生成Bundle文件。其原因如下:
◎?很多應(yīng)用都運(yùn)行在HTTP/1.1上,并且各瀏覽器有連接限制。
◎?系統(tǒng)不能直接運(yùn)行瀏覽器不支持的模塊,如CommonJS。
◎?瀏覽器不識(shí)別新的語(yǔ)法。
◎?代碼依賴關(guān)系與順序管理。
但是,在項(xiàng)目達(dá)到一定規(guī)模后,基于Bundle構(gòu)建優(yōu)化的“收益”就變得越來(lái)越少,無(wú)法實(shí)現(xiàn)質(zhì)的提升。
Webpack 變慢的主要原因是,它將各個(gè)資源打包整合在一起形成 Bundle,項(xiàng)目規(guī)模越大,資源就越多。是否可以不用打包直接在瀏覽器中執(zhí)行代碼呢?當(dāng)然可以,這就是Bundleless,如圖1所示。

圖1
在Bundleless模式下,應(yīng)用不再需要構(gòu)建成一個(gè)完整的Bundle,修改文件時(shí)也不需要重新生成Bundle文件,瀏覽器只需重新加載單個(gè)文件即可。也就是說(shuō),只需刷新即可即時(shí)生效。如果有 HotModuleReplace等相關(guān)技術(shù)加持,則可以實(shí)現(xiàn)完美的開(kāi)發(fā)體驗(yàn)。
實(shí)現(xiàn)?Bundleless?一個(gè)很重要的前提是模塊的動(dòng)態(tài)加載能力,實(shí)現(xiàn)這個(gè)功能的主要思路有兩個(gè):
◎?使用System.js之類的ES模塊加載器,優(yōu)點(diǎn)是具有很好的模塊兼容性。
◎?直接利用標(biāo)準(zhǔn)的ES module。該module實(shí)現(xiàn)已經(jīng)標(biāo)準(zhǔn)化,并且各個(gè)瀏覽器廠商也已紛紛支持(Edge 79、Firefox 67、Chrome 63、Safari 11.1、Opera 50,這幾個(gè)瀏覽器支持ES module的最低版本 )。相信以后前端同時(shí)整體架構(gòu)和在各種標(biāo)準(zhǔn)化的基礎(chǔ)上也會(huì)變得更加簡(jiǎn)單。
Bundle和Bundleless的對(duì)比如表1所示。
表1

基于ES module的構(gòu)建,其實(shí)Vite并不是首創(chuàng),同樣的實(shí)戰(zhàn)在之前有類似的“輪子”,如esbuild、snowpack、es-dev-server等。下面通過(guò)示例講解Vite是如何進(jìn)行開(kāi)發(fā)的。
與常見(jiàn)的開(kāi)發(fā)工具一樣,Vite提供了用npm或者Yarn一鍵生成項(xiàng)目結(jié)構(gòu)的方式。這里使用Yarn生成一個(gè)React項(xiàng)目。
yarn create vite-app vite-projectcd vite-projectyarn install
結(jié)果如圖2所示。

圖2
index.html為頁(yè)面入口;main.jsx為系統(tǒng)主入口;vite.config.js為配置文件,該文件可以類比Vue項(xiàng)目的vue.config.js。
在項(xiàng)目開(kāi)始之前,先引入幾個(gè)項(xiàng)目核心庫(kù):核心庫(kù)react-router-dom和history、UI庫(kù)Ant Design、AJAX庫(kù)axios和CSS預(yù)處理器Less。
首先配置組件庫(kù),因?yàn)樵诤竺娴慕M件中會(huì)用到UI組件。注意,組件庫(kù)可以在配置文件中引入,而不是在main.jsx中引入。如果在main.jsx中引入,則在創(chuàng)建項(xiàng)目時(shí)構(gòu)建工具會(huì)引入整個(gè)CSS文件,這是沒(méi)有必要的。
Vite需要借助插件vite-plugin-imp 來(lái)按需加載。
yarn add vite-plugin-imp -D在vite.config.js中配置插件。
import vitePluginImp from 'vite-plugin-imp'plugins: [vitePluginImp({libList: [{libName: "antd",style: (name) => `antd/lib/${name}/style/index.less`,},],})],css: {preprocessorOptions: {less: {//內(nèi)聯(lián) JavaScriptjavascriptEnabled: true,}}}
CSS預(yù)處理器提取公有CSS變量及CSS函數(shù)并放在一個(gè)文件中,所以確認(rèn)增加以上配置。并且配置javascriptEnabled為true,支持Less內(nèi)聯(lián)JavaScript。
另一個(gè)比較實(shí)用的功能是自動(dòng)刷新,Vite也沒(méi)有掉隊(duì),借助插件@vitejs/plugin-react-refresh即可實(shí)現(xiàn)。
import reactRefresh from '@vitejs/plugin-react-refresh'plugins: [reactRefresh()]
短路徑配置
resolve: {alias: {"@": path.resolve(__dirname, 'src')}},
代理配置
server : {proxy: {'/api': {target: 'http://jsonplaceholder.typicode.com',changeOrigin: true,rewrite: (path) => path.replace(/^\/api/, '')}}}
環(huán)境參數(shù)配置
在日常開(kāi)發(fā)中,有些代碼和配置是要區(qū)分環(huán)境的。在 Webpack 中,可以在 scripts 中定義NODE_ENV,或者在webpack .config.js中定義DefinePlugin來(lái)區(qū)分環(huán)境。在Vite中,可以在scripts中定義mode來(lái)區(qū)分環(huán)境。
"dev": "vite --mode development",//環(huán)境值const env = process.argv[process.argv.length - 1]console.log("當(dāng)前環(huán)境:", env) // development
我們先在container目錄下新建兩個(gè)組件:home和main。當(dāng)path為“/”時(shí)渲染home組件,當(dāng)path為“/main”時(shí)渲染main組件。
// container/home/home.jsximport { Button } from 'antd'function Home() {return (<div><div>Home, from routerdiv><Button type="primary">submitButton>div>);}//container/main/index.jsxfunction Main() {return (<div>Main, from routerdiv>);}
有了組件之后,下面開(kāi)始配置router。在routers目錄下新建index.js。
import Home from "@/contanier/home"import Main from "@/contanier/main"export default [{path: "/",component: Home},{path: "/main",component: Main}]
定義配置后,需要在app.jsx中遍歷這個(gè)數(shù)組,生成路由配置。
//app.jsximport { BrowserRouter as Router, Route, Switch } from "react-router-dom";import routes from "./routers"function App() {const [count, setCount] = useState(0)return (<Router><div className="App"><header className="App-header">// 省略部分代碼<Switch>{routes.map(route => <Route exact key={route.path} path={route.path}><route.component />Route>)}Switch>header>div>Router>)}
啟動(dòng)項(xiàng)目
yarn run devvite v2.1.2 dev server running at:> Local: http://localhost:3000/> Network: http://192.168.1.6:3000/> Network: http://192.168.192.196:3000/ready in 1982ms.
結(jié)果如圖3所示。

圖3
輸入http://localhost:3000/main,結(jié)果如圖4所示。

圖4
有了頁(yè)面組件之后,就需要考慮AJAX請(qǐng)求的事兒了,否則頁(yè)面是沒(méi)有靈魂的。在api目錄下新建request.js,對(duì)axios做一層封裝,配置請(qǐng)求攔截器和響應(yīng)攔截器,這也是前端開(kāi)發(fā)中的通用做法。
import axios from "axios";import StatusCode from "@/constants/statusCode";const instance = axios.create({baseURL: "",timeout: 50000,xsrfCookieName: "xsrf-token",});//請(qǐng)求攔截器,如果需要在header中增加一些參數(shù),則可以在這里統(tǒng)一處理instance.interceptors.request.use((config) => {return config;},(error) => {return Promise.reject(error);});// 添加一個(gè)響應(yīng)攔截器,對(duì)每次返回的數(shù)據(jù)進(jìn)行攔截,并進(jìn)行業(yè)務(wù)判斷instance.interceptors.response.use((response) => {return Promise.reject(response.data);},(error) => {return Promise.reject(error);});
axios攔截器為我們的日常開(kāi)發(fā)提供了諸多便利,如果需要在每個(gè)請(qǐng)求中增加相同的參數(shù),則可以在請(qǐng)求攔截器中進(jìn)行配置。如果是統(tǒng)一處理返回的數(shù)據(jù),如無(wú)權(quán)限、404、沒(méi)有登錄等這種通用場(chǎng)景,則可以統(tǒng)一在響應(yīng)攔截器中進(jìn)行處理。
以上是Vite配合React開(kāi)發(fā)的基本配置。
▼
本文節(jié)選自《前端開(kāi)發(fā)必知必會(huì):從工程核心到前沿實(shí)戰(zhàn)》一書(shū),歡迎閱讀本書(shū)了解更多關(guān)于前端開(kāi)發(fā)必知必會(huì)的知識(shí)點(diǎn)。


▊《前端開(kāi)發(fā)必知必會(huì):從工程核心到前沿實(shí)戰(zhàn)》
侯躍偉 著
詮釋前端工程化實(shí)現(xiàn)細(xì)節(jié)
解密Babel、Deno、WebAssembly、Docker等前端融合
本書(shū)共5 章。第1、2 章系統(tǒng)介紹前端工程化的核心知識(shí),包括Babel 7、ES 規(guī)范、Deno 開(kāi)發(fā)入門(mén)、腳手架、自動(dòng)化部署、Nginx、Jest 測(cè)試、Webpack 5、Vite、Rollup、Parcel 等。第3、4 章著重介紹前端架構(gòu)的核心思想,包括前端核心模塊的6 種常用設(shè)計(jì)模式、V8 引擎、宏任務(wù)與微任務(wù)、異步加載規(guī)范和函數(shù)式編程等。第5 章通過(guò)實(shí)戰(zhàn)詳細(xì)介紹如何從0 開(kāi)發(fā)微前端和WebAssembly,幫助前端人員開(kāi)拓視野。
本書(shū)系統(tǒng)介紹了前端開(kāi)發(fā)的工程核心及前沿實(shí)戰(zhàn)。相信無(wú)論是初級(jí)開(kāi)發(fā)人員,還是具有豐富經(jīng)驗(yàn)的中高級(jí)開(kāi)發(fā)人員都能從本書(shū)中找到需要的內(nèi)容,都能從閱讀本書(shū)中有所收獲。
(京東滿100減50,快快掃碼搶購(gòu)吧!)
送書(shū)規(guī)則:
公眾號(hào)內(nèi)回復(fù)【抽獎(jiǎng)】掃碼即可參與
開(kāi)獎(jiǎng)時(shí)間:2021-10-06?00:00:00
