博客 / 詳情

返回

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

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

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

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

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

1、eject 彈出配置

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

npm run eject

2、更改paths.js

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

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

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

3、更改webpack.config.js

更改entry入口

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

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加上對應包的chunkName

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 這樣的錯誤

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

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,
    };
  }
}),

4、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' },
  ]
},

5、更改

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

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.