使用Facebook官方脚手架create-react-app创建React应用,默认只能生成一个SPA,入口是index.html。虽然,SPA的页面切换可以使用前台路由框架方便(比如React-Router)实现,这也是SPA的推荐做法;但某些情况下,仍要将页面切分为多个页面,或者在同一个工程开发多个SPA,比如一个是面向客户的SPA,一个是后台管理的SPA。

官方给出的回答是:

Sorry, but Create React App doesn't support this use case.
You can eject and then configure Webpack to have multiple entry points.

查阅create-react-app和webpack官方文档,测试如下方式可行,步骤如下:(假设在默认的index.html外增加一个admin.html)

1. Eject

要实现自定义配置,就需要先Eject出配置(此步骤对create-react-app工程不可逆):npm run eject

运行后,package.js会被更新,工程下会多出config目录,其中有webpack有两个配置文件,分别对应开发和生产环境(/config/webpack.config.dev.js和/config/webpack.config.prod.js)。这两个配置文件都要修改,但略有不同,下面以dev为例说明:

2. 修改webpack配置支持多入口

由于是使用webpack打包,先要让webpack配置出多入口。/config/webpack.config.dev.js默认配置的入口如下:

 entry: [
require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('./polyfills'),
require.resolve('react-error-overlay'),
paths.appIndexJs,
],
output: {
path: paths.appBuild,
pathinfo: true,
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath),
},

根据webpack官方文档MULTIPLE ENTRY POINTS,可做如下修改:

要点是:

  1. entry从原来的数组扩展为对象,每个key代表一个入口。
  2. output中的filename要区分输出名,可增加[name]变量,这样会根据entry分别编译出每个entry的js文件。
  3. 由于path里面没有定义新的entry的路径,图方便可以直接写死为paths.appSrc + "/admin.js"
 entry: {
index: [
require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('./polyfills'),
require.resolve('react-error-overlay'),
paths.appIndexJs,
],
admin:[
require.resolve('react-dev-utils/webpackHotDevClient'),
require.resolve('./polyfills'),
require.resolve('react-error-overlay'),
paths.appSrc + "/admin.js",
]
},
output: {
path: paths.appBuild,
pathinfo: true,
filename: 'static/js/[name].bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath),
},

这样在src文件夹下,就可以再增加一个admin.js的入口,单独写新的SPA。

普通的webpack打包工程,到此即可实现多入口,但create-react-app流程更复杂,需继续修改。

3. 修改HtmlWebpackPlugin生成多个HTML

Webpack配置多入口后,只是编译出多个入口的JS,同时入口的HTML文件由HtmlWebpackPlugin生成,也需做配置。

原配置如下:

new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),

修改为:

    new HtmlWebpackPlugin({
inject: true,
chunks: ["index"],
template: paths.appHtml,
}),
new HtmlWebpackPlugin({
inject: true,
chunks: ["admin"],
template: paths.appHtml,
filename: 'admin.html',
}),

每调一次HtmlWebpackPlugin生成一次HTML页面,故为admin.html多增加一个节点。其他要点如下:

  • chunks,指明哪些webpack入口的JS会被注入到这个HTML页面。如果不配置,则将所有entry的JS文件都注入HTML。
  • filename,指明生成的HTML路径,如果不配置就是build/index.html,admin配置了新的filename,避免与第一个入口的index.html相互覆盖。

另外,template属性也可以修改为不同的HTML模板,这里的例子,我么就和index入口共用HTML模板了。

4. 修改webpack Dev Server配置

上述配置做完后,理论就可以打包出多入口的版本;但使用npm start启动后,发现无论输入/index.html还是/admin.html,好像都是和原来/index.html显示一样的内容。甚至输入显然不存在的/xxxx.html,也显示为/index.html的内容。

这种现象,初步判断是HTTP服务器把所有请求重定向到了/index.html。对于单页应用,这种做法是没有问题的(本来就一个页面);但我们新增的/admin.html就可以访问了。

参考官方文档The historyApiFallback option,发现是webpack dev server的问题,还要额外做一些配置,需修改/config/webpackDevServer.config.js。

原配置如下:

 historyApiFallback: {
disableDotRule: true,
},

修改为:

   historyApiFallback: {
disableDotRule: true,
// 指明哪些路径映射到哪个html
rewrites: [
{ from: /^\/admin.html/, to: '/build/admin.html' },
]
}

增加的rewrites节点,特别对/admin.html这个URL重定向为/build/admin.html页面(也就是HtmlWebpackPlugin输出的HTML文件路径),这样/admin.html就可以正常访问了。
至此,dev环境的多入口问题就解决了。

prod环境

prod环境,比dev环境更简单。由于不存在webpack Dev Server,直接在config/webpack.config.prod.js同理做2和3步骤即可。

使用npm run build构建prod版本,观察build目录,入口/admin.html的html、js和css文件俱在:

build
├── admin.html
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── service-worker.js
└── static
├── css
│ ├── admin.d41d8cd9.css
│ ├── admin.d41d8cd9.css.map
│ ├── index.9a0fe4f1.css
│ └── index.9a0fe4f1.css.map
├── js
│ ├── admin.f3dca2cd.js
│ ├── admin.f3dca2cd.js.map
│ ├── index.4b87195c.js
│ └── index.4b87195c.js.map
└── media
└── logo.5d5d9eef.svg

修改create-react-app支持多入口的更多相关文章

  1. 深入 Create React App 核心概念

    本文差点难产而死.因为总结的过程中,多次怀疑本文是对官方文档的直接翻译和简单诺列:同时官方文档很全面,全范围的介绍无疑加深了写作的心智负担.但在最终的梳理中,发现走出了一条与众不同的路,于是坚持分享出 ...

  2. 在 .NET Core 5 中集成 Create React app

    翻译自 Camilo Reyes 2021年2月22日的文章 <Integrate Create React app with .NET Core 5> [1] Camilo Reyes ...

  3. 如何扩展 Create React App 的 Webpack 配置

    如何扩展 Create React App 的 Webpack 配置  原文地址https://zhaozhiming.github.io/blog/2018/01/08/create-react-a ...

  4. tap news:week5 0.0 create react app

    参考https://blog.csdn.net/qtfying/article/details/78665664 先创建文件夹 安装create react app 这个脚手架(facebook官方提 ...

  5. 使用create react app教程

    This project was bootstrapped with Create React App. Below you will find some information on how to ...

  6. Create React App

    Facebook开源了React前端框架(MIT Licence),也同时提供了React脚手架 - create-react-app. create-react-app遵循约定优于配置(Coc)的原 ...

  7. Create React App 安装less 报错

    执行npm run eject 暴露模块 安装 npm i  less less-loader -D 1.打开 react app 的 webpack.config.js const sassRege ...

  8. [React] Use the Fragment Short Syntax in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is upgrading to Ba ...

  9. [React] {svg, css module, sass} support in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is added the svgr  ...

  10. create react app 项目部署在Spring(Tomcat)项目中

    网上看了许多,大多数都是nginx做成静态项目,但是这样局限性太多,与Web项目相比许多服务端想做的验证都很麻烦,于是开始了艰难的探索之路,终于在不经意间试出来了,一把辛酸... 正常的打包就不说了. ...

随机推荐

  1. [pycocotools修改]cocoeval.py

    __author__ = 'tsungyi' import numpy as np import datetime import time from collections import defaul ...

  2. javascript 之 面向对象【继承】

    继承:函数没有签名,无法实现接口继承.ECMAScript只支持实现继承 1/原型链 回顾:构造函数.原型和实例的关系? 回:每个构造函数都有一个原型对象.原型对象都包含一个指向构造函数的指针.实例都 ...

  3. (Code) Python implementation of phrase extraction from sentence

    import os import numpy as np import pandas as pd from tqdm import tqdm import numpy as np import str ...

  4. Docker Swarm Mode 学习笔记(创建 Swarm 集群)

    Swarm 集群由管理节点与工作节点组成. 初始化集群 使用命令:docker swarm init 如果你的 Docker 主机有多个网卡, 拥有多个 IP 地址, 必须使用 --advertise ...

  5. 基于卷积神经网络CNN的电影推荐系统

    本项目使用文本卷积神经网络,并使用MovieLens数据集完成电影推荐的任务. 推荐系统在日常的网络应用中无处不在,比如网上购物.网上买书.新闻app.社交网络.音乐网站.电影网站等等等等,有人的地方 ...

  6. LeetCode120-Triangle-数组,动态规划

    题目描述 Problem Description:   Given a triangle, find the minimum path sum from top to bottom. Each ste ...

  7. <工厂方法>比<简单工厂>多了啥

    前言:多注重设计.仅当复习讨论! 简单工厂模式 UML图   假如有一位爱心人士,想给饥饿的流浪动物喂食.此时爱心人士身带了狗粮,但是他到处找啊找,最终只找到了猫大人,是不是有点惨兮兮.但是如果有简单 ...

  8. pycharm使用selenium之前

    2.python安装好后,查看你的pycharm输出控制台,第一行就写了你所使用的python.exe的路径,如下图箭头处所示: 检查python使用的是不是你刚刚安装的,如果不是,换成你刚刚安装的p ...

  9. redis 执行操作时提示(error) NOAUTH Authentication required.

    (error) NOAUTH Authentication required. 出现认证问题,设置了认证密码,输入密码即可 127.0.0.1:6379> auth 123456

  10. error CS1002: ; expected 错误解决

    一般出现这种错误,大概原因是因为前端页面里的C#代码少个分号,或少个括号 导致编译器出错:仔细检查页面中的C#代码是否写的正确. 我之所以出现这个错误是因为前台页面中:@{  } 这里的代码少一个括号 ...