將create-react-app單頁面SPA改形成多頁面MPA

將create-react-app單頁面SPA改形成多頁面MPA

React推薦的腳手架 create-react-app (如下簡稱CRA) 默認建立的是單頁面(SPA)應用,若是項目須要使用多頁面(MPA),則須要對腳手架進行更改html

Tips: 如下配置基於 create-react-app@3.4.0 版本react

舉個栗子,好比我要將原來的index.html擴充出來一個iframe.html頁面打包webpack

一、eject 彈出配置

CRA把腳手架相關的配置給隱藏了,須要將配置給彈出git

npm run eject

二、更改paths.js

將須要多頁面化的html和js入口文件添加到paths中,可參考原有appHtml和appIndexJs便可github

module.exports = {
  ...
  appHtml: resolveApp('public/index.html'),
  appIndexJs: resolveModule(resolveApp, 'src/index'),

  // 多頁面添加path部分
  iframeHtml: resolveApp('public/iframe.html'),
  appIframeJs: resolveModule(resolveApp, 'src/iframe/index'), // 路徑可按需指定
    ...
};

三、更改webpack.config.js

更改entry入口

將原有的單entry入口的數組形式,更改爲多chunk入口的對象形式web

entry: {
  index: [
    isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
    paths.appIndexJs,
  ].filter(Boolean),
  iframe: [
    isEnvDevelopment && require.resolve('react-dev-utils/webpackHotDevClient'),
    paths.appIframeJs,
  ].filter(Boolean),
}

更改output的filename

在開發模式,將打包的bundle.js加上對應包的chunkNameshell

filename: isEnvProduction ? 'static/js/[name].[contenthash:8].js' : isEnvDevelopment && 'static/js/[name].bundle.js',

更改webpack的插件 ==HtmlWebpackPlugin== 選項

plugins: [
  // Generates an `index.html` file with the <script> injected.
  new HtmlWebpackPlugin(
    Object.assign(
      {},
      {
        inject: true,
        template: paths.appHtml,
        chunks: ['index']
      },
      ...原代碼
    )
  ),
  new HtmlWebpackPlugin(
    Object.assign(
      {},
      {
        inject: true,
              template: paths.iframeHtml,
        filename: 'iframe.html',
        chunks: ['iframe']
      },
    )
  ),
  // 若是有多個頁面,繼續添加便可
]

更改ManifestPlugin中entrypointFiles

在generate函數中,改造entrypointFiles,否則在編譯時會出現 Cannot read property 'filter' of undefined 這樣的錯誤npm

參考 https://github.com/timarney/r... 這個issue,裏面有討論json

new ManifestPlugin({
  fileName: 'asset-manifest.json',
  publicPath: paths.publicUrlOrPath,
  generate: (seed, files, entrypoints) => {
    const manifestFiles = files.reduce((manifest, file) => {
      manifest[file.name] = file.path;
      return manifest;
    }, seed);
    // 改造entrypointFiles
    const entrypointFiles = {};
    Object.keys(entrypoints).forEach(entrypoint => {
      entrypointFiles[entrypoint] = entrypoints[entrypoint].filter(fileName => !fileName.endsWith('.map'));
    });

    return {
      files: manifestFiles,
      entrypoints: entrypointFiles,
    };
  }
}),

四、webpackDevServer.config.js中更改historyApiFallback選項

使用rewrites選項數組

historyApiFallback: {
  disableDotRule: true,
  // index: paths.publicUrlOrPath,
  // 指明哪些路徑映射到哪一個html
  rewrites: [
    { from: /^\/index.html/, to: '/dist/index.html' },
    { from: /^\/iframe.html/, to: '/dist/iframe.html' },
  ]
},

五、更改

更改完以上配置後,重啓項目便可,訪問 localhost:3000/index.html 和 localhost:3000/iframe.html 看效果

相關文章
相關標籤/搜索