如何擴展 Create React App 的 Webpack 配置

如何擴展 Create React App 的 Webpack 配置  
原文地址https://zhaozhiming.github.io/blog/2018/01/08/create-react-app-override-webpack-config/

Create React App(如下簡稱 CRA)是建立 React 應用的一個腳手架,它與其餘腳手架不一樣的一個地方就是將一些複雜工具(好比 webpack)的配置封裝了起來,讓使用者不用關心這些工具的具體配置,從而下降了工具的使用難度。css

可是對於一些熟悉 webpack 的開發者來講,他們可能想對 webpack 配置作一些修改,這個時候應該怎麼辦呢?react

其實咱們能夠經過如下幾種方式來修改 webpack 的配置:webpack

  • 項目 eject
  • 替換 react-scripts 包
  • 使用 react-app-rewired
  • scripts 包 + override 組合

下面對這幾種方式分別進行介紹。git

項目 eject

使用 CRA 建立完項目之後,項目在package.json裏面提供了這樣一個命令:github

1
2 3 4 5 6 7 
{  ...  "scripts": {  "eject": "react-scripts eject"  },  ... } 

執行完這個命令——yarn run eject後會將封裝在 CRA 中的配置所有反編譯到當前項目,這樣用戶就能夠徹底取得 webpack 文件的控制權,想怎麼修改就怎麼修改了。web

1
2 3 4 5 6 7 8 9 10 11 
# eject 後項目根目錄下會出現 config 文件夾,裏面就包含了 webpack 配置 config ├── env.js ├── jest │   ├── cssTransform.js │   └── fileTransform.js ├── paths.js ├── polyfills.js ├── webpack.config.dev.js // 開發環境配置 ├── webpack.config.prod.js // 生產環境配置 └── webpackDevServer.config.js 

CRA 與其餘腳手架不一樣的另外一個地方,就是能夠經過升級其中的react-scripts包來升級 CRA 的特性。好比用老版本 CRA 建立了一個項目,這個項目不具有 PWA 功能,但只要項目升級了react-scripts包的版本就能夠具有 PWA 的功能,項目自己的代碼不須要作任何修改。npm

但若是咱們使用了eject命令,就再也享受不到 CRA 升級帶來的好處了,由於react-scripts已是以文件的形式存在於你的項目,而不是以包的形式,因此沒法對其升級。json

替換 react-scripts 包

react-scripts 是 CRA 的一個核心包,一些腳本和工具的默認配置都集成在裏面,使用 CRA 建立項目默認就是使用這個包,可是 CRA 還提供了另一種方式來建立 CRA 項目,即便用自定義 scripts 包的方式。app

1
2 3 4 5 
# 默認方式 $ create-react-app foo  # 自定義 scripts 包方式 $ create-react-app foo --scripts-version 自定義包 

自定義包能夠是下面幾種形式:ide

  • react-scripts包的版本號,好比0.8.2,這種形式能夠用來安裝低版本的react-scripts包。
  • 一個已經發布到 npm 倉庫上的包的名字,好比your-scripts,裏面包含了修改過的 webpack 配置。
  • 一個 tgz 格式的壓縮文件,好比/your/local/scripts.tgz,一般是未發佈到 npm 倉庫的自定義 scripts 包,能夠用 npm pack 命令生成。

這種方式相對於以前的eject是一種更靈活地修改 webpack 配置的方式,並且能夠作到和 CRA 同樣,經過升級 scrips 包來升級項目特性。

自定義 scripts 包的結構能夠參照react-scripts包的結構,只要修改對應的 webpack 配置文件,並安裝上所需的 webpack loader 或 plugin 包就能夠了。

使用 react-app-rewired

雖然有這兩種方式能夠擴展 webpack 配置,可是不少開發者仍是以爲太麻煩,有沒有一種方式能夠既不用eject項目又不用建立本身的 scripts 包呢?答案是確定的,react-app-rewired 是 react 社區開源的一個修改 CRA 配置的工具。

在 CRA 建立的項目中安裝了react-app-rewired後,能夠經過建立一個config-overrides.js文件來對 webpack 配置進行擴展。

1
2 3 4 5 6 
/* config-overrides.js */  module.exports = function override(config, env) {  //do stuff with the webpack config...  return config; } 

override方法的第一個參數config就是 webpack 的配置,在這個方法裏面,咱們能夠對 config 進行擴展,好比安裝其餘 loader 或者 plugins,最後再將這個 config 對象返回回去。

最後再修改package.json中的腳本命令,修改內容請見這裏

scripts 包 + override 組合

雖然react-app-rewired的方式已經能夠很方便地修改 webpack 的配置了,但其實咱們也能夠在自定義的 script 包中實現相似的功能。

react-app-rewired的源碼中能夠看到它核心的包也叫 react-app-rewired,裏面從新覆蓋了react-scripts中的幾個腳本文件,包括build.jsstart.jstest.js

具體過程是怎樣的呢?以build.js爲例:

  • 先獲取 webpack 的基本配置,而後再調用config-overrides.js(就是在根目錄中新增的那個文件)中的override方法,將原先的 webpack 對象做爲參數傳入,
  • 再取得通過修改後的 webpack 配置對象
  • 最後再調用react-scripts中的build.js腳本,傳入修改後的 webpack 對象來執行命令,

具體源碼以下:

1
2 3 4 5 6 7 8 9 10 
const overrides = require('../config-overrides'); const webpackConfigPath = paths.scriptVersion + "/config/webpack.config.prod";  // load original config const webpackConfig = require(webpackConfigPath); // override config in memory require.cache[require.resolve(webpackConfigPath)].exports =  overrides.webpack(webpackConfig, process.env.NODE_ENV); // run original script require(paths.scriptVersion + '/scripts/build'); 

知道了原理以後,咱們也能夠修改自定義 scripts 包的腳本文件,仍是以build.js爲例,在獲取基本 webpack 配置對象和使用 webpack 對象之間加入如下代碼:

1
2 3 4 
// override config const override = require(paths.configOverrides); const overrideFn = override || ((config, env) => config); const overrideConfig = overrideFn(config, process.env.NODE_ENV); 

overrideConfig就是修改後的 webpack 對象,最後修改調用了 webpack 對象的代碼,將原來的 webpack 對象替換成修改後的 webpack 對象。

總結

CRA 是一個很是棒的 React 腳手架工具,但你若是不知足於它的 webpack 默認配置,你能夠經過上述幾種方式來擴展本身項目的 webpack 配置,這幾種方式各有優缺點,能夠結合具體的使用場景來選擇合適本身的方式。

相關文章
相關標籤/搜索