从头写一个 React-like 框架:工程搭建

最近在网上看到了 Build your own React 这篇文章,做者从零开始实现了一个简易类 React 框架,虽然没有过多的优化,但 React 中的核心思想 Concurrent ModeFiber Reconciler 等都有实现,看完后对理解 React 有很大帮助,所以我想在 Build your own React 的基础上,对代码进行拆分,搭建起本身的框架工程,而后完善教程中没完成的其余功能,代码在 rac 中。node

工程搭建

技术栈上我选择用 TypeScript 开发,Rollup 打包, 都是平时用的很少的技术,顺带一块儿练练手,并且相比 webpack, rollup 配置更简单一些。在工程中建立一个 tsconfig.json 和一个 rollup.config.js, 而后安装一下须要的 rollup 插件,好比 rollup-plugin-typescript2rollup-plugin-terser。另外准备一个 examples 文件夹,建立一个小型的 demo 工程,使用 tsx 开发react

支持 jsx

若是想让 TypeScript 支持 jsx,须要在 tsconfig 中开启 jsx TypeScript 自带了三种模式: preservereact,和 react-native,咱们设置为 react, TypeScript 就会将代码中的 jsx 翻译成 React.createElement,这也是在使用 jsx 时,React 必需要在做用域中的缘由。webpack

可是咱们要本身实现一个 React-like 框架,彻底能够给 React.createElement 换个名字。在 Build your own React 中,做者经过 /** @jsx Didact.createElement */ 注释,告诉编译器将 jsx 的输出函数改成 Didact.createElement,这个方法只对当前文件生效,若是是在工程中使用为每一个文件都加一行注释就麻烦了。咱们经过另外一种办法,在 tsconfig 中经过 jsxFactory 属性指定,咱们这里叫 h,除了 React.createEmenent,还有个特殊元素 - Fragment,TypeScript 默认会翻译成 React.Fragment,咱们经过 jsxFragmentFactory 直接改成 Fragmentgit

tsconfig.json:es6

{
  "compilerOptions": {
    "target": "esnext",
    "module": "commonjs",
    "moduleResolution": "node",
    "jsx": "react", // enable jsx
    "jsxFactory": "h", // React.createElement => h
    "jsxFragmentFactory": "Fragment", // React.Fragment => Fragment
    "rootDir": "./src",
    "lib": ["dom", "es2015"]
  }
}

Rollup 配置

Rollup 的配置比较简单,除了 input,output,再额外加一些插件就能够了:github

const path = require('path')
const typescript = require('rollup-plugin-typescript2')
const { terser } = require('rollup-plugin-terser')
const eslint = require('@rollup/plugin-eslint')

export default {
  input: 'src/index.ts',
  output: [
    { file: 'dist/rac.umd.js', format: 'umd', name: 'rac' }
  ],
  plugins: [
    terser(),
    eslint({
      throwOnError: true,
      include: ['src/**/*.ts']
    }),
    typescript({
      verbosity: 0,
      tsconfig: path.resolve(__dirname, 'tsconfig.json'),
      useTsconfigDeclarationDir: true
    })
  ]
}

Eslint in TypeScript

为了能让 Eslint 支持 TypeScript,须要给 Eslint 一些额外配置:web

module.exports = {
  parser: '@typescript-eslint/parser',
  env: {
    es6: true,
    browser: true
  },
  plugins: [
    '@typescript-eslint'
  ],
  extends: [
    'eslint:recommended',
  ],
  parserOptions: {
    sourceType: 'module'
  },
  rules: {
    ...
  }
}

项目结构
React 新的 Fiber 架构有几个核心概念,在 Build your own React 中,做者依照typescript

  • Step I: The createElement Function
  • Step II: The render Function
  • Step III: Concurrent Mode
  • Step IV: Fibers
  • Step V: Render and Commit Phases
  • Step VI: Reconciliation
  • Step VII: Function Components
  • Step VIII: Hooks

这几步逐步实现了一个 mini React,为了提升代码可读性和可维护性,会把这些功能划分到不一样的文件中:json

.
├── README.md
├── examples  // demo目录
├── package.json
├── rollup.config.js
├── src
│   ├── dom.ts
│   ├── h.ts
│   ├── hooks.ts
│   ├── index.ts
│   ├── reconciler.ts
│   ├── scheduler.ts
│   └── type.ts
└── tsconfig.json
  • dom.ts 中处理 DOM 相关工做
  • h.ts 中是对 jsxFactory, jsxFragmentFactory 的实现
  • hooks.ts 中是对 hooks 的实现
  • reconciler.ts 是 reconcile 阶段和 commit 阶段的实现
  • shceduler.ts 是任务调度器的实现
  • type.ts 是一些类型定义

到这工程就搭建起来了,整个工程的结构和一些代码实现上借鉴了 fre 这个框架。react-native

相关文章
相关标签/搜索