create-react-app如何開發多頁應用
阿新 • • 發佈:2018-11-26
用構建工具create-react-app初始化的專案預設是單頁應用,即整個專案只有一個入口檔案和出口檔案。但是在實際工作中,由於業務的需求,需要多頁面應用,這裡記錄一下如何修改create-react-app的預設配置來滿足多頁應用的開發。
1、在專案下執行yarn run eject(npm run eject)
此命令對專案工程是不可逆的,且只能執行一次。執行後,package.js會被更新,工程下會多出config目錄,其中有webpack有兩個配置檔案,分別對應開發和生產環境(/config/webpack.config.dev.js和/config/webpack.config.prod.js)。這兩個配置檔案都要修改,但略有不同,下面以dev為例說明:
2、修改webpack配置支援多入口
- 修改config/paths.js檔案
安裝globbyyarn add globby
//遍歷public下目錄下的html檔案生成arry
const globby = require('globby');
const htmlArray = globby.sync([path.join(resolveApp('public'), '/*.html')]);
//module.exports 裡面增加
htmlArray
- 修改config/webpack.config.dev.js
要點:
- entry從原來的陣列擴充套件為物件,每個key代表一個入口;
- output中的filename要區分輸出名,可增加[name]變數,這樣會根據entry分別編譯出每個entry的js檔案。
- Webpack配置多入口後,只是編譯出多個入口的JS,同時入口的HTML檔案由HtmlWebpackPlugin生成,也需做配置。
chunks
,指明哪些webpack入口的JS會被注入到這個HTML頁面。如果不配置,則將所有entry的JS檔案都注入HTML。filename
,指明生成的HTML路徑,如果不配置就是build/index.html,admin配置了新的filename,避免與第一個入口的index.html相互覆蓋。
// 遍歷html const entryObj = {}; const htmlPluginsAray = paths.htmlArray.map((v)=> { const fileParse = path.parse(v); entryObj[fileParse.name] = [ require.resolve('./polyfills'), require.resolve('react-dev-utils/webpackHotDevClient'), `${paths.appSrc}/${fileParse.name}.js`,, ] return new HtmlWebpackPlugin({ inject: true, chunks:[fileParse.name], template: `${paths.appPublic}/${fileParse.base}`, filename: fileParse.base }) }); <!--entry 替換為entryObj--> entry:entryObj //出口增加[name] output: { path: paths.appBuild, pathinfo: true, filename: 'static/js/[name].js', chunkFilename: 'static/js/[name].chunk.js', publicPath: publicPath, devtoolModuleFilenameTemplate: info => path.resolve(info.absoluteResourcePath), }, <!--替換htmlplugin內容--> // new HtmlWebpackPlugin({ // inject: true, // chunks: ["index"], // template: paths.appPublic + '/index.html', // }), ...htmlPluginsAray,
- 修改config/webpackDevServer.config.js
上述配置做完後,理論就可以打包出多入口的版本;但使用npm start啟動後,發現無論輸入/index.html還是/admin.html,好像都是和原來/index.html顯示一樣的內容。甚至輸入顯然不存在的/xxxx.html,也顯示為/index.html的內容。
這種現象,初步判斷是HTTP伺服器把所有請求重定向到了/index.html。對於單頁應用,這種做法是沒有問題的(本來就一個頁面);但我們新增的/admin.html就不能訪問了。發現是webpack dev server的問題,還要額外做一些配置,需修改/config/webpackDevServer.config.js。
// 增加
const path = require('path');
const htmlPluginsAray = paths.htmlArray.map((v)=> {
const fileParse = path.parse(v);
return {
from: new RegExp(`^\/${fileParse.base}`), to: `/build/${fileParse.base}`
};
});
<!--historyApiFallback 增加 rewrites-->
rewrites: htmlPluginsAray
3、prod環境
- 修改config/webpack.config.prod.js,同開發環境。
- 修改scripts/build.js
增加複製模組(yarn add cpy
)
//增加
const cpy = require('cpy');
// function copyPublicFolder () 替換
// 原來的方法是複製public下所有的內容,因為增加了多html 所以不再直接複製過去(直接複製會覆蓋html)
const copyPublicFolder = async() => {
await cpy([`${paths.appPublic}/*.*`, `!${paths.appPublic}/*.html`], paths.appBuild);
console.log('copy success!');
// fs.copySync(paths.appPublic, paths.appBuild, {
// dereference: true,
// filter: file => file !== paths.appHtml,
// });
}