cra(create-react-app)
脚手架默认创建的是单页应用,如果想要改造为多页应用,首先要把wepback
配置暴露出来,然后自己维护。以下是配置步骤:
cra版本:4.0.0
弹出后使用的webpack
版本
"webpack": "4.44.2",
"webpack-dev-server": "3.11.0",
"webpack-manifest-plugin": "2.2.0",
"workbox-webpack-plugin": "5.1.4"
1. eject弹出配置
在项目搭建完毕后,第一步操作就是执行弹出操作,暴露出webpack
配置。
npm(yarn) run eject
我在实际运行中,先把原有目录删除一部分,然后搭建了自己的目录结构,最后执行弹出操作,结果报错。所以这一步一定要首先执行。 弹出后,在项目根目录中会多出
config
、scripts
两个文件夹,我们需要维护的webpack配置就在config
文件夹中了。
2. paths.js配置
参考原有的配置选项,配置其他页面:
/* config/paths.js */
//原有的
module.exports = {
...
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
...
}
//更改为
module.exports = {
...
appHtml: resolveApp('public/index.html'),
appQueryHtml: resolveApp('public/query.html'),
appTicketHtml: resolveApp('public/ticket.html'),
appOrderHtml: resolveApp('public/order.html'),
appIndexJs: resolveModule(resolveApp, 'src/index/index'),
appQueryJs: resolveModule(resolveApp, 'src/query/index'),
appTicketJs: resolveModule(resolveApp, 'src/ticket/index'),
appOrderJs: resolveModule(resolveApp, 'src/order/index'),
...
}
注意:在src和public目录中要增加所需要的页面,页面里的内容就照搬index.html和index.js中的就可以。
3. 更改webpack.config.js中的配置
paths.js中的路径配置完成后,就可以愉(踩)快(坑)的配置webpack
了。
3.1 改写entry入口
//原有的
entry: isEnvDevelopment && !shouldUseReactRefresh ?
[
...
webpackDevClientEntry,
// Finally, this is your app's code:
paths.appIndexJs,
...
]:paths.appIndexJs,
//更改为
entry: isEnvDevelopment && !shouldUseReactRefresh ?
{
index:[webpackDevClientEntry,paths.appIndexJs],
query:[webpackDevClientEntry,paths.appQueryJs],
ticket:[webpackDevClientEntry,paths.appTicketJs],
order:[webpackDevClientEntry,paths.appOrderJs]
}:
{index:[paths.appIndexJs],
query:[paths.appQueryJs],
ticket:[paths.appTicketJs],
order:[paths.appOrderJs]
}
3.2 改写output的filename
//原有的
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/bundle.js',
//更改为
filename: isEnvProduction
? 'static/js/[name].[contenthash:8].js'
: isEnvDevelopment && 'static/js/[name].js',
3.3 改写plugin中HtmlWebpackPlugin配置
//原有的
plugins:{
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
...
),
...
}
//在照搬原有的配置,增加query、ticket、order
...
new HtmlWebpackPlugin(
Object.assign(
{}, {
inject: true,
template: paths.appQueryHtml,
filename: 'query.html',
chunks: ['query'],
}...
)
...
3.4 改写plugin中的ManifestPlugin配置
//原有的
...
const entrypointFiles = entrypoints.main.filter(
fileName => !fileName.endsWith('.map')
);
...
//更改为
const entrypointFiles = {};
Object.keys(entrypoints).forEach(entrypoint => {
entrypointFiles[entrypoint] = entrypoints[entrypoint].filter(fileName =>
!fileName.endsWith('.map'));
});
...
由于版本的原因,我在参考其他版本的cra配置的时候没有这一项,导致
yarn start
运行的时候页面无限加载最后连接失败。所以这一步对于新版本来说很有必要,或者直接删除ManifestPlugin配置项。
以上是简单配置,如果页面比较少手动添加即可。如果页面比较多,就需要写一些函数方法,自动查找帮助我们直接添加entry
和htmlPlugin
部分。
为何选择多页应用?
单页应用
- 在SPA(单页)应用中,使用 webpack 构建完成项目之后,会生成一个 html 文件,若干个 js 文件,以及若干个 css 文件。在 html 文件中,会引用所有的 js 和 css 文件。
- 缺点:单页面应用,往往对应着高复杂度,比如多层次路由配置、统一数据处理等;首屏比较慢。
- 优点:页面切换快。
多页应用
- 多页应用中,使用 webpack 构建完成项目之后,会生成多个 html 文件,多个 js 文件,以及多个 css 文件。在每个 html 文件中,只会引用该页面所对应的 js 和 css 文件。
- 缺点:每次页面切换都是一次网页刷新并下载相关资源文件,浪费带宽。
- 优点:SEO效果好,首页加载快。
对于单页应用的缺点来说,有很多技术方案可以修正,比如首页SSR(服务端渲染)、置react-router路由等插件可以轻松把多页应用改成单页。
多页应用使用场景:
- 老旧项目重构(jquery等应用),复用原有页面
- 需要迁移到其他项目或平台中