React Europe 2020 的 recompilation 优化笔记

看 React-Conf Europe 2020 的 recompilation 优化笔记。

开篇,作者讲了其灵感来源。源自项目 re-bulma 的文档,文档中的 React 代码可以在网页内被实时编译执行。

Dev bundlers


作者认为理想的处理方式:

  • If you improve the recompilation time, you increase productivity.(如果您提高了重新编译的时间,您就提高了生产率。)
  • If you remove the recompilation time, you introduce a new style of development.(如果您去掉重新编译时间,您引入了一种新的开发风格。)

Let's make instant recompilation the norm

让我们把即时重新编译变成规范。

How do bundlers work?

What do current bundlers do?

  • Resolve - 查找依赖
import a from './a.js'
console.log(a)
export default 'Hello World'
  • Transform - 转换代码

We need to make this code understandable by the browser so that can run it. so the bundle will be converted to commonjs module.

const a = require('./a.js')
console.log(a.default)
exports.default = 'Hello World'

Next step we wrap the code into a function that exposes require module and exports:

function(require, module, exports) {
  const a = require('./a.js')
  console.log(a.default)
}
function(require, module, exports) {
  exports.default = 'Hello World'
}

The last step that we need to do is we need to map every file to a module number because this is more of an optimization but it is really important and useful.

moduleId:

function(require, module, exports) {
  const a = require(1) // 1 => './a.js'
  console.log(a.default)
}

moduleId:

function(require, module, exports) {
  exports.default = 'Hello World'
}
  • Concatenate - 拼接/组装代码

Final step is the concatenation process.

const moduleMap = {
  0: function(require, module, exports) {
    const a = require(1) // 1 => './a.js'
    console.log(a.default)
  },
  1: function(require, module, exports) {
    exports.default = 'Hello World'
  }
}

const cache = {}

const bundlerRequire = function(requireId) {
  if (cached[requireId]) {
    return cached[requireId]
  }
  
  const module = { exports: {} }
  cached[requireId] = module
  
  const moduleFunc = moduleMap[requireId]
  moduleFunc(bundlerRequire, module, module.exports)
  
  return module.exports
}

bundlerRequire(0)
  • Hot-Reload - development 热更新
  • Minify - prod - 压缩大小
  • Optimize - prod - 代码优化

Development focused "Bundlers"

  • Snowpack
  • Vite

image

  1. 使用 es6 module 浏览器已原生支持,所以 resolve 过程浏览器会自己去请求 JS 文件。
  2. 监听对应文件变化,执行更新 change 替换 transformed 之后的文件
  3. 浏览器根据现有 state 执行 render 重新渲染被影响的对应组件
  • Sandpack(sandpack 是 codesandbox 的打包工具)

  • Pre-bundled Dependencies
    • Server 直接返回预编译好的代码到前端给浏览器执行,所以跳过了编译过程,直接执行。这一步就是前面提到的 Resolve + transform。
    • 用户代码如图中的示例就是简单的 eval(codeByUser)
    • 如果 UI 更新,那开发的代码中跟UI相关的部分也会被实时 Recompilation instantly
  • Distributed Cache

What about Hot Module Reloading?

  • React-Fast-Refresh
  • Recompilation instantly

References

Let’s Make Development Fast Again! 备梯子

posted @ 2020-05-30 22:23  月光宝盒造梦师  阅读(307)  评论(0编辑  收藏  举报