第八期:前端九條啟發分享
一、 設定git commit的校驗 (husky:^5
版本之前配置與這裡不一樣)
在一般情況下, 我們每次執行git commit -m'提交資訊'
的時候, 會觸發針對commit資訊的校驗以及程式碼風格的校驗, 如果沒通過校驗會導致commit失敗, 那麼這些校驗是如何加入到專案中的那?
大部分時候新增針對commit的校驗我們會使用husky
這個包, 讓我們來安裝一下它:
yarn add husky -D
在packgae.json中新增下面內容, 這裡是初始化.husky/目錄並指定該目錄為git hooks
所在的目錄, 所謂的git hooks
可以理解為git的鉤子函式, 比如git add
執行之前, git commit
之後等等生命週期的鉤子函式, 而git hooks
所在目錄就是用來定義git
各個生命週期需要執行的各種函式。
{
"scripts": {
"prepare": "husky install"
}
}
第一步: 新增程式碼校驗
接下來我們在命令列執行:
yarn prepare
npx husky add .husky/pre-commit "npm run lint"
上述第二條命令定義了pre-commit
這個生命週期執行npm run lint
這句命令。
在packgae.json中定義lint
命令是使用eslint
檢測src
資料夾裡的檔案, 當然啦檢測什麼檔案都可以。
"scripts": {
"lint": "eslint src"
},
第二步: 新增提交資訊校驗
校驗commit
資訊我們最簡便的方式就是依賴commitlint
這個包。
yarn add @commitlint/config-conventional @commitlint/cli -D
在根目錄裡新建commitlint.config.js
並寫入下面內容:
module.exports = {
extends: ["@commitlint/config-conventional"]
};
新增校驗commit的hook:
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
上面命令的意思是建立一個commit-msg
hook的檔案, 裡面的內容是npx --no-install commitlint --edit "$1"
。
commitlint
命令來檢測$1
這個引數的值是否合法, 而$1
就是我們的git commit -m ${1}
。
校驗的標準
這裡我只列出最常用的幾個:
規範 | 使用方式 |
---|---|
docs | git commit -m"docs: 更新xxx文件" |
feat | git commit -m"feat: 新增xxx模組" |
fix | git commit -m"fix: 修復了上線的xxxxbug" |
style | git commit -m"style: 更新使用者資訊彈框的樣式" |
test | git commit -m"test: 修改新增使用者按鈕的測試用例" |
與你專案裡配置不一樣?
有的同學可能發現了, 我這裡的寫法可能與你專案裡的寫法不一致, 你的專案可能是如下的寫法:
{
"husky": {
"hooks": {
"pre-commit": "npm run test",
"commit-msg": "commitlint -e $HUSKY_GIT_PARAMS"
}
}
}
上述寫法是husky^6
版本之前的寫法, 現在husky
已經更新到了7版本, 所以未來建立新專案可能不會再用這種寫法配置了。
git的hook
二、 ///這種註釋的使用
我們在react
專案程式碼裡會看到下面這種註釋, 那麼這種奇怪的註釋是幹麼的那?
/// <reference types="react-scripts" />
原來這種/// <reference types="包" />
的寫法主要用在.d.ts
檔案裡面, 作用是引入其他的.d.ts
檔案, 比如我需要用到一個xxx.d.ts
檔案, 但是這個並沒有放在node_modules/@types
裡面, 所以並不會被系統預設匯入。
三、 推薦一款react
引導外掛 guide
一般網站第一次訪問的時候都會有個引導操作, 使用guide
就可以輕鬆實現, 讓我們一步步來配置:
yarn add byte-guide
這個外掛的使用方法的中心思想是, 我們以陣列的形式傳入一套配置, 找個配置裡面有要被掛載
的目標dom, 以及顯示的文案等資訊, 然後每次點選下一步就可以依次執行陣列內的物件:
import Guide from "byte-guide";
export default function Home() {
const SEARCH = {
hotspot: true,
title: "搜尋元件",
selector: "#search",
placement: "top-left",
content: <div>這個搜尋元件很厲害</div>,
offset: { x: 20 },
};
const TOTAL = {
title: "列表總數",
parent: "#search",
selector: "#total",
placement: "right",
content: "這裡是列表總數。",
};
return (
<div className={"org"}>
<div id={"search"}>目標1</div>
<div id={"total"}>目標2</div>
<Guide
lang="en"
localKey="uni-key"
className="my-guide"
steps={[SEARCH, TOTAL]}
onClose={() => {
console.log("點選關閉");
}}
afterStepChange={(nextIndex, nextStep) => {
console.log("點選下一步");
}}
/>
</div>
);
}
主要屬性的說明
localKey
: 我們引導元件的顯示一般是隻有使用者第一次登入才顯示, 或者是當使用者點選了引導的結束按鈕就永遠不顯示了,guide
將是否需要展示引導元件的值儲存在Local Storage
中, 所以這裡定義了儲存的key名。placement
定義了彈出框所在的位置, 比如頂端的元素我們會選擇使用bottom
之類的屬性。offset
雖然設定了placement
但是難免位置不盡人意, 所以可以使用這個屬性對引導框進行位置的再調。
注意事項
元件內建了簡單的國際化, 也就是當我們不指定文案的時候, 他自己會根據傳入的語言英語
、中文
、日語
進行文案的改變。
這個外掛有bug, 如果兩個元素處於父元素的內部滾動狀態時, 會出現定位偏差非常多的問題, 所以如果你的引導專案涉及內部滾動的元素則不建議使用這個外掛。
四、 eslint 7 版本之後可以註釋
發現團隊專案中難免會出現一些/* eslint-disable*/
這種註釋, 每次看到會嘗試將其刪除, 但是可能會引起一系列的連鎖翻譯, 這種情況下如果我們使用的是eslint^7
版本及以上, 則可以新增註釋, 說明為什麼這裡必須使用/* eslint-disable*/
。
// eslint-disable-next-line a-rule -- 這裡的錯誤無法修復!
上面的寫法更加友好, 因為畢竟這種禁止eslint
檢測的方式不推薦大家使用, 如果必須要使用也需要在初期就標明原因。
五、 統一一個index檔案匯出的利與弊
比如我們有很多的工具方法
放在同一個資料夾下,a.js
檔案匯出a1, a2
等方法 我們常常使用一個index.js
檔案進行統一的匯出, 專案裡會有很多如下的寫法:
export * from './a';
export * from './b';
export * from './c';
export * from './d';
這種寫法雖然看起來計較"優雅"但是有不少弊端存在, 這裡我們就列舉一下:
1: 匯出名字可能重複
這是個小問題因為會有ts
報錯提示, 起因是index.js
檔案裡面沒有寫出具體的方法名, 所以需要每次修改留意一下index檔案是否報錯。
2: 程式碼尋徑麻煩
這點也就是對操作最不友好的一點, 比如我們在某個頁面上有一個外界匯入的方法, 我們mac電腦的話點選`c
ommand + 滑鼠左鍵就可以查到這個方法的出處, 但是往往只是尋徑到了
index.js`, 這裡也沒有具體的方法名稱呈現, 所以需要再次進到各個檔案裡面查詢。
3: 改變匯出沒有提示
當我們修改一個匯出時沒有提示, 比如刪掉一個匯出方法, 修改一個匯出方法的名稱, 此時並不會在檔案本身以及index.js
檔案種報錯, 報錯的地方是具體使用到這個方法的檔案, 這就可能會忽略到, 因為不啟動專案直接git push
也是可以檢驗通過的。
4: ts型別二次推導
有時候會出現你命名匯出了一個方法函式, 但是eslint報錯說沒有匯出該成員
, 但是當我們進入到這個方法的資料夾裡後, eslint的報錯就消失了, 這種不好的體驗都與這種寫法有關。
六、svgr
庫轉換svg圖片
, filter:drop-shadow
xxx.svg
這些檔案是不好控制的, 我們想動態的傳入很多配置可能需要藉助svgr
這個庫將svg圖片
轉換成react
元件的形式, 通過下面的命令可以在命令列生成程式碼資料:
npx @svgr/cli --icon 圖片的地址.svg
在命令列裡生成肯定是不能工程化的, 其實各種腳手架已經內建了這個svgr
庫, 所以我們其實如下方式就可以使用元件模式的
svg圖片啦。
import { ReactComponent as Logo } from "./logo.svg";
// ....
<Logo width={"30px"} style={{ filter: "drop-shadow(red 20px 0)" }} />
filter: "drop-shadow(red 20px 0)"
這句可以使svg變成紅色,關於它的細節我會單拿一篇文章去講。
七、 yarn resolutions 管理被多專案依賴的包
專案中會引用很多的npm包, 比如我們專案裡面依賴了A包
, A包
自身又依賴 ^3.1.5
版本的B包
, 我們專案本身yarn add B
已經安裝了^3.0.5
版本的B包
, 此時B包
其實是可以通用的, 完全沒必要引用兩個版本。
並且如果打包的話由於我們兩處依賴的不同版本的B包
導致打包後體積的增大, 所以yarn
提供了resolutions
這個配置項, 我們可以如下配置(package.json):
"resolutions": {
"B": "^3.1.5"
}
舉一個實際的例子
我們建立一個新專案
npx create-react-app 專案名稱
進入到專案中
yarn list --depth=1
列出專案的依賴, 並且只列印一級依賴即可, 我們就以workbox-build
為例:
我們在外層package.json
進行配置:
"resolutions": {
"fs-extra": "^4.0.2"
}
此時執行yarn
命令, 並且在此yarn list --depth=1
列印:
上面的依賴關係已經變化了, 不是僅僅在workbox-build
包的下面了。
八、 pnpm 代替 yarn lean做包的管理
我們經常使用yarn + lean
這種方式管理子專案, 但是傳輸中pnpm
更適合做這個工作, 那麼為什麼說pnpm
更適合那?
yarn
管理node_modules
的機制會導致, A包
依賴的B包
, 那麼B包
的檔案位置會處於與A包
同級, 這就導致開發者雖然沒有執行yarn add B
但是專案中也可以引入import B from 'B'
, 這就為開發埋下拉隱患。
pnpm
採用的方式是, 將包統一管理, 單個專案的node_modules
檔案裡面儲存的類似軟連線
, 這樣就不會出現重複安裝某個依賴的情況了, 並且也沒必要將B 與 A
放在同一層級了, 也就不存在莫名其妙的引入B包的情況
。
當我們有很多子專案並且依賴越來越複雜的時候, pnpm
的優勢就顯示出來了。
九、 微前端的子應用, 如何單獨啟動
微前端應用裡面都會有幾個子專案, 這些子專案往往會依賴一個主專案(殼工程), 主專案負責分發一些重複使用的資源, 比如react react-router
等等公用的依賴, 並且也會出現主專案裡的一些自定義的utils
工具方法傳遞給子專案
。
由於存在眾多需要主專案分發的資源那麼就對子專案單獨的執行製造了困難, 我們每次都要啟動至少主專案+子專案
, 並且想要看到完整工程還需要啟動其餘的所有子專案
, 但我們有什麼辦法只啟動子專案自身那?
我這裡的做法是利用請求的代理, 因為大部分微前端框架的原理是每個子專案
都是一個js檔案
, 主應用啟動後按需載入子專案的js入口檔案
, 那麼我們就可以訪問線上測試環境
的地址, 然後找到線上測試環境
的主應用訪問子應用的url
, 然後將這個url
代理其指向本地啟動的子專案
的地址即可。
這樣做的好處就是可以讓子專案完全處於一個線上環境的主應用的上下文裡, 並且不用啟動其餘子專案, 要注意子專案的css
檔案也要代理過來。
end
這次就是這樣, 希望與你一起進步。