Create React App 簡介及如何拓展webpack配置

Create React App(如下簡稱 CRA)是一個官方支持的建立 React 單頁應用的腳手架,它提供了一個零配置的現代構建設置,將一些複雜工具(好比 webpack, Babel)的配置封裝了起來,讓使用者不用關心這些工具的具體配置,從而下降了工具的使用難度。css

建立方法

npx: npx 來自 npm 5.2+ 或更高版本html

npx create-react-app my-app

npm: npm init <initializer> 在 npm 6+ 中可用node

npm init react-app my-app

Yarn: yarn create 在 Yarn 0.25+ 中可用react

yarn create react-app my-app

Scripts

在新建立的項目中,能夠運行一些內置命令:webpack

npm startyarn startgit

在開發模式下運行應用程序, 默認在瀏覽器打開http://localhost:3000。若是更改代碼,頁面將自動從新加載。github

npm testyarn testweb

以交互模式運行測試程序。 默認狀況下,運行與上次提交後更改的文件相關的測試。npm

npm run buildyarn buildjson

將生產環境的應用程序構建到 build 目錄。 它能將 React 正確地打包爲生產模式中並優化構建以得到最佳性能。構建將被壓縮,文件名中將包含哈希。

npm run eject

注意:這是單向操做。一旦 eject ,就不能回去了!

執行完這個命令後會將封裝在 CRA 中的配置所有反編譯到當前項目,這樣開發者徹底取得 webpack 文件的控制權,能夠自定義修改webpack打包配置。

文件結構

建立後,項目文件結構以下所示:

my-app
  node_modules
  public
    favicon.ico
    index.html // 頁面模板
    manifest.json
  src
    App.css
    App.js
    App.test.js
    index.css
    index.js // 項目入口
    logo.svg
    reportWebVitals.js
    setupTests.js
  .gitignore
  package.json
  README.md
  yarn.lock
  • 爲了加快從新構建的速度,Webpack 只處理 src 中的文件。 你須要將任何 JS 和 CSS 文件放在 src,不然 Webpack 將發現不了它們。
  • 只能在 public/index.html 中使用 public 中的文件。
  • manifest.js: 目的是將Web應用程序安裝到設備的主屏幕,爲用戶提供更快的訪問和更豐富的體驗。

項目升級

Create React App 分爲兩個包:

  • create-react-app 是一個全局命令行實用程序,可用於建立新項目。
  • react-scripts 包含Create React App的腳本與配置

當你運行 create-react-app 時,它始終使用最新版本的 react-scripts 建立項目,新建立的應用會得到全部新功能和改進。

CRA 將全部新特性委託給 react-scripts , 只須要更新react-scripts, 不須要更新 create-react-app 就能夠升級CRA 的特性。好比用老版本 CRA 建立了一個項目,這個項目不具有 PWA 功能,但只要項目升級了react-scripts包的版本就能夠具有 PWA 的功能,項目自己的代碼不須要作任何修改。

如何擴展 Create React App 的 Webpack 配置

Create React App已經封裝了webpack 配置,若是想對 webpack 配置作一些修改,這個時候應該怎麼辦呢?CRA提供瞭如下幾種方式來修改 webpack 的配置:

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

eject 命令

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

{
  ...
  "scripts": {
    "eject": "react-scripts eject"
  },
  ...
}

執行yarn eject後會將封裝在 CRA 中的配置所有複製到當前項目。eject 後項目根目錄下會新增 config與scripts 文件夾,修改package.json與yarn.lock文件。

config
  jest
  env.js
  getHttpsConfig.js
  modules.js
  paths.js
  pnpTs.js
  webpack.config.js
  webpackDevServer.config.js
scripts
  build.js
  start.js
  test.js

若是使用了eject命令,雖然擴展了 webpack 配置,可是再也享受不到 CRA 升級帶來的好處了。由於react-scripts已是以文件的形式存在於你的項目,而不是以包的形式,因此沒法對其升級。

替換 react-scripts 包

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

// 默認方式
$ create-react-app my-app

// 自定義 scripts 包方式
$ create-react-app my-app --scripts-version 自定義包

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

  • 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

react-app-rewired 是 react 社區開源的一個修改 CRA 配置的工具,這種方式讓開發者既不用eject項目也不用本身建立 scripts 包就能夠拓展webpack。

如何使用 react-app-rewired

1.在 CRA 建立的項目中安裝react-app-rewired

npm install react-app-rewired --save-dev

2.在項目根目錄下建立config-overrides.js 文件(支持自定義文件路徑)

/* config-overrides.js */

module.exports = function override(config, env) {
  // 參數中的 config 就是默認的 webpack config
  
  // 對 config 進行任意修改
  config.mode = 'development';
  
  // 必定要把新的 config 返回
  return config;
}

config-overriders.js 導出的是一個函數,這個函數的簽名是 const override = (oldWebpackConfig, env) => newWebpackConfig

3.修改scripts命令

/* package.json */

"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
    "eject": "react-scripts eject"
}
config-overrides.js 文件

設置自定義路徑 經過package.json 的config-overrides-path設置自定義路徑:

/* package.json */
{
  ...
  "config-overrides-path": "src/app", // src/app/config-overrides.js
  ...
}

默認狀況下,config-overrides.js文件導出一個函數,用於自定義Webpack配置以在開發或生產模式下編譯React應用。 也能夠改成此文件導出一個對象,該對象最多包含三個字段,每一個字段都是一個函數。

module.exports = {
  // The Webpack config
  webpack: function(config, env) {
    // ...add your webpack config
    return config;
  },
  // The Jest config
  jest: function(config) {
    // ...add your jest config customisation...
    return config;
  },
  // create a webpack dev server
  devServer: function(configFunction) {
    return function(proxy, allowedHost) {
      const config = configFunction(proxy, allowedHost);
      const fs = require('fs');
      config.https = {
        key: fs.readFileSync(process.env.REACT_HTTPS_KEY, 'utf8'),
        cert: fs.readFileSync(process.env.REACT_HTTPS_CERT, 'utf8'),
        ca: fs.readFileSync(process.env.REACT_HTTPS_CA, 'utf8'),
        passphrase: process.env.REACT_HTTPS_PASS
      };
      return config;
    };
  },
  paths: function(paths, env) {
    // ...add your paths config
    return paths;
  },
}
實現原理

編譯時,react-app-rewired 會先取到 create-react-app 生成的默認的 webpack config,而後調用 override(config) 方法,對 config 進行修改,獲得新的 webpack config。webpack 最終會使用這個新的 config 進行打包。

流程大體以下:

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 包 + override 組合

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

build.js爲例,在獲取基本 webpack 配置對象和使用 webpack 對象之間加入如下代碼:

// 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 對象。

相關文章
相關標籤/搜索