熬了3天夜,準(zhǔn)備的一個React項(xiàng)目升級Vite的指南
寫在開頭(邊聽歌邊看效果更佳)
在之前,已經(jīng)很多朋友已經(jīng)升級到了 vite,但是大部分都是vue的項(xiàng)目,那么今天我們把之前webpack的react項(xiàng)目升級到vite!為此,為了讓大家少踩坑,我先把 china-dev.cn這個網(wǎng)站項(xiàng)目升級到了vite
對于在線畫圖功能,可能沒有什么影響,但是跟在線編寫 javascript這個功能影響挺大,因?yàn)橹笆褂玫膸欤瑫?code style="font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">webpack綁定,目前不支持vite,于是我更換了技術(shù)棧,但是效果反而更好了~,這說明,跟webpack強(qiáng)綁定是一個偽命題,辦法總比困難多,構(gòu)建工具只是一種選擇而已~
PS:這個網(wǎng)站永遠(yuǎn)免費(fèi),里面還有大量前端免費(fèi)學(xué)習(xí)資料,為此,我把這個項(xiàng)目抽離了業(yè)務(wù)部分,然后做成了一個簡單的項(xiàng)目模板
正式開始
如果你沒看過我之前寫的:webpack和vite的核心區(qū)別,建議你先看一遍,再來看這篇文章
webpack遷移到vite,最先要解決的事情:
把跟 webpack強(qiáng)關(guān)聯(lián)的插件&技術(shù)棧解耦,任何時候,跟一個第三方工具&環(huán)境強(qiáng)依賴,都不是一件好事,這一點(diǎn),做過重型系統(tǒng)部署的架構(gòu)師,相信都有這個感觸將項(xiàng)目中除了 import引入方式的,全部替換成通過import引入。可以這樣說,esm就是一種趨勢,因?yàn)樗褪且粋€規(guī)范。vue3已經(jīng)不支持ie11,替換國內(nèi)老舊系統(tǒng)只是時間而已,這是一個大趨勢,深圳官方的一些網(wǎng)站已經(jīng)開始推薦你使用新的瀏覽器了~規(guī)范你的代碼,不能出現(xiàn) typescript的類型錯誤等和其他警告等,vite的熱更新非常脆弱,有可能你一個小的警告或不規(guī)范寫法,就會導(dǎo)致熱更新失效,而且報錯定位不準(zhǔn),或者直接不報錯,而是失效(下面會說這些坑)接下來 克隆我的腳手架到本地
地址 https://github.com/JinJieTan/Peter-/tree/master/vite-react-ts-antd將你的 src源碼目錄植入我的項(xiàng)目模板中項(xiàng)目根目錄執(zhí)行 yarn安裝依賴index.hmtl入口文件,我這里默認(rèn)是去加載src/index.tsx文件執(zhí)行 yarn dev, 啟動項(xiàng)目 ,如果此時你的代碼沒問題,已經(jīng)run起來了(我項(xiàng)目中默認(rèn)是react17.x,ts4.x版本,如果需要降級,請你安裝指定依賴)

腳手架說明:
通過 husky在每次git commit 時候使用prettier統(tǒng)一美化代碼,再通過eslint進(jìn)行代碼檢測,最終使用commitlint提交信息是否符合要求,以此保證代碼質(zhì)量
這幾十條規(guī)則,都是我一條一條精挑細(xì)選出來的,因?yàn)槲也幌矚g用不清楚別人細(xì)節(jié)的東西,這套規(guī)則我也希望大家用下去,每一條都有注釋
rules: {
semi: ['error', 'always'], // 該規(guī)則強(qiáng)制使用一致的分號
'no-unused-vars': 'off', // 禁止未使用過的變量
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', //生產(chǎn)環(huán)境禁用 debugger
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', //生產(chǎn)環(huán)境禁用 console
'default-case': ['warn', { commentPattern: '^no default$' }], //要求 Switch 語句中有 Default
'dot-location': ['warn', 'property'], // 強(qiáng)制在點(diǎn)號之前或之后換行
eqeqeq: ['error', 'allow-null'], //要求使用 === 和 !==
'new-parens': 'warn', //要求調(diào)用無參構(gòu)造函數(shù)時帶括號
'no-caller': 'error', // 禁用 caller 或 callee
'no-const-assign': 'error', //不允許改變用 const 聲明的變量
'no-dupe-args': 'error', //禁止在 function 定義中出現(xiàn)重復(fù)的參數(shù)
'no-dupe-class-members': 'error', //不允許類成員中有重復(fù)的名稱
'no-dupe-keys': 'warn', //禁止在對象字面量中出現(xiàn)重復(fù)的鍵
'no-extend-native': 'warn', //禁止擴(kuò)展原生對象
'no-extra-bind': 'warn', //禁止不必要的函數(shù)綁定
'no-fallthrough': 'error', //禁止 case 語句落空
'no-func-assign': 'warn', //禁止對 function 聲明重新賦值
'no-implied-eval': 'error', //禁用隱式的 eval()
'no-label-var': 'error', //禁用與變量同名的標(biāo)簽
'no-loop-func': 'error', //禁止循環(huán)中存在函數(shù)
'no-mixed-operators': [
'warn',
{
groups: [
['&', '|', '^', '~', '<<', '>>', '>>>'],
['==', '!=', '===', '!==', '>', '>=', '<', '<='],
['&&', '||'],
['in', 'instanceof'],
],
allowSamePrecedence: false,
},
], //禁止混合使用不同的操作符
'no-multi-str': 'warn', //禁止多行字符串 (需要多行時用\n)
'no-native-reassign': 'warn', //禁止重新分配本地對象
'no-obj-calls': 'warn', //禁止將全局對象當(dāng)作函數(shù)進(jìn)行調(diào)用
'no-redeclare': 'error', //禁止重新聲明變量
'no-script-url': 'warn', //禁用 Script URL
'no-shadow-restricted-names': 'warn', //關(guān)鍵字不能被遮蔽
'no-sparse-arrays': 'warn', //禁用稀疏數(shù)組
'no-this-before-super': 'warn', //在構(gòu)造函數(shù)中禁止在調(diào)用 super()之前使用 this 或 super
'no-undef': 'error', //禁用未聲明的變量
'no-unexpected-multiline': 'warn', //禁止使用令人困惑的多行表達(dá)式
'no-use-before-define': [
'warn',
{
functions: false,
classes: false,
variables: false,
},
], //禁止定義前使用
'no-with': 'error', //禁用 with 語句
radix: 'error', //禁用函數(shù)內(nèi)沒有 yield 的 generator 函數(shù)
'rest-spread-spacing': ['warn', 'never'], //強(qiáng)制限制擴(kuò)展運(yùn)算符及其表達(dá)式之間的空格
'react/jsx-no-undef': 'error', //在 JSX 中禁止未聲明的變量
'react/no-direct-mutation-state': 'error', //禁止 this.state 的直接變化
'react/jsx-uses-react': 'warn', //防止 React 被錯誤地標(biāo)記為未使用
'no-alert': 0, //禁止使用alert confirm prompt
'no-duplicate-case': 2, //switch中的case標(biāo)簽不能重復(fù)
'no-eq-null': 2, //禁止對null使用==或!=運(yùn)算符
'no-inner-declarations': [2, 'functions'], //禁止在塊語句中使用聲明(變量或函數(shù))
'no-iterator': 2, //禁止使用__iterator__ 屬性
'no-negated-in-lhs': 2, //in 操作符的左邊不能有!
'no-octal-escape': 2, //禁止使用八進(jìn)制轉(zhuǎn)義序列
'no-plusplus': 0, //禁止使用++,--
'no-self-compare': 2, //不能比較自身
'no-undef-init': 2, //變量初始化時不能直接給它賦值為undefined
'no-useless-call': 2, //禁止不必要的call和apply
'init-declarations': 0, //聲明時必須賦初值
'prefer-const': 0, //首選const
'use-isnan': 2, //禁止比較時使用NaN,只能用isNaN()
'vars-on-top': 2, //var必須放在作用域頂部
},
支持ant-design按需加載
import vitePluginImp from "vite-plugin-imp";
plugins:[
...,
vitePluginImp({
libList: [
{
libName: "antd",
style(name) {
if (/CompWithoutStyleFile/i.test(name)) {
return false;
}
return `antd/es/${name}/style/index.css`;
},
},
],
}),
]
執(zhí)行無感知熱更新:
import reactRefresh from "@vitejs/plugin-react-refresh";
plugins:[
...,
reactRefresh(),
]
兼容不支持 esm的瀏覽器
import legacy from "@vitejs/plugin-legacy";
plugins:[
...,
legacy({
targets: ["defaults", "not IE 11"],
}),
]
支持ts在vite中的alias配置
vite.config.ts
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
"@c": path.resolve(__dirname, "./src/components"),
"@s": path.resolve(__dirname, "./src/service"),
"@m": path.resolve(__dirname, "./src/model"),
},
},
tsconfig.json中
"baseUrl": "./",
"paths": {
"@/*": ["./src/*"],
"@c/*": ["./src/components/*"],
"@m/*": ["./src/model/*"],
"@s/*": ["./src/service/*"],
"@t/*": ["./src/types/*"]
}
遇到的問題
第三方庫之前跟 webpack插件有綁定,而vite不支持,最后更換了技術(shù)棧vite熱更新問題,這個問題應(yīng)該很多人都會遇到,但是我踩坑一天后,就沒有再遇到了。vite的prod模式構(gòu)建,是通過tsc轉(zhuǎn)換成js后,再通過rollup進(jìn)行打包,但是先yarn build后,就會在tsx附近產(chǎn)生js文件,例如:

在這個時候,無論是熱更新模式,還是prod構(gòu)建,都是會去打包js文件,后面我刪除后就解決了這個問題。
當(dāng)然, vite熱更新還有一個問題,就是你可能會因?yàn)橐粋€警告,就熱更新失效,而且報錯定位也不準(zhǔn)確,當(dāng)系統(tǒng)變得極度復(fù)雜的時候,這個問題就很致命。原生不支持less,需要安裝以下依賴,即可直接引入使用 less,這點(diǎn)我覺得優(yōu)于webpack
yarn add less less-loader -D
使用下來感受
開發(fā)模式,比 webpack好太多。基本上毫秒級別的啟動和熱更新速度配置也比較簡單,沒有webpack那一大堆東西 純粹,干凈。沒有 require.context這種黑魔法,沒有上面是import,下面代碼里面是require。全部都是import。
有人會問,如果老的庫不兼容
esm,怎么辦,例如dva。
module.exports = require('./lib');
module.exports.connect = require('react-redux').connect;
這就有一個問題, esm在生產(chǎn)模式中無法直接引入dva,這個時候可以做一個簡單的處理,可以優(yōu)先取default屬性,如果取不到,就取默認(rèn)的
import dva from "dva";
let tag = dva.default || dva;
const app = test({
history: createHistory(),
});
寫在最后
看得再多,不如直接動手實(shí)踐,克隆我這個模板下來試試吧。別忘了給個 star,開源不易,里面還有其他的源碼,https://github.com/JinJieTan/Peter-/tree/master/vite-react-ts-antd

評論
圖片
表情
