create-react-app 修改为多入口编译的方法


Posted in Javascript onAugust 01, 2018

需求和出发点

我们会有较多的小的单页应用,主要是一些简单的页面和活动之类。这些页面相互之间没有交集,但是会有一些可以共用的代码,资源、接口、组件啥的。

对此,我们想到了两种解决方案:

  • react-router 路由方案;
  • 同一个项目的多入口编译;

针对我们的业务需求,其实 react-router 方案会有两个小问题:

  • 单个活动的修改,其实需要编译整个项目;
  • 若是不做编译优化,整个项目的包会比较大,但其实没必要,当然这个可以通过 react-router 的按需加载来解决;

权衡之下,我们还是选择了第二个方案——改造项目成为多入口编译。

文件结构设计

改进后,整个项目的结构大体如下:

- project
  - build
  - config
  - public
  - scripts
  - src
    - api
    - component
    - site
      - site1
        - index.html
        - index.js
        - ...
      - site2
        - index.html
        - index.js
        - ...
  - package.json

site 文件夹下的所有文件夹都是一个独立的项目,项目通用的代码、资源被抽离到更外层的文件夹内,如 api、component 等,文件夹内都会有自己的 index.html 和 index.js,这会作为该项目的 html 模板和入口文件。下面,我们看下是如何修改编译过程的。

修改入口和出口

编译需要指定编译的入口和输出的位置,在 create-react-app 本来生成的 code 中,只有单入口和单出口,但是其实 webpack 是支持多入口、多出口的。

入口修改

create-react-app 命令生成的 config 文件夹中,有个 paths.js 文件,这里面 export 了比较常用的路径。在这里,我对 src/site 文件夹内的文件夹进行了遍历,生成为对象。具体代码如下:

// all site paths
function allSitePath(source) {
 const { lstatSync, readdirSync } = fs
 const { join } = path
 const result = {}
 const isDirectory = source => lstatSync(source).isDirectory()
 readdirSync(source).map(name => {
  let path = join(resolveApp(source), name)
  if (isDirectory(path)) result[name] = path
 })
 return result
}

module.exports = {
 ...
 allSites: allSitePath('src/site'),
}

在 webpack.config.dev.js / webpack.config.prod.js 中找到 module.exports 的 entry 属性,将其修改为:

// 动态生成 entry
const entry = {}
Object.keys(paths.allSites).forEach(item => {
 entry[item] = [
  require.resolve('./polyfills'),
  require.resolve('react-dev-utils/webpackHotDevClient'),
  require.resolve('react-error-overlay'),
  paths.allSites[item]
 ]
})

module.exports = {
 ...
 entry: entry,
 ...
}

出口修改

出口的修改分为两部分,一部分是 module.exports 的 output,添加 name 以使静态资源区分不同项目:

module.exports = {
 ...
 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).replace(/\\/g, '/'),
 },
 ...
}

另一部分是 plugin 的修改,webpack 中,每个 HTML 文件的输出,其实是一个 HtmlWebpackPlugin,我们需要添加多个 HtmlWebpackPlugin,以求生成多个 HTML:

// 动态生成 plugins
const plugins = []
Object.keys(paths.allSites).forEach(item => {
 plugins.push(new HtmlWebpackPlugin({
  inject: true,
  chunks: [item],
  template: `${paths.allSites[item]}/index.html`,
  filename: `${item}/index.html`,
 }))
})

module.exports = {
 ...
 plugins: [
  ...
 ].concat(plugins),  
 ...
}

修改 webpack Dev Server 配置

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

这里,我们还需要修改 /config/webpackDevServer.config.js,做一些额外配置。

const rewrites = []
Object.keys(paths.allSites).forEach(item => {
 rewrites.push({
  from: new RegExp(`^\\/${item}/`, 'i'),
  to: `/${item}/index.html`,
 })
})

...

module.exports = function(proxy, allowedHost) {
 return {
  ...
  historyApiFallback: {
   // Paths with dots should still use the history fallback.
   // See https://github.com/facebookincubator/create-react-app/issues/387.
   disableDotRule: true,
   // 指明哪些路径映射到哪个html
   rewrites: rewrites,
  },
  ...
 };
};

OK,到这里,整个改造就完成了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
直接生成打开窗口代码,不必下载
May 14 Javascript
Javascript学习笔记7 原型链的原理
Jan 11 Javascript
原生JS实现加入收藏夹的代码
Oct 24 Javascript
angularJS 入门基础
Feb 09 Javascript
基于jquery实现的仿优酷图片轮播特效代码
Jan 13 Javascript
一道常被人轻视的web前端常见面试题(JS)
Feb 15 Javascript
Angular 向组件传递模板的两种方法
Feb 23 Javascript
Vue+element-ui 实现表格的分页功能示例
Aug 18 Javascript
Three.JS实现三维场景
Dec 30 Javascript
async/await优雅的错误处理方法总结
Jan 30 Javascript
html中创建并调用vue组件的几种方法汇总
Nov 17 Javascript
Javascript实现打鼓效果
Jan 29 Javascript
Vue项目全局配置页面缓存之按需读取缓存的实现详解
Aug 01 #Javascript
JavaScript执行环境及作用域链实例分析
Aug 01 #Javascript
Vue.js 利用v-for中的index值实现隔行变色
Aug 01 #Javascript
echarts设置图例颜色和地图底色的方法实例
Aug 01 #Javascript
看看“疫苗查询”小程序有温度的代码
Jul 31 #Javascript
Vue父子组件双向绑定传值的实现方法
Jul 31 #Javascript
react中实现搜索结果中关键词高亮显示
Jul 31 #Javascript
You might like
PHP中文件缓存转内存缓存的方法
2011/12/06 PHP
使用PHP接收POST数据,解析json数据
2013/06/28 PHP
PHP模板引擎Smarty自定义变量调解器用法
2016/04/11 PHP
php中array_unshift()修改数组key注意事项分析
2016/05/16 PHP
PHP实现权限管理功能示例
2017/09/22 PHP
jQuery实现跟随鼠标运动图层效果的方法
2015/02/02 Javascript
js判断文本框输入的内容是否为数字
2015/12/23 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
AngularJS基础 ng-init 指令简单示例
2016/08/02 Javascript
详解.vue文件中监听input输入事件(oninput)
2017/09/19 Javascript
Node 自动化部署的方法
2017/10/17 Javascript
分享vue.js devtools遇到一系列问题
2017/10/24 Javascript
详解vue添加删除元素的方法
2018/06/30 Javascript
微信小程序自定义底部弹出框
2020/11/16 Javascript
JavaScript 反射和属性赋值实例解析
2019/10/28 Javascript
Element图表初始大小及窗口自适应实现
2020/07/10 Javascript
关于JavaScript中异步/等待的用法与理解
2020/11/18 Javascript
python中遍历文件的3个方法
2014/09/02 Python
python创建进程fork用法
2015/06/04 Python
python开发利器之ulipad的使用实践
2017/03/16 Python
Python Web编程之WSGI协议简介
2018/07/18 Python
python生成以及打开json、csv和txt文件的实例
2018/11/16 Python
django的403/404/500错误自定义页面的配置方式
2020/05/21 Python
css3 旋转按钮 使用CSS3创建一个旋转可变色按钮
2012/12/31 HTML / CSS
Html5实现用户注册自动校验功能实例代码
2016/05/24 HTML / CSS
关于canvas.toDataURL 在iOS运行失败的问题解决
2020/09/16 HTML / CSS
德国街头和运动文化高品质商店:BSTN Store
2017/08/26 全球购物
英国最大的经认证的有机超市:Planet Organic
2018/02/02 全球购物
戴森台湾线上商城:Dyson Taiwan
2018/05/21 全球购物
小班下学期评语
2014/05/04 职场文书
小学生勤俭节约演讲稿
2014/08/28 职场文书
店面出租协议书范本
2014/11/28 职场文书
个人年终总结开头
2015/03/06 职场文书
保护校园环境倡议书
2015/04/28 职场文书
鉴史问廉观后感
2015/06/10 职场文书
教你怎么用PyCharm为同一服务器配置多个python解释器
2021/05/31 Python