不想eject,還咋修改create-react-app的配置?

胡哥有話說發表於2021-04-12

一、先拋問題

許多剛開始接觸create-react-app框架的同學,不免都會有個疑問:如何在不執行eject操作的同時,修改create-react-app的配置。今天胡哥就來帶大家一起來看看這個問題~

二、為啥不建議執行eject

1. 執行eject產生了什麼變化?

create-react-app框架本身將webpackbabel的相關配置封裝在了react-scripts中, 執行yarn eject後,會將webpackbabel等配置暴露在config目錄下,同時scripts目錄下會有新的命令檔案更新,package.json檔案中scripts命令同步更新。

2. 執行eject帶來了什麼問題?

首先,執行eject是不可逆的,複雜的webpack等配置由框架本身轉交給使用者自己進行維護了。

其次,在版本迭代時,如果更新了reactreact-scriptseslinttsconfig等依賴,有可能會引起版本依賴的問題,即使我們按錯誤資訊修復了之後,專案還是無法執行

所以我們一般不太建議使用yarn eject的方式暴露create-react-app框架的配置。

三、有需求咋解決

實際開發中,我們還是需要更新webpackbabel的配置,比如:

  • antd的按需載入;

  • 配置css前處理器 - less;

  • 設定alias、externals;

  • 生產環境打包-去除console.log、debugger;

  • 打包結果優化分析;

  • 打包增加進度條提示;

前方高能預警~

藉助react-app-rewiredcustomize-cra來完成配置的擴充套件~

這裡劃重點,記住要考呦~

我們劃分幾個步驟,來一一實現:

  1. 下載安裝依賴

    yarn add react-app-rewired customize-cra -D
    

    胡哥現在使用的版本是 react-app-rewired@^2.1.8 、customize-cra@^1.0.0

  2. 配置package.json的命令

    "scripts": {
    -   "start": "react-scripts start",
    +		"start": "react-app-rewired start",
    -   "build": "react-scripts build",
    +   "build": "react-app-rewired build",
    }
    
  3. 在根目錄下配置config-overrides.js檔案

    module.exports = {}
    

完成了基礎配置後,我們在config-overrides.js中進行詳細配置,解決我們上面的需求問題。

  1. antd的按需載入

    安裝依賴:

    yarn add antd -D
    

    配置

    cosnt { override, fixBabelImports } = require('customize-cra');
    
    module.exports = override(
    	fixBabelImports(
      	"import",
        {
    			"libraryName": "antd",
          "libraryDirectory": "es",
          "style": "css"
        }
      )
    )
    
  2. 配置css前處理器 - less

    為啥在這裡只強調了less呢,因為create-react-app中內建了sass/scss的前處理器,只需要使用時安裝相關的依賴就可以了(執行時,根據提示缺失的包進行安裝即可)。

    yarn add sass -D
    

    接下來我們來less的是如何支援的

    安裝依賴:

    yarn add less less-loader@7.3.0 -D
    

    注意這裡less-loader的版本 less-loader@7.3.0,如果是最新的版本和上面的react-app-rewired和customize-cra版本配合配置時有問題,所以使用了低版本的。

    less-loader的最新版本其實是為了配合webpack@5.0使用的。

    配置

    const { override, addLessLoader } = require('customize-cra');
    
    module.exports = override(
    	addLessLoader({
    		// 這裡可以新增less的其他配置
    		lessOptions: {
       		// 根據自己需要配置即可~
        }
    	})
    );
    
  3. 設定alias、externals;

    const { override, addWebpackAlias } = require('customize-cra');
    const path = require('path');
    
    module.exports = override(
      // alias
    	addWebpackAlias({
        // 載入模組的時候,可以使用“@”符號來進行簡寫啦~
        '@': path.resolve(__dirname, './src/')
      }),
      // externals
      addWebpackExternals({
        // 注意對應的在public/index.html引入jquery的遠端檔案地址
        "jQuery": "jQuery"
      })
    )
    
  4. 生產環境打包-去除console.log、debugger;

    安裝依賴

    yarn add uglifyjs-webpack-plugin -D
    

    配置

    const { override, addWebpackPlugin } = require('customize-cra');
    const  UglifyJsPlugin = require('uglifyjs-webpack-plugin');
    
    module.exports = override(
    	// 注意是production環境啟動該plugin
    	process.env.NODE_ENV === 'production' && addWebpackPlugin(
      	new UglifyJsPlugin({
      		// 開啟打包快取
      		cache: true,
      		// 開啟多執行緒打包
      		parallel: true,
      		uglifyOptions: {
      			// 刪除警告
      			warnings: false,
      			// 壓縮
      			compress: {
      				// 移除console
      				drop_console: true,
      				// 移除debugger
      				drop_debugger: true
      			}
      		}
      	})
      )
    )
    
  5. 打包結果優化分析;

    安裝依賴

    yarn add webpack-bundle-analyzer cross-env -D
    

    cross-env用於配置環境變數

    配置

    // package.json檔案
    "scripts": {
    	"build:analyzer": "cross-env ANALYZER=true react-app-rewired build"
    }
    
    // config-overrides.js
    const { override, addWebpackPlugin } = require('customize-cra');
    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
    
    module.exports = override(
      // 判斷環境變數ANALYZER引數的值
    	process.env.ANALYZER && addWebpackPlugin(new BundleAnalyzerPlugin())
    )
    
  6. 打包增加進度條提示;

    安裝依賴

    yarn add progress-bar-webpack-plugin -D
    
    const { override, addWebpackPlugin } = require('customize-cra');
    const ProgressBarPlugin = require('progress-bar-webpack-plugin');
    
    module.exports = override(
    	addWebpackPlugin(new ProgressBarPlugin())
    )
    

以上就是我們實現幾個需求的配置。我們來看看完整的config-overrides.js檔案。

// config-overrides.js
cosnt { override, fixBabelImports, addWebpackPlugin, addLessLoader, addWebpackAlias, addWebpackExternals } = require('customize-cra');
const path = require('path');
const  UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');

module.exports = override(
	fixBabelImports(
  	"import",
    {
			"libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
    }
  ),
  addLessLoader({
		// 這裡可以新增less的其他配置
		lessOptions: {
   		// 根據自己需要配置即可~
    }
	}),
  // alias
	addWebpackAlias({
    // 載入模組的時候,可以使用“@”符號來進行簡寫啦~
    '@': path.resolve(__dirname, './src/')
  }),
  // externals
  addWebpackExternals({
    // 注意對應的在public/index.html引入jquery的遠端檔案地址
    "jQuery": "jQuery"
  }),
  // 注意是production環境啟動該plugin
	process.env.NODE_ENV === 'production' && addWebpackPlugin(
  	new UglifyJsPlugin({
  		// 開啟打包快取
  		cache: true,
  		// 開啟多執行緒打包
  		parallel: true,
  		uglifyOptions: {
  			// 刪除警告
  			warnings: false,
  			// 壓縮
  			compress: {
  				// 移除console
  				drop_console: true,
  				// 移除debugger
  				drop_debugger: true
  			}
  		}
  	})
  ),
  // 判斷環境變數ANALYZER引數的值
	process.env.ANALYZER && addWebpackPlugin(new BundleAnalyzerPlugin()),
  addWebpackPlugin(new ProgressBarPlugin())
)

後記

以上就是胡哥今天給大家分享的內容,喜歡的小夥伴記得點贊收藏呦,關注胡哥有話說,學習前端不迷路,歡迎多多留言交流...

胡哥有話說,專注於大前端技術領域,分享前端系統架構,框架實現原理,最新最高效的技術實踐!

相關文章