react源码阅读环境配置

前言

阅读源码时,有许多变量在程序运行过程当中不断的产生,其中存放着什么东西,一直是一个比较头疼的问题。不停的推导增长了验算的负担,随着代码逐渐的深刻,也会产生必定的记忆负担。若是靠脑壳去记,简单点的代码还好。复杂的代码。。。你懂的。
随着react被普遍使用,不少人会好奇react是怎么实现的。会有一探源码的想法。若是直接阅读react.development.js是很简单,页面引入就行了。可是react.development.js终因而通过编译工具编译过的代码,不少的代码看起来并不直观。理想的状况是直接引用源文件,也就是github上react仓库中,packages目录下的代码,直接阅读es6的代码。
可是es6代码浏览器支持并不友好。因此须要配置webpack打包成es5。同时须要配上sourceMap。这样,既可让源码跑在浏览器环境,也能够直接读es6的代码,并且能够随时打断点,查看变量里保存的值。css

那么,闲言少叙,开始本章的主题。html

目录结构

概述

这是我目前用的一个简单的目录结构。这次调试的代码为react 16.4.0node

详情

  • node_modules 存放依赖的包
  • packages github上的packages文件夹直接拿来用
  • test-env 测试用的目录react

    • index.js #引用react、react-dom的启动文件
    • index.less
    • tpl.html # html模板文件

clipboard.png

webpack的配置

概要

webpack的配置就是常规的babel,和一堆loader。为了提升打包速度,可使用Happypack插件。若是以为速度还不够快,能够再引入DLLplugin。此处webpack的使用不是重点,在此只是简单给出打包须要的基本配置
代码以下:webpack

详情

const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const os = require('os');
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module.exports = {
  mode: 'development',
  entry: './test-env/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  module: {
    rules: [{
        test: /\.css$/,
        use: {
          loader: 'happypack/loader?id=happyLess',
        }
      },
      {
        test: /\.less$/,
        use: {
          loader: 'happypack/loader?id=happyLess',
        }
      },
      {
        test: /\.js$/,
        use: {
          loader: 'happypack/loader?id=happyBabel',
        }
      }
    ]
  },
  plugins: [
    
    new HtmlWebpackPlugin({
      template: './test-env/tpl.html'
    }), new webpack.HotModuleReplacementPlugin(),
    new webpack.DefinePlugin({
      __DEV__: true,
      NODE_ENV:JSON.stringify("development"),
      spyOnDev: false,
      spyOnDevAndProd: false,
      spyOnProd: false,
      __PROFILE__: true,
    }),
    new HappyPack({
        //用id来标识 happypack处理那里类文件
      id: 'happyBabel',
      //如何处理  用法和loader 的配置同样
      loaders: [{
        loader: 'babel-loader?cacheDirectory=true',
      }],
      //共享进程池
      threadPool: happyThreadPool,
      //容许 HappyPack 输出日志
      verbose: true,
    }),
    new HappyPack({
      //用id来标识 happypack处理那里类文件
      id: 'happyLess',
      //如何处理  用法和loader 的配置同样
      loaders: ['style-loader','css-loader','less-loader'],
      //共享进程池
      threadPool: happyThreadPool,
      //容许 HappyPack 输出日志
      verbose: true,
    }),
  ],
  devtool: "inline-source-map", // enum
  devServer: {
    contentBase: path.join(__dirname, 'test-env'),
    port: 9000,
    hot: true,
    overlay: true
  },
  resolve: {
    modules: [
      "node_modules",
      path.resolve(__dirname, "packages"),
      path.resolve(__dirname, "packages/shared")
    ],
    alias: {
      '@packages': path.resolve(__dirname, 'packages/'),
    }
  }
};

babel配置

{
  "presets": ["env","react","stage-0"],
}

入口文件

概述

为了简化项目流程,此处用了一个最简单的tpl.html模板文件,经过webpackhtmlplugin引入了打包好后的带sourcemap的js。
其中,js只是用react实现了一个简单的Hello world而且用react-render渲染到页面上。git

index.js

import './index.less';
import React, {Component} from '@packages/react';
import ReactDOM from '@packages/react-dom/index.js';

class Hello extends Component{
  constructor(){
    super();
    console.log('hello world');
  }

  render() {
    return <div>hello world</div>
  }
}

ReactDOM.render(<Hello></Hello>, document.getElementById('root'));

其中@packages是我在webpack中配置的路径别名,对应packages目录。es6

tpl.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="root">
    hello world;
  </div>
</body>
</html>

概述

至此,环境已经配的差很少了。只是实际运行的时候仍是须要安装一些包。此处忽略了装包的过程。可是实际项目运行中控制台仍是报了一些错。其中一个最纠结的地方github

This module must be shimmed by a specific renderer.

自环境配好后我遇到的第一个问题是这句话。起初觉得是react的问题。纠结了好几个小时候,才找到了问题的根源。web

问题并不来react这个包

既然问题不是react,那来自哪里呢。没错,来自react-dom,由于页面上总共就引用了两个包,非react则react-domjson

问题解决思路

经过错误信息处函数调用堆栈能够看出,该错误来源于一个ReactFiberHostConfig.js中。虽然不知道这里为何会有这个,可是仍是想去源仓库找找答案。看了react官方实际使用了rollup去打包代码。可是rollup里一大坨看不懂得代码。那怎么办呢。去搜索这个hostconfig.js是什么鬼。

貌似的答案

react为了实现将一样的结构,render到不一样的平台,使用了react-reconciler作了一个中间层。提供接口可让用户自定义render的实现,而且给出了一个render-dom的示例。可是无论使用哪一种render,都要提供一个hostconfig,源码中这个react-reconciler文件夹中引用的config老是会抛出一段错误,可是实际上,正确的config已经在文件夹中给出,只要将抛错这段代码给替换成引用正确的config便可。

概括总结

错误调用栈 react-dom-》react-reconciler-》hostconfig error

解决

react-reconclier中src下的ReactFiberHostConfig中的报错改成引用正确的config。贴上引用代码
export * from './forks/ReactFiberHostConfig.dom';

完结撒花

至此已经能够在浏览器中调试es6版本的react代码。不过这个环境配置过程当中并不是一路顺风。首先遇到错首先觉得是react的问题。纠结了好几个晚上(下班后才开始想),网上查阅了不少资料,也没想出因此然,最后发现是react-dom的问题,也纠结了很久,最终终于配起了这套环境。

喜欢的朋友点个赞哈。谢谢支持。

相关文章
相关标签/搜索