1. 程式人生 > >create-react-app如何開發多頁應用

create-react-app如何開發多頁應用

用構建工具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配置支援多入口

  1. 修改config/paths.js檔案
    安裝globby yarn add globby
//遍歷public下目錄下的html檔案生成arry
const globby = require('globby');
const htmlArray = globby.sync([path.join(resolveApp('public'), '/*.html')]);  


//module.exports 裡面增加
htmlArray

  1. 修改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,
  1. 修改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,
 // });
}