将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 看效果

相关文章
相关标签/搜索