第二章的配置基本已能達到正常的開發需求了。但是還有很多地方可以進行改善。
第三章 改善專案
使用最新的ES語法
React開發中難免要用到ES最新語法。例如常用的Decorators還在Stage 2階段,Dynamic import還在Stage 3階段。這些新的語法並沒被@babel/preset-env
涵蓋。因此我們需要額外配置對應的babel外掛。
安裝babel外掛:
- 支援裝飾器
@babel/plugin-proposal-decorators
- 支援類屬性
@babel/plugin-proposal-class-properties
- 支援動態import
@babel/plugin-syntax-dynamic-import
配置.babelrc
檔案:
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
// 注意decorators外掛要寫在class-properties前面
// decorators外掛需要配置legacy為true來相容以前的裝飾器寫法
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
"@babel/plugin-syntax-dynamic-import"
]
}
複製程式碼
新增css預處理與postcss
我們可以使用sass來增強css的程式設計和抽象能力,使用postcss的autoprefixer
外掛給css自動新增瀏覽器廠商字首。
安裝:
sass-loader
postcss-loader
autoprefixer
webpack.dev.js
的配置:
// ...
module: {
rules: [
{
test: /\.scss$/,
// loader是從後往前載入的,postcss-loader得在sass-loader前面
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"]
},
// ...
]
},
// ...
複製程式碼
webpack.prod.js
的配置:
// ...
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"postcss-loader",
"sass-loader"
]
},
// ...
]
},
// ...
複製程式碼
在專案根目錄下建立postcss.config.js
檔案:
module.exports = {
plugins: [require("autoprefixer")]
};
複製程式碼
配置瀏覽器相容範圍
.babelrc
內配置的@babel/preset-env
能自動為專案打包必要的polyfill,postcss.config.js
內配置的autoprefixer
外掛能自動為css新增必要的瀏覽器廠商字首。它們是怎麼確定哪些polyfill還有哪些瀏覽器廠商字首是必要新增的呢,畢竟不同公司甚至不同專案所要相容的瀏覽器版本不一樣。有的專案沒有任何相容需求,那麼專案應該少依賴一些polyfill,有些專案要相容到IE瀏覽器,那就要新增更多的polyfill和瀏覽器廠商字首。所以我們需要配置.browserslistrc
來告訴這些打包工具我們要相容的瀏覽器範圍。
在專案根目錄下建立.browserslistrc
檔案:
> 1%
last 2 versions
not ie <= 8
複製程式碼
這個配置的大概意思是:市場份額大於1%的瀏覽器,最新的兩個版本,排除IE8以下的瀏覽器。
配置.editorconfig
有些人喜歡用水平製表符縮排,而有些人喜歡用2個空格。因為使用的作業系統不同,有些人換行符是LF,有些人是CRLF。雖然這些瑣碎的東西可以在專案開發初期約定好,並設定到每個開發人員編輯器格式化配置內。但是這樣很麻煩。
我們在專案根目錄下建立.editorconfig
:
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
複製程式碼
這個配置告訴編輯器,當前專案的縮排用的是2個空格,換行用的是LF,並在每個檔案底部插入一行空行。編輯器看到專案內有.editorconfig
檔案,就會按它的要求來格式化專案檔案。
使用editorconfig的好處是,他能更細粒度的控制每個專案甚至不同檔案型別的格式化風格,這樣可以讓不同的專案擁有不同的格式化風格。
配置完後,編輯器需要在外掛市場下載editorconfig外掛。webstorm內部預設安裝了該外掛,所以可以不用下載。
配置ESLint和prettier
ESLint可以校驗我們的程式碼風格和一些語法錯誤,在團隊開發時,可以保證程式碼風格的一致性並及早發現一些錯誤。
ESLint很多時候會因為缺少空格或逗號而報錯,這些瑣碎的錯誤會很惱人,因此我們可以使用prettier來幫助我們來格式化程式碼。
安裝:
eslint
eslint-loader
babel-eslint
eslint-config-airbnb
eslint-config-prettier
在安裝eslint-config-airbnb
時,控制檯會有warning,我們需要根據它的warning將所有的peer dependency都安裝好。
webpack.common.js
配置:
// ...
module: {
rules: [
{
enforce: "pre",
test: /\.jsx?$/,
include: path.resolve(__dirname, "src"),
use: "eslint-loader"
},
// ...
]
}
// ...
複製程式碼
根目錄下新增.eslintrc.js
:
module.exports = {
root: true,
parser: "babel-eslint",
env: {
browser: true,
es6: true,
node: true
},
parserOptions: {
ecmaVersion: 6,
sourceType: "module"
},
extends: ["airbnb", "prettier"],
rules: {
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
}
};
複製程式碼
在package.json
內新增lint
precommit
兩條指令碼
// ...
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server --config webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack --config webpack.prod.js",
"lint": "cross-env NODE_ENV=production eslint --ext .jsx --ext .js --fix ./src",
"precommit": "npm run lint"
},
// ...
複製程式碼
執行npm run lint
時,ESLint會檢查./src
目錄下的所有.js
.jsx
結尾的檔案,並盡力修復一些問題。ESLint不能修復的問題會列印到控制檯上,此時就要手動去修復問題了。
每次git提交程式碼前會先執行precommit
指令碼,該指令碼就是讓ESLint檢查程式碼,如果檢查不通過就無法提交程式碼。這樣可以保證程式碼倉庫內的程式碼質量。想要precommit
指令碼生效,需要安裝husky
(哈士奇),而且我們在指令碼內使用“cross-env”來修改環境變數,所以得安裝cross-env
。
安裝:
husky
cross-env
推薦在編輯器內安裝ESLint 外掛,這樣能在書寫程式碼實就能看的ESLint的報錯資訊。安裝ESLint外掛後,它可能會在我們不願意它去檢查的檔案內報錯,所以我們新增.eslintignore
來告訴外掛要跳過的檢查檔案與目錄。
.eslintignore配置
node_modules
/dist
webpack.common.js
webpack.prod.js
webpack.dev.js
postcss.config.js
複製程式碼
同時推薦安裝prettier外掛,並配置編輯器在儲存時自動格式化。
熱更新 (Hot Module Replacement)
使用webpack-dev-server
開發React時,每次檔案修改便會自動重新整理頁面。雖然這和傳統的手動重新整理頁面相比方便了很多,但是在某些情況下還不夠方便。就比如開發一個表單模態視窗時,重新整理頁面會導致模態視窗被關閉,並且表單內填寫的資訊丟失。
webpack的熱更新就能解決這個痛點,它能在介面不重新整理的狀態下更新介面。
webpack4預設支援熱更新,我們只需要開啟這個功能就可以。
在webpack.dev.js
內開啟熱更新:
// ...
devServer: {
hot: true, // 開啟熱更新
historyApiFallback: true
},
// ...
複製程式碼
我們使用react-hot-loader
來支援React的熱更新。
安裝:
react-hot-loader
在.babelrc
新增react-hot-loader
提供的外掛:
{
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
"@babel/plugin-syntax-dynamic-import",
"react-hot-loader/babel"
]
}
複製程式碼
注意這個外掛的寫法是react-hot-loader/babel
。
最後,修改App.jsx
內的程式碼。使用react-hot-loader
提供的高階元件來裝飾我們的App
元件。
import React from "react";
// 匯入hot函式
import { hot } from "react-hot-loader/root";
// ...
function App() {
return (
// ...
);
}
// 使用hot函式裝飾App元件
export default hot(App);
複製程式碼
搖樹優化 (Tree Shaking)
webpack4在production
模式下會開啟Tree Shaking,但是需要注意以下幾點
- 使用ES2015模組語法(例:
import
和export
),被編譯成CommonJS規範的模組不能被優化。 - 需要在
package.json
檔案內新增"sideEffects"
欄位。該欄位的值可以是模組名稱陣列,用來告訴webpack哪些模組是有負作用的。該欄位的值也可以是false
,表示所有模組都沒有副作用。被標識有副作用的模組不會被Tree Shaking。 - webpack配置內的
mode
設為"production"