create-react-app 配置多个html入口(CRACO)

2,314 阅读2分钟

问题背景

使用create-react-app会默认创建一个单页应用(SPA: Single Page Application)。即如下图所示:

spa.png

我们希望生成多个html文件,但仍加载同样的js文件。就像这样:

spa.png

之所以要这样做,是为了满足不同场景下SEO的需要。比如我们可以生成en.html、jp.html、zh.html等各异的html入口文件,并在各自的<head>中配置符合相应语言习惯的<metaname="description" />标签和 <title> ,但是它们共享同一套业务逻辑,即引入的为同一个js入口文件index.js

安装CRACO

CRACO(Create React App Configuration Override)是一款可以修改CRA应用的构建配置而无需使用 eject 的工具。

这里是官方的安装教程,不再赘述。

我们为了复刻出多个html入口,只需要做两件事:

  1. 打包生成多个html
  2. 开发环境DevServer配置:重新配置DevServer的入口html

打包生成多个html

在webpack的plugins列表中每添加一个new HtmlWebpackPlugin(),就会相应的生成一个html入口文件。

于是,在 craco.config.js 中添加配置:

const path = require('path')
const fs = require('fs')
const { whenProd } = require('@craco/craco')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const appDirectory = fs.realpathSync(process.cwd())
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath)


// help doc: https://github.com/gsoft-inc/craco
module.exports = {
  webpack: {
    plugins: {
      add: [
        // 另一个html入口
        [
          new HtmlWebpackPlugin(
            Object.assign(
              {},
              {
                inject: true,
                filename: 'another-index.html',
                template: resolveApp('public/another-index.html'), // 需要在 public 文件夹中添加一个 another-index.html 文件作为模版
              },
              whenProd(() => ({
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }))
            )
          ),
          'prepend', // html-webpack-plugin 需要在plugins列表中前置,需要 @craco/craco > v6.3.0
        ],
      ] /* An array of plugins */,
    },
  },
}

开发环境DevServer配置

CRACO 内置了 DevServer , DevServer默认将使用index.html作为入口文件。

可以在 craco.config.js 中添加配置来切换入口:

// help doc: https://github.com/gsoft-inc/craco
module.exports = {
  devServer: {
    // 选择使用html入口( /index.html | /another-index.html )进行调试, 默认为 /index.html
    historyApiFallback: {
      disableDotRule: true,
      index: '/another-index.html',
    },
  },
}

也可以使用 rewrites 实现路由分发:

// help doc: https://github.com/gsoft-inc/craco
module.exports = {
  devServer: {
    // 访问 /one/xxx 和 /another/xxx 会使用不同的入口html
    historyApiFallback: {
      disableDotRule: true,
      historyApiFallback: {
      disableDotRule: true,
      rewrites: [
        { from: /^\/one/, to: '/index.html' },
        { from: /^\/another/, to: '/another-index.html' },
      ],
    },
  },
}