追溯 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 使用过程中的基本原则以及编写过程中的心得分享,本文主要和大家聊聊在各个使用场景下的 ...
随机推荐
- Regular Expression Syntax
python的正则表达式 正则表达式的概念 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个"规则字符串",这个"规 ...
- Linux三剑客之awk最佳实践
笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 知识点: 记录与字段 模式匹配:模式与动作 基本的awk执行过程 awk常用内置变量(预定义变量) awk数组 a ...
- 结合find和cp批量查找文件并复制到指定文件夹中
find . -name JA1_*001_027 | xargs -i cp {} F:/ 说明: . 表示当前文件夹及其子文件夹中查找 -name 指定待查找文件,可以使用通配符 F:/ 表示 ...
- Android webView包装WebAPP
前言 Android webView 兼容体验真的差到了极点!! 前一阵子,老板要讲 WebAPP 放到 Android 和 iOS 里面,而我因为以前做过安卓,所以这方面就由我来打包, 原理是很简单 ...
- js中的深拷贝与浅拷贝
对象的深拷贝于浅拷贝 对于基本类型,浅拷贝过程就是对值的复制,这个过程会开辟出一个新的内存空间,将值复制到新的内存空间.而对于引用类型来书,浅拷贝过程就是对指针的复制,这个过程并没有开辟新的堆内存空间 ...
- linux的定时任务服务crond(crontab)服务
1,Crond: Crond是linux系统中用来定期执行命令或指定程序任务的一种服务或者软件.(Centos5以后默认存在) 当优化开机自启动的时候,第一个就是crond. Crond服务默认情况( ...
- Python之Django rest_Framework框架源码分析
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_fram ...
- python os模块实用函数
os.sep可以取代操作系统特定的路径分隔符.windows下为 “\\” os.name字符串指示你正在使用的平台.比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'pos ...
- Spring mybatis源码学习指引目录
前言: 分析了很多方面的mybatis的源码以及与spring结合的源码,但是难免出现错综的现象,为了使源码陶冶更为有序化.清晰化,特作此随笔归纳下分析过的内容.博主也为mybatis官方提供过pul ...
- 洛谷 [P1402] 酒店之王
有两个约束条件的二分图匹配 我们回忆一下二分图匹配的匈牙利算法的具体流程,它是通过寻找增广路来判断最大匹配数的,我们再观察一下题目中的两个条件,只有两个条件都满足,才算找到一条增广路,所以我们可以分别 ...