追溯 React Hot Loader 的实现
文:萝卜(沪江金融前端开发工程师)
本文原创,转载请注明作者及出处
如果你使用 React ,你可以在各个工程里面看到 Dan Abramov 的身影。他于 2015 年加入 facebook,是 React Hot Loader 、React Transform、redux-thunk、redux-devtools 等等的开发者。同样也是 React、Redux、Create-React-App 的联合开发者。从他的签名 Building tools for humans. 或许表明了他想打造高效的开发环境以及调试过程。
作为 Dan 的小迷妹,如他说 is curious where the magic comes from。这篇文章会带你们去了解 React Hot Loader 的由来,它实现的原理,以及在实现中遇到的问题对应的解决方法。也许你认为这篇文章太过于底层,对日常的业务并没有帮助,但希望你和我一样能通过了解一个实现得到乐趣,以及收获一些思路。
首先,React Hot Loader 的产生
Dan 在自己的文章里面说到。React Hot Loader 起源一个来自 stackoverflow 上的一个问题 —— what exactly is hot module replacement in webpack,这个问题解释了 webpack 的 hot module replacement(下面简称 HMR)到底是什么,以及我们可以利用它做什么,Dan 当时想到也 React 可以和 webpack hot module 以一种有趣的方式结合在一起。
于是他在 Twitter 上录制了一个简单的视频(请看下面),事实上视频中的实现依赖于它在 React 源代码里面插入了很多自己的全局变量。他本没指望到这个视频能带来多大的关注,但结果是他收到了很多点赞,并且粉丝狂增,他意识到必须以一个真正的工程去实现。
初步尝试, 直接使用 HMR
HMR 是属于 webpack 范畴内的实现,你可以在 webpack 的官方文档 看到如何开启它以及它提供的接口。如果你有印象,你会记得使用它需要
在 webpack config 或者 webpack-dev-server cli 里面指定开启 hot reloading 模式,并且在你的代码里写上 module.hot.accept(xxx)
。但 HMR 到底是什么?我们可以用一句话总结:当一个 import 进来的模块发生了变化,HMR 提供了一个接口让我们使用 callback 回调去做一些事情。
一个使用 HMR 实现自动刷新的 React App 像下面这样:
// index.js
var App = require('./App')
var React = require('react')
var ReactDOM = require('react-dom')
// 像通常一样 render Root Element
var rootEl = document.getElementById('root')
ReactDOM.render(<App />, rootEl)
// 我们是不是在 dev 环境 ?
if (module.hot) {
// 当 App.js 更新了
module.hot.accept('./App', function () {
// require 进来更新的 App.js 重新render
var NextApp = require('./App')
ReactDOM.render(<NextApp />, rootEl)
})
}
请注意,这个实现没有使用 React Hot Loader 或者 React Transform 或者任何其他的,这仅仅是 webpack 的HMR 的 api。而这里的 callback 回调函数当然是 re-render 我们的 app。
得益于 HMR API 的设计,在嵌套的组件也能实现更新。如果一个模块没有指明如何去更新自己,那么引入这个模块的另一个模块也会被包含在热更新的 bundle 里,这些更新会”冒泡“,直到某个 import 它们的模块 "接收" 更新。如果有些模块最终没有被"接受",那么热更新失败,控制台会打印出警告。为了“接受”更新,你只需要调用 module.hot.accept('./name', callback)
。
因为我们在 index.js 里的接受了 App.js 的更新 ,这使得我们隐性的接受了所有从 App.js 引入的所有模块(component)的更新。打个比方,假如我编辑了 Button.js 组件,而它被 UserProfile.js 以及 Navbar.js import, 而这两个模块都被 App.js import 引入了。因为 index.js import 了 App.js,并且它包含了 module.hot.accept('./App', callback)
,Webpack 会自动产生一个包含以上所有文件的 “updated bundle”, 并且运行我们提供的 callback。
你以为 hot reloading 就到此为止了吗,当然远远不够
追溯 React Hot Loader 的实现的更多相关文章
- [转] React Hot Loader 3 beta 升级指南
前言 在用 react-hot-loader v1.3 的时候有些深层组件不会很完美的热更新(可能是我使用有问题).然后在 react-hot-loader 首页中看到 React Hot Loade ...
- [转] Spring Boot and React hot loader
When I develop web applications, I love using React. I'm also a Spring and groovy addict. Those two ...
- npm scripts + webpack 实践经验(React、Nodejs)
最近用Webpack+npm scripts+Mongodb+Nodejs+React写了个后台项目,在用Webpack构建过程中遇到了许多坑,就写出来分享一下. 构建工具五花八门,想当年刚学会Gru ...
- Rails + React +antd + Redux环境搭建
前提条件:node和ruby on rails必须已经安装好(相关安装流程不再此处介绍) 1.nvm.node 2.npm or yarn装一个就好 3.rvm.ruby on rails 4.for ...
- Webpack+React项目入门——入门及配置Webpack
一.入门Webpack 参考文章:<入门Webpack,看这篇就够了> 耐心看完这篇非常有帮助 二.React+Webpack环境配置 参考文章:<webpack+react项目初体 ...
- webpack学习(五)—webpack+react+es6(第1篇)
如果你看过webpack学习系列的前一个文章,接下来做的东西会比较简单 :webpack学习(四)— webpack-dev-server react发展的很快,现在大部分开发react相关的项目,都 ...
- 蒲公英 · JELLY技术周刊 Vol 27: 平平无奇 React 17
蒲公英 · JELLY技术周刊 Vol.27 这个热闹的十月终于要走到尾声,React 17 历经 4 个 RC 版本之后,也于数天前正式发布了,而同在几天前发布的 CRA 4.0 也已经完成了 Re ...
- [react]react创建app,路由,mobx 全教程
1.创建app, npx create-react-app my-app Cmd Copy 2.进入项目目录 cd my-app Cmd Copy 3.启用配置文件(默认是不开启配置文件的) ya ...
- JavaScript 踩坑心得— 为了高速(下)
一.前言 本文的上一篇 JavaScript 踩坑心得- 为了高速(上) 主要和大家分享的是 JavaScript 使用过程中的基本原则以及编写过程中的心得分享,本文主要和大家聊聊在各个使用场景下的 ...
随机推荐
- CentOS 通过yum来升级php到php5.6
在文章中,我们将展示在centOS系统下如果将php升级到5.6,之前通过yum来安装lamp环境,直接升级的话,提示没有更新包,也就是说默认情况下php5.3.3是最新 1.查看已经安装的php版本 ...
- MySQL--当事务遇到DDL命令
众所周知MySQL的DDL语句是非事务的,即不能对DLL语句进行回滚操作,哪在事务中包含DDL语句会怎样呢? 如: #禁用自动提交 set autocommit=off; #创建tb1 create ...
- FastDFS分布式存储实战
<FastDFS分布式存储实战> 技术选型 FastDFS相关组件及原理 FastDFS介绍 FastDFS架构 FastDFS工作流程 上传 同步机制 下载 文件合并原理 实验环境说明 ...
- [HTTP] PHP 实现 HTTP Server 原理
单进程服务器简陋版: <?php /** * Single http server. * * Access http://127.0.0.1:8081 * * @license Apache-2 ...
- PYTHON3 中的虚假四舍五入:round()
PYTHON3 中的虚假四舍五入:round() 创建时间: 2017/12/5 17:08 作者: CN_Simo 标签: python基础, round, 四舍五入 一.这不是一个BUG! 在使用 ...
- isFile() exists() isDirectory()的区别
isFile()public boolean isFile()测试此抽象路径名表示的文件是否是一个标准文.如果该文件不是一个目录,并且满足其他与系统有关的标准,那么该文件是标准文件.由Java应用程序 ...
- php动态编译mysqli扩展
在源PHP安装文件中进入注意是你下载的php源文件软件包cd ./php-5.5.4/ext/mysqli注意要先确保/server/php/bin/php-config存在/server/php/b ...
- HBase 数据库检索性能优化策略--转
https://www.ibm.com/developerworks/cn/java/j-lo-HBase/index.html HBase 数据表介绍 HBase 数据库是一个基于分布式的.面向列的 ...
- JVM基础篇(一)
JVM简介 JVM(Java虚拟机)是一个虚拟的机器,在实际的计算机上通过软件模拟来实现.JVM有自己的硬件,如处理器.堆栈.寄存器等,还具有相应的指令系统. JVM包括一套字节码指令集.一组寄存器. ...
- bzoj 3509: [CodeChef] COUNTARI] [分块 生成函数]
3509: [CodeChef] COUNTARI 题意:统计满足\(i<j<k, 2*a[j] = a[i] + a[k]\)的个数 \(2*a[j]\)不太好处理,暴力fft不如直接暴 ...