最初對前端的觀感:眼花繚亂,各種各樣的工具鏈以及其對應的配置檔案、VS Code 外掛,各種技術百家爭鳴,選擇眾多。後來才理解前端不同於後端,後端程式碼的執行環境相對可控,而前端程式碼執行在使用者裝置上,所以需要相容不同的環境,而很大一部分的工具、配置都是解決相容性的問題
TL;DR
工程化的目的:降低開發成本提高開發效率
方式:解決前端三大件(HTML, CSS, JS)存在的問題並對其進行增強,JS 透過 Babel
而 CSS 可以透過 Sass
, Less
, PostCSS
等工具實現進行增強,並且保證輸出向後相容的的 JS 或 CSS 程式碼
模組化、包管理
分解聚合:拆分複雜任務,降低複雜度(分而治之)
模組化解決 問題:1. 全域性汙染 2. 依賴管理 等等
JS 模組化標準(常用):1. CommonJS
(Node 標準)2. ES modules
(JavaScript 官方標準模組化方案)
實現:1. 瀏覽器只支援 ESM 2. Node 和 構建工具 上面兩種標準都支援
包 (package) 管理:npm(Node.js的標準包管理器),還有其他的 pnpm 和 yarn 等
JS 工具鏈
JS 語言本身一直都在繁榮地發展,經常出現新的 API 和 語言特性,但是使用者的執行環境(瀏覽器、Node等)的版本可能是五花八門的,可能會導致報錯、相容性等的問題,所以最樸素的解決方式就是把 JS 都轉換為向後相容的老版本 JS 程式碼。前端的執行環境更多的是在使用者這邊,這點不同於後端能比較自由地調整伺服器執行環境,這可能就是前端縫縫補補的原因吧,修補主要有的方式:
- 新 API:使用 Polyfill(填充物),為其實現缺少的 API,例如
core-js
庫,就實現了Array
的flatMap
方法,這樣在舊版本的 Node 環境,也可使用該方法 - 新語法:例如
Promise
,對於這樣的語法糖,就無法直接為其編寫方法,需要轉換程式碼,有點類似翻譯,透過regenerator
庫可以將含有Promise
的程式碼轉換為向後相容的程式碼
有很多這樣的庫用於解決某個特定的相容性問題,一個個匯入很麻煩,所以就有了 Babel,可以透過 Babel
的外掛整合這些轉換程式碼的庫,需要安裝對應的 Babel
外掛依賴 並在 babel.config.js
中配置 plugins
。這樣還是很麻煩,所以我們可以直接使用 Babel
的預設,其中最常用的就是:@babel/preset-env
,安裝依賴以後完成以下的 babel.config.js
配置,即可開箱即用:
// common js
module.exports = {
presets: [
// 預設名稱 & 配置
['@babel/preset-env', {
targets: {
edge: '17',
firefox: '60',
chrome: '67',
safari: '11.1'
},
// 按需匯入 polyfill,未使用的 API 不匯入
useBuiltIns: 'usage',
corejs: '3.37.0',
}]
]
// 外掛的配置方式
// plugins: [
// '@babel/plugin-transform-optional-chaining'
// ]
}
有了這種思維之後,就可以透過 轉換程式碼 的方式任意地增強 JS 的能力,就像:JSX
和 TypeScript
,它們最終還是會被編譯為純 JS 程式碼
CSS 工具鏈
CSS 語法缺失(邏輯、函式等等),無法進行復雜的操作,所以就有了 CSS 預編譯器:Less, Sass 等等的,與 JS 的處理方式一樣,可以透過工具對其進行轉換,轉換為最樸素的 CSS,這樣就沒有相容性的問題。解決了相容性問題還需要解決 CSS 本身的問題:
- 瀏覽器字首 ( vendor prefixes ):類似
-webkit-
開頭的樣式 ,可以透過 autoprefixer 來自動新增瀏覽器字首以確保網頁在不同瀏覽器中的相容性 - 壓縮:減少 CSS 檔案的大小,從而提高網頁載入速度,相關的庫 cssnano
- 剪枝:移除沒有用到的 CSS,相關的庫:purgecss
- 類名衝突:透過 css module 來實現,相關的庫:postcss-modules
與處理 JS 的 Babel
類似,CSS 也有工具整合了上面這些工具,它就是PostCSS,安裝需要的 依賴後,還需要配置 postcss.config.js
。與 Babel 類似,它也可以開箱即用,需要安裝依賴並配置 postcss-preset-env
module.exports = {
map: false,
plugins: {
tailwindcss: {},
'postcss-preset-env': {},
},
};
構建工具和腳手架
開發和執行的程式碼不一致,開發階段我們希望工程程式碼可以方便地開發維護,而在對於生產執行的程式碼,我們則希望它相容性強、檔案小、載入快等等。這中間就需要打包工具來進行轉換,常用的打包工具有:webpack,它的主要作用:
- 模組化管理:使得專案結構清晰、依賴關係明確
- 打包編譯:將各個模組按照其依賴關係進行打包編譯,將它們轉換為瀏覽器可識別的靜態資原始檔
- 資源最佳化:壓縮 JavaScript、CSS、圖片等檔案,以減小檔案體積,提高載入速度
- 程式碼分割:實現按需載入,提高頁面載入效能
- 開發伺服器:自動編譯並執行服務(熱更新),便於開發
- Source Map:儲存了編譯後程式碼與原始碼之間的對映關係,便於除錯程式碼
與 Babel
和 PostCSS
相似,一旦有很多細碎的東西出現,就必然有工具可以進行整合並提供預設,對於整個程式碼工程來說,它就是腳手架:vue-cli, vite 等等,提供了互動式的介面輔助生成工程模版
參考資料
ECMAScript 6 入門 - 阮一峰
工程化大師課
What is @babel/preset-env and why do I need it?
postcss 結合 tailwindcss
前端技術的十八年風雨(2006-2024)