文:萝卜(沪江金融前端开发工程师)

本文原创,转载请注明作者及出处

如果你使用 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 的实现的更多相关文章

  1. [转] React Hot Loader 3 beta 升级指南

    前言 在用 react-hot-loader v1.3 的时候有些深层组件不会很完美的热更新(可能是我使用有问题).然后在 react-hot-loader 首页中看到 React Hot Loade ...

  2. [转] 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 ...

  3. npm scripts + webpack 实践经验(React、Nodejs)

    最近用Webpack+npm scripts+Mongodb+Nodejs+React写了个后台项目,在用Webpack构建过程中遇到了许多坑,就写出来分享一下. 构建工具五花八门,想当年刚学会Gru ...

  4. Rails + React +antd + Redux环境搭建

    前提条件:node和ruby on rails必须已经安装好(相关安装流程不再此处介绍) 1.nvm.node 2.npm or yarn装一个就好 3.rvm.ruby on rails 4.for ...

  5. Webpack+React项目入门——入门及配置Webpack

    一.入门Webpack 参考文章:<入门Webpack,看这篇就够了> 耐心看完这篇非常有帮助 二.React+Webpack环境配置 参考文章:<webpack+react项目初体 ...

  6. webpack学习(五)—webpack+react+es6(第1篇)

    如果你看过webpack学习系列的前一个文章,接下来做的东西会比较简单 :webpack学习(四)— webpack-dev-server react发展的很快,现在大部分开发react相关的项目,都 ...

  7. 蒲公英 · JELLY技术周刊 Vol 27: 平平无奇 React 17

    蒲公英 · JELLY技术周刊 Vol.27 这个热闹的十月终于要走到尾声,React 17 历经 4 个 RC 版本之后,也于数天前正式发布了,而同在几天前发布的 CRA 4.0 也已经完成了 Re ...

  8. [react]react创建app,路由,mobx 全教程

    ​ 1.创建app, npx create-react-app my-app Cmd Copy 2.进入项目目录 cd my-app Cmd Copy 3.启用配置文件(默认是不开启配置文件的) ya ...

  9. JavaScript 踩坑心得— 为了高速(下)

    一.前言 本文的上一篇 JavaScript 踩坑心得- 为了高速(上) 主要和大家分享的是 JavaScript 使用过程中的基本原则以及编写过程中的心得分享,本文主要和大家聊聊在各个使用场景下的 ...

随机推荐

  1. 使用sed替换一行内多个括号内的值

    1. 括号在同一行 # cat test2good morning (good afternoon) (good evening) (goodgood) (good morning) # cat se ...

  2. 基础知识全面LINUX

    学习Linux系统的重要性应该不用多说,下面我就对Linux的基础知识进行一个全面而又简单的总结.不过建议大家还是装个Linux系统多练习,平时最好只在Linux环境下编程,这样会大有提高. linu ...

  3. C# 取值函数

    C# 中取绝对值的函数 System.Math.Abs(float value); System.Math.Abs(decimal value);System.Math.Abs(int value); ...

  4. sizeof和strlen的使用

    sizeof和strlen的使用 1. sizeof 其值在编译时就计算好了,所以不能用来返回动态分配的内存空姐的大小. 当参数为下面内容是,所表达的含义: 数组——编译时分配的数组空间大小: 指针— ...

  5. Python学习笔记(一):列表和元组

    1.列表和元组的主要区别在于:列表可以修改,元组则不能.即如果要根据要求添加元素,列表更适合,    如果出于某种原因,序列不能修改的时候,使用元组更为合适. 2.通用序列操作1)索引:正数索引时,p ...

  6. 浅谈python中的闭包函数

    闭包函数初探 通常我们定义函数都是这样定义的 def foo(): pass 其实在函数式编程中,函数里面还可以嵌套函数,如下面这样 def foo(): print("hello worl ...

  7. MySQL密码重置(root用户)

    分别在Windows下和Linux下重置了MYSQL的root的密码: 在windows下: 1:进入cmd,停止mysql服务:Net stop mysql 到mysql的安装路径启动mysql,在 ...

  8. Objective-C Runtime 文档翻译

    前言   Objective-C语言尽可能多的将许多决定从编译连接推迟到运行时.无论何时,它都尽可能的动态处理事件.这就意味着OC语言不仅仅需要编译器,还需要一个运行时系统来执行编译完成的代码.对于O ...

  9. 使用react-router实现单页面应用路由

    这是Webpack+React系列配置过程记录的第二篇.其他内容请参考: 第一篇:使用webpack.babel.react.antdesign配置单页面应用开发环境 第二篇:使用react-rout ...

  10. tomcat集群与负载均衡

    参考文章http://kalogen.iteye.com/blog/784908,加上了自己调试过程中遇到的问题. 注1:实现此集群的方法参考了网上的很多文章,但由于很多文章都表明是原创的,故无法知道 ...