更新時間:2019-01-11
版本信息:CRA v2.1.1 + Webpack v4.19.1 + react-app-rewired v1.6.2
一、前言
爲什麼要進行多頁面配置
在使用 React 進行開發的過程中,我們通常會使用 creat-react-app 腳手架命令來搭建項目,避免要自己配置 webpack,提高我們的開發效率。但是使用 creat-react-app 搭建的項目是單頁面應用,如果我們是做中後臺管理頁面或 SPA,這樣是滿足要求的,但如果項目有多入口的需求,就需要我們進行一些配置方面的修改。
一般現在有兩種方式將腳手架搭建的項目修改爲多入口編譯:
- 執行
npm eject
命令,彈出配置文件,進行自定義配置。請參見:React-CRA 多頁面配置(npm eject)。 - 使用 react-app-rewired 修改腳手架配置,在項目中安裝 react-app-rewired 後,可以通過創建一個 config-overrides.js 文件來對 webpack 配置進行擴展。
本文對第 2 種方法給出具體配置方案,第 1 種方案詳見:React-CRA 多頁面配置(npm eject)。在閱讀本文之前,可以先了解一下第 1 種方案,有助於更好的理解本文內容。
webpack 基礎
本文對 React 多頁面應用配置的探討是基於使用 create-react-app 腳手架命令構建的項目,並不是 webpack 多頁面配置教程。但上述兩種方案都應該具有一定的 webpack 的基礎,實際上當你決定要改造或增強項目的構建打包配置的時候,你應該先對 webpack 進行一定的瞭解。
如果你之前使用 webpack v3.x 版本,這裏附上 webpack v4.0.0 更新日誌 以及 webpack4升級完全指南。
方案說明
通過使用 react-app-rewired 可以修改腳手架配置,從而實現擴展 webpack 配置,如增加對 less 文件的支持、增加 antd 組件的按需加載、處理 html 文檔中的圖片路徑問題等,甚至可以將單頁面入口編譯修改爲多頁面入口編譯的方式。
但是需要說明的是,我們可以通過 react-app-rewired 在不暴露配置文件的情況下達到擴展項目配置的目的,但並不建議使用這種方式進行多頁面入口編譯的配置,雖然本文主要就是介紹這種方案。本文的意義更多的是記錄對這種方案的嘗試,如果真的需要進行多頁面配置,最好還是使用 npm eject
暴露配置文件的方式。
主要原因是,通過 react-app-rewired 來實現多頁面配置,是需要對腳手架原來的配置具有一定了解的,相較於 npm eject
暴露配置文件的方式來說,這種方式是不太具有透明度的,後面維護的難度較大。本文方案完成的基礎是,我之前已經通過 npm eject
這種方式改造過一次多頁面的配置,相當於說我已經拆過這個箱子了,我基本上了解了這個箱子裏有什麼,因此我在配置這個方案的過程中其實是對照着 npm eject
這個方案中的配置文件來逐步進行的。
版本的變動
使用 CRA 腳手架命令生成的項目免去了我們自己配置 webpack 的麻煩,其內置的各種配置所需要的插件和依賴包的版本都是確定的,是經過了檢驗的成熟配置,不會因爲其中某個依賴包版本的問題造成構建出錯。但當我們決定要自己動手配置 webpack 的時候,就意味着我們要自己根據需要安裝一些 plugin 或 npm 依賴包,而這些插件和依賴包的版本可能不適用於當前 CRA 的版本,從而造成構建過程中出現一些不可預期的錯誤。
因此,我們需要查看 CRA 腳手架項目的 package.json 文件,對於其中已經列出的 dependencies 依賴包,我們不應該改變這些依賴包的版本,而對於未列出的 npm 包,我們在使用的過程中需要逐個驗證,不要一次性安裝很多個 npm 包,否則執行構建命令的時候如果出錯就會很難排查,最好是根據我們需要的功能逐個的安裝相應的 npm 包,確定沒有問題,再進行下一個功能的擴展。
正是由於版本的變動會對配置產生很大的影響,因此當我們確定了一個配置方案之後,不要再輕易去改動其中涉及到的 npm 包的版本,通過 package-lock.json 文件鎖定版本,防止配置方案錯亂。
另外,在本文編輯的時候,CRA 的最新版本爲 v2.1.2,這個版本的 CRA 生成的項目,當前版本的 react-app-rewired v1.6.2 已經無法使用,具體信息可以參見 CRA >=2.1.2 breaking issue 2.1.2。至少在本文編輯的時候(2019.01.05),是無法適用於 CRA >=2.1.2 版本的,因此本文方案是基於最後一個可以適用的 CRA v2.1.1 版本來做的,package.json 文件中其他的 version 信息會附在方案後面。
2019-01-11 補充:上面提到的版本基本都是指 package.json 文件中列出的依賴包的版本,但是嚴格來講還應包含一些構建配置中使用的 node.js 工具包,比如 globby、dir-glob等,這些工具包的版本更新也有可能會造成構建出錯。這種情況的出現往往是無法預期的,它們造成的影響一般比較廣泛,而不僅僅是出現在我們方案配置的過程中,這種錯誤基本上都會在 Github 上有相應的 issue 以及解決方法或修復措施,本文中也列出了遇到的一個這種類型的錯誤,詳見 四、錯誤排查 章節中的 其他錯誤 一節。
二、準備工作
創建一個 CRA v2.1.1 項目
我們的配置方案是基於 CRA v2.1.1 腳手架項目進行改造的,因此首先我們要先創建一個 CRA 項目,詳見官方文檔:Create React App。
但是這樣創建出來的項目默認是最新版本的 CRA 項目,我們在上文中已經說明,我們的配置方案是要求特定版本的 CRA 項目的,那麼如何創建特定的 CRA v2.1.1 版本項目?
CRA 項目版本的核心其實就是 react-scripts 的版本,我們可以先創建一個最新版本的腳手架項目,然後更改爲 v2.1.1 版本,具體如下:
- 創建一個最新版本的 CRA 項目,參見官方文檔:Create React App;
- 刪除 node_modules 文件夾,如果有 package-lock.json 文件或 yarn.lock 文件,也要一併刪除,否則重新安裝 node_modules 依賴包仍然會被鎖定爲原來的版本;
-
修改 package.json 文件,重新指定 react-scripts 的版本:
"dependencies": { - "react": "^16.7.0", + "react": "^16.6.3", - "react-dom": "^16.7.0", + "react-dom": "^16.6.3", - "react-scripts": "2.1.3" + "react-scripts": "2.1.1" }
- 執行
yarn install
或npm install
重新安裝項目依賴。
至此,我們已經創建了一個 CRA v2.1.1 項目,可以正式開始多頁面入口編譯的改造了。
react-app-rewired 的用法
首先要學習 react-app-rewired 的用法,參照官方文檔:How to rewire your create-react-app project。
主要是三點:
- 安裝 react-app-rewired
- 創建一個 config-overrides.js 文件
- 修改 package.json 文件中的腳本命令
查看 CRA 項目原有的配置文件
上面我們提到在進行多頁面配置之前,需要對腳手架原有的配置文件具有一定了解,那麼如何查看原有的配置文件?
-
方法1:將使用 CRA 腳手架命令生成的項目拷貝一份,執行
npm eject
暴露配置文件,eject 之後文件組織結構如下:my-app ├── config │ ├── jest │ ├── env.js │ ├── paths.js │ ├── webpack.config.dev.js │ ├── webpack.config.prod.js │ └── webpackDevServer.config.js ├── node_modules ├── public ├── scripts │ ├── build.js │ ├── start.js │ └── test.js ├── package.json ├── README.md └── src
其中 config 文件夾下就是腳手架原有的配置文件。
- 方法2:使用 CRA 腳手架命令生成項目,在 my-app/node_modules/react-scripts/config 路徑下可以看到原有的配置文件
- 方法3:在 config-overrides.js 文件中將 webpack 配置對象輸出在控制檯,查看其結構
推薦使用第 1 種方式,便於我們在配置過程中查看和操作,第 3 種方式作爲一種輔助手段,主要是用於改造過程中的調試和驗證配置對象的改造結果的。
項目文件組織結構
在開始進行多入口配置之前,需要先明確項目的文件組織結構,這關係到我們如何準確獲取所有的入口文件,這裏不再詳述,請參見React-CRA 多頁面配置(npm eject)中的項目文件組織結構一節。
三、具體方案
- 安裝 react-app-rewired,創建 config-overrides.js 文件,修改 package.json 文件中的腳本命令。詳見官方文檔 How to rewire your create-react-app project。
執行
yarn start
命令,查看 http://localhost:3000,確保安裝 react-app-rewired 操作沒有問題。 -
修改文件組織結構。這裏不再詳述,參見上文 項目文件組織結構 一節。
CRA項目原文件組織結構爲:my-app ├── README.md ├── node_modules ├── package.json ├── config-overrides.js // 安裝 react-app-rewired 時創建的 ├── .gitignore ├── public │ ├── favicon.ico │ ├── index.html │ └── manifest.json └── src ├── App.css ├── App.js ├── App.test.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js
修改爲多頁面入口編譯的文件組織結構:
// 本方案示例項目有兩個頁面 index.html & admin.html // 這裏給出的文件組織結構是配置完成後的完整結構, 有些文件(如 src/setupProxy.js)的具體作用後面會給出說明 my-app ├── README.md ├── node_modules ├── package.json ├── config-overrides.js // 安裝 react-app-rewired 時創建的 ├── .gitignore ├── public │ ├── favicon.ico │ ├── index.html // 作爲所有頁面的 html 模板文件 │ └── manifest.json └── src ├── index.js // 空白文件, 爲了避免構建報錯, 詳見下文 ├── setupProxy.js // proxy 設置, 詳見下文(在當前操作步驟中可以缺失) ├── index // index.html 頁面對應的文件夾 │ ├── App.less │ ├── App.js │ ├── App.test.js │ ├── index.less // 使用 less 編寫樣式文件 │ ├── index.js │ ├── logo.svg │ └── serviceWorker.js └── admin // admin.html 頁面對應的文件夾 ├── App.less ├── App.js ├── App.test.js ├── index.less // 使用 less 編寫樣式文件 ├── index.js ├── logo.svg └── serviceWorker.js
執行
yarn start
命令,查看 http://localhost:3000/index.html 和 http://localhost:3000/admin.html,確保修改文件組織結構操作沒有問題。這個示例項目是以 /my-app/public/index.html 作爲所有頁面的 html 模板文件的,當然也可以分別指定不同的 html 模板文件,這是根據項目需要和項目文件組織結構決定的。在這個示例項目中,由於作爲模板的 html 文件只需要有個根元素即可,因此將其作爲所有入口的 html 模板文件。這樣的話,每個頁面的 <title></title> 就需要在各自頁面中分別指定,一般可以在頁面掛載之後進行操作,比如:
class App extends Component { componentDidMount() { document.title = 'xxx'; } render() { return ( ... ); } }
-
修改 config-overrides.js 文件,進行具體配置。實際上我們之後所有的操作都是在這個文件中進行的。
我們的測試方案是一個使用了 Ant Design、Redux、Less、Echarts 的多頁面項目,需要達到以下要求:- 指定頁面的多入口文件路徑以及入口文件對應的 html 模板
- 實現 antd 組件的按需加載
- 增加對 less 文件的支持
- 更改輸出的文件名
- 增加對 html 文檔中圖片路徑的處理
- 更改代碼切割的配置
- 設置別名路徑
上述每一個功能的實現,都需要執行 yarn start
或 yarn build
進行驗證,確保操作成功後再進行下一項的配置。這裏不再逐步說明配置的步驟,詳見下面的代碼及註釋。
最終 config-overrides.js 文件內容如下:
/* config-overrides.js */
/*
* @Author: mzhang.eric
* @Last Modified time: 2019-01-10 18:37:17
* @Description: 使用 react-app-rewired 擴展和改造 CRA v2.1.1 項目, 基於 webpack v4.19.1 + react-app-rewired v1.6.2 版本
*/
const rewireLess = require('react-app-rewire-less');
const { injectBabelPlugin, paths } = require('react-app-rewired');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const fs = require('fs');
const globby = require('globby');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = function override(config, env) {
// 使用 babel-plugin-import 按需加載組件
config = injectBabelPlugin(
['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }],
config,
);
// 增加 less 支持
config = rewireLess.withLoaderOptions({
// 解決報錯: Inline JavaScript is not enabled. Is it set in your options?
javascriptEnabled: true,
})(config, env);
// 入口文件路徑
// const entriesPath = globby.sync([resolveApp('src') + '/*/index.js']);
const entriesPath = globby.sync([resolveApp('src') + '/*/index.js'], {cwd: process.cwd()});
paths.entriesPath = entriesPath;
// 獲取指定路徑下的入口文件
function getEntries(){
const entries = {};
const files = paths.entriesPath;
files.forEach(filePath => {
let tmp = filePath.split('/');
let name = tmp[tmp.length - 2];
if(env === 'production'){
entries[name] = [
filePath,
];
} else {
entries[name] = [
require.resolve('react-dev-utils/webpackHotDevClient'),
filePath,
];
}
});
return entries;
}
// 入口文件對象
const entries = getEntries();
// 配置 HtmlWebpackPlugin 插件, 指定入口文件生成對應的 html 文件
let htmlPlugin;
if(env === 'production'){
htmlPlugin = Object.keys(entries).map(item => {
return new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
filename: item + '.html',
chunks: [item],
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
});
});
} else {
htmlPlugin = Object.keys(entries).map(item => {
return new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
filename: item + '.html',
chunks: [item],
});
});
}
if (env === 'production') {
for (let i = 0; i < config.plugins.length; i++) {
let item = config.plugins[i];
// 更改輸出的樣式文件名
if (item.constructor.toString().indexOf('class MiniCssExtractPlugin') > -1) {
item.options.filename = 'static/css/[name].css?_v=[contenthash:8]';
item.options.chunkFilename = 'static/css/[name].chunk.css?_v=[contenthash:8]';
}
// SWPrecacheWebpackPlugin: 使用 service workers 緩存項目依賴
if(item.constructor.toString().indexOf('function GenerateSW') > -1){
// 更改輸出的文件名
item.config.precacheManifestFilename = 'precache-manifest.js?_v=[manifestHash]';
}
}
// 更改生產模式輸出的文件名
config.output.filename = 'static/js/[name].js?_v=[chunkhash:8]';
config.output.chunkFilename = 'static/js/[name].chunk.js?_v=[chunkhash:8]';
} else {
// 更改開發模式輸出的文件名
config.output.filename = 'static/js/[name].js';
config.output.chunkFilename = 'static/js/[name].chunk.js';
}
// 修改入口
config.entry = entries;
// 修改 HtmlWebpackPlugin 插件
for (let i = 0; i < config.plugins.length; i++) {
let item = config.plugins[i];
if (item.constructor.toString().indexOf('class HtmlWebpackPlugin') > -1) {
config.plugins.splice(i, 1);
}
}
config.plugins.push(...htmlPlugin);
// 分析打包內容
// config.plugins.push(new BundleAnalyzerPlugin());
// 設置別名路徑
config.resolve.alias = {
...config.resolve.alias,
'@src': paths.appSrc, // 在使用中, 有些 Eslint 規則會報錯, 禁用這部分代碼的 Eslint 檢測即可
};
// 處理 html 文檔中圖片路徑問題
config.module.rules[2].oneOf.push({
test: /\.html$/,
loader: 'html-withimg-loader'
});
// 修改 build/static/media/ 路徑下的文件名
for (let i = 0; i < config.module.rules[2].oneOf.length; i++) {
const item = config.module.rules[2].oneOf[i];
if(!item.options || !item.options.name){
continue;
}
let str = item.options.name.toString();
if(str.indexOf('static/media/[name].[hash:8].[ext]') > -1){
item.options.name = 'static/media/[name].[ext]?_v=[hash:8]';
}
}
// 修改代碼切割配置
// 參見 webpack 文檔:https://webpack.js.org/plugins/split-chunks-plugin/#optimization-splitchunks
config.optimization = {
splitChunks: {
// 將所有入口點共同使用到的、次數超過 2 次的模塊,創建爲一個名爲 commons 的代碼塊
// 這種配置方式可能會增大初始的捆綁包,比如有些公共模塊在首頁其實並未用到,但也會打包進來,會降低首頁的加載性能
// 建議將非必需模塊使用 import() 的方式動態加載,提升頁面的加載速度
// cacheGroups: {
// commons: {
// name: 'commons',
// chunks: 'initial',
// minChunks: 2
// }
// }
// 將所有使用到的 node_modules 中的模塊包打包爲 vendors 代碼塊。(不推薦)
// 這種方式可能會產生一個包含所有外部依賴包的較大代碼塊,建議只包含核心框架和工具函數代碼,其他依賴項動態加載
// cacheGroups: {
// commons: {
// test: /[\\/]node_modules[\\/]/,
// name: 'vendors',
// chunks: 'all'
// }
// }
cacheGroups: {
// 通過正則匹配,將 react react-dom echarts 等公共模塊拆分爲 vendor,可以通過 BundleAnalyzerPlugin 幫助確定拆分哪些模塊包
vendor: {
test: /[\\/]node_modules[\\/](react|react-dom|echarts-for-react)[\\/]/,
name: 'vendor',
chunks: 'all', // all, async, and initial
},
// 將 css|less 文件合併成一個文件, mini-css-extract-plugin 的用法請參見文檔:https://www.npmjs.com/package/mini-css-extract-plugin
// MiniCssExtractPlugin 會將動態 import 引入的模塊的樣式文件也分離出去,將這些樣式文件合併成一個文件可以提高渲染速度
// 其實如果可以不使用 mini-css-extract-plugin 這個插件,即不分離樣式文件,可能更適合本方案,但是我沒有找到方法去除這個插件
styles: {
name: 'styles',
test: /\.css|less$/,
chunks: 'all', // merge all the css chunk to one file
enforce: true
}
},
},
};
return config;
};
四、錯誤排查
這裏對方案形成過程中遇到的錯誤進行記錄,這些錯誤有些是配置過程中必定會出現的,是需要我們進行改造的,也有些錯誤可能是操作不當主觀造成的。
客觀錯誤
這類錯誤是進行多頁面入口編譯改造過程中必定會遇到的,有些是由於項目文件組織結構的改變造成的,也有些是爲了擴展項目配置而使用了源 CRA 腳手架項目未提供的 npm 包造成的,前者會出現哪些錯誤我們是可以明確知道的,後者相對來說是不確切的,但大多都是版本不適用造成的。
-
Could not find a required file.
Could not find a required file.
Name: index.js
Searched in: C:xxxxxxmy-appsrc錯誤描述:通過 create-react-app 腳手架搭建的項目以 /src/index.js 作爲應用入口,當執行構建腳本時如果檢測到缺失了這個必要文件,node 進程會退出。但是在我們進行多頁面入口改造的時候,src 直接路徑下沒有 index.js 文件,根據我們的文件組織結構,index.js 文件存在於每個獨立頁面的子文件夾下,如
/src/index/index.js
/src/admin/index.js
。
解決方法:在 src 直接路徑下創建一個空的 index.js 文件。 -
Inline JavaScript is not enabled. Is it set in your options?
// https://github.com/ant-design...
.bezierEasingMixin();^ Inline JavaScript is not enabled. Is it set in your options?
in C:xxxsrcmy-appnode_modulesantdesstylecolorbezierEasing.less (line 110, column 0)錯誤描述:當我們使用了 antd 組件的時候,構建報錯,需要允許 less 文件中 js 的執行。
解決方法:在 config-overrides.js 文件中增加 less 文件支持時,設置 javascriptEnabled 爲 true。module.exports = function override(config, env) { ... // 增加 less 支持 config = rewireLess.withLoaderOptions({ // 解決報錯: Inline JavaScript is not enabled. Is it set in your options? javascriptEnabled: true, })(config, env); ... return config; };
-
Failed to load resource: net::ERR_FILE_NOT_FOUND(build 版本)
錯誤描述:執行
yarn build
或npm run build
構建生產版本時,構建出的頁面未能正確加載樣式和腳本文件,chrome 檢查工具報路徑錯誤。
解決方法:修改 package.json 文件,指定 homepage 字段的值,本項目這裏指定爲相對路徑。"homepage": "./",
-
When specified, "proxy" in package.json must be a string.
When specified, "proxy" in package.json must be a string.
Instead, the type of "proxy" was "object".
Either remove "proxy" from package.json, or make it a string.錯誤描述:我們在開發過程中一般會在 package.json 文件中配置 proxy 代理服務器,但是在 CRA 2.x 升級以後對 proxy 的設置做了修改,具體請參見官方升級文檔:Move advanced proxy configuration to src/setupProxy.js
解決方法:移除 package.json 文件中有關 proxy 的設置,使用 http-proxy-middleware,在 src 目錄下創建 setupProxy.js 文件。詳細方法請參見上述文檔。
主觀錯誤
這類錯誤應該是可以避免的,但是在配置過程中可能會由於開發人員的不當操作造成出錯,最主要的就是安裝了錯誤版本的 plugin 或 npm 包,我們上面已經說過,對於項目原本的配置中在 package.json 文件中已經列出的 plugin 和 npm 包,不要再重複進行安裝,否則可能重新安裝的 plugin 或 npm 包版本是不適用的,從而造成出錯。
例如,CRA v2.1.1 腳手架項目原有的 html-webpack-plugin 版本是 v4.0.0-alpha.2,是不需要再另外進行安裝的。如果此時開發人員自己執行了 yarn add html-webpack-plugin
,從而將 html-webpack-plugin 的版本更換爲了 v3.2.0,這就會造成構建報錯:URIError: Failed to decode param '/%PUBLIC_URL%/favicon.ico'
URIError: Failed to decode param '/%PUBLIC_URL%/manifest.json'
,其他主觀錯誤類似。
-
html-webpack-plugin 版本錯誤
URIError: Failed to decode param '/%PUBLIC_URL%/favicon.ico'
URIError: Failed to decode param '/%PUBLIC_URL%/manifest.json'錯誤描述:在執行
yarn start
構建命令時報錯,頁面空白。
解決方法:html-webpack-plugin 版本錯誤,在本文的配置方案中,應當使用"html-webpack-plugin": "4.0.0-alpha.2",
版本。 - TypeError: Cannot read property 'state' of undefined(頁面報錯)
錯誤描述:編譯構建過程沒有報錯,但頁面報錯:TypeError: Cannot read property 'state' of undefined。
解決方法:redux 版本錯誤,在本文的配置方案中,應當使用 redux <=3.7.2 版本。
其他錯誤
我們在上文 版本的變動 一節的補充中已經對此有所提及,這類錯誤主要是由 node.js 工具包版本的升級造成的,這些錯誤基本都是不可預期的,也無法在這裏全部涵蓋,只能就當前遇到的問題進行簡要記錄,可能隨着時間的推移,還會出現其他的類似問題,也可能這些錯誤已經在後續的版本中被修復了,因此請勿糾結於這裏記錄的錯誤,如果遇到了這類錯誤,就查閱資料進行修正,如果沒有遇到,則無須理會。
-
TypeError: Expected
cwd
to be of typestring
but received typeundefined
C:xxxmy-appnode_modulesdir-globindex.js:59
throw new TypeError(Expected \
cwd` to be of type `string` but received type `${typeof opts.cwd}``);
TypeError: Expectedcwd
to be of typestring
but received typeundefined
錯誤描述:本文的寫作開始於 2019-01-05,在 2019-01-11 重新審覈本文方案的時候,遇到了這個錯誤,主要是由於 dir-glob 版本的升級造成的,我們在配置腳本中使用了 globby 的 sync 方法,dir-glob 版本升級之後,這個方法的調用會使得 dir-glob 拋出上述錯誤。詳細信息參見:Broken build do to major change from 2.0 to 2.2 以及 globby will pass opts.cwd = undefined to dir-glob, which leads to TypeError.。
解決方法:這裏給出的解決方法是限定於當前時間的,因爲在本文編輯的時候(2019-01-11)這個 issue 還沒有給出最終的解決方案,個人覺得可能會由 globby 進行修復。
/* config-overrides.js */
// 修改獲取入口文件路徑的代碼
- const entriesPath = globby.sync([resolveApp('src') + '/*/index.js']);
+ const entriesPath = globby.sync([resolveApp('src') + '/*/index.js'], {cwd: process.cwd()});
五、package.json 信息
本文的多頁面配置方案是基於 CRA 腳手架項目的,項目的依賴包信息會包含在兩個 package.json 文件中,其中腳手架自帶的配置信息位於 /my-app/node_modules/react-scripts/package.json
文件中,而我們根據項目需要自己增加的配置信息在 /my-app/package.json
文件中,這裏將本方案項目配置信息附錄如下:
/* package.json */
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"antd": "^3.12.1",
"babel-plugin-import": "^1.11.0",
"echarts": "^4.2.0-rc.2",
"echarts-for-react": "^2.0.15-beta.0",
"html-withimg-loader": "^0.1.16",
"http-proxy-middleware": "^0.19.1",
"react": "^16.6.3",
"react-app-rewire-less": "^2.1.3",
"react-app-rewired": "^1.6.2",
"react-dom": "^16.6.3",
"react-intl": "^2.7.2",
"react-lazyload": "^2.3.0",
"react-loadable": "^5.5.0",
"react-redux": "^6.0.0",
"react-scripts": "2.1.1",
"redux": "3.7.2",
"redux-promise-middleware": "^5.1.1",
"webpack-bundle-analyzer": "^3.0.3"
},
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --env=jsdom",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"homepage": "./"
}