资讯专栏INFORMATION COLUMN

react源码阅读环境配置

Songlcy / 3530人阅读

摘要:会有一探源码的想法。理想的情况是直接引用源文件,也就是上仓库中,目录下的代码,直接阅读的代码。所以需要配置打包成。坑概述至此,环境已经配的差不多了。不过这个环境配置过程中并非一帆风顺。

前言

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

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

目录结构 概述

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

详情

node_modules 存放依赖的包

packages github上的packages文件夹直接拿来用

test-env 测试用的目录

index.js #引用react、react-dom的启动文件

index.less

tpl.html # html模板文件

webpack的配置 概要

webpack的配置就是常规的babel,和一堆loader。为了提高打包速度,可以使用Happypack插件。如果觉得速度还不够快,可以再引入DLLplugin。此处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渲染到页面上。

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 
hello world
} } ReactDOM.render(, document.getElementById("root"));

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

tpl.html



  
  
  
  Document


  
hello world;
概述

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

This module must be shimmed by a specific renderer.

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

问题并不来react这个包

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

问题解决思路

通过错误信息处函数调用堆栈可以看出,该错误来源于一个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的问题,也纠结了好久,最终终于配起了这套环境。

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96666.html

相关文章

  • SegmentFault 技术周刊 Vol.4 - 这份 Android 有点甜

    摘要:阅读本期周刊,你将快速入门,开启甜蜜之旅。然则的原理负责发送以及处理消息,创建消息队列并不断从队列中取出消息交给,则用于保存消息。 showImg(/img/bVCN99?w=900&h=385); 2016 年 8 月,Android 7.0 Nougat(牛轧糖)正式发布,那么问题来了,你 Marshmallow 了么(¬ -̮ ¬) Cupcake、Donut、Gingerbre...

    jay_tian 评论0 收藏0
  • SegmentFault 技术周刊 Vol.4 - 这份 Android 有点甜

    摘要:阅读本期周刊,你将快速入门,开启甜蜜之旅。然则的原理负责发送以及处理消息,创建消息队列并不断从队列中取出消息交给,则用于保存消息。 showImg(https://segmentfault.com/img/bVCN99?w=900&h=385); 2016 年 8 月,Android 7.0 Nougat(牛轧糖)正式发布,那么问题来了,你 Marshmallow 了么(¬ -̮ ¬)...

    shinezejian 评论0 收藏0
  • 剖析 React 源码:先热个身

    摘要:我们先来看下这个函数的一些神奇用法对于上述代码,也就是函数来说返回值是。不管你第二个参数的函数返回值是几维嵌套数组,函数都能帮你摊平到一维数组,并且每次遍历后返回的数组中的元素个数代表了同一个节点需要复制几次。这是我的 React 源码解读课的第一篇文章,首先来说说为啥要写这个系列文章: 现在工作中基本都用 React 了,由此想了解下内部原理 市面上 Vue 的源码解读数不胜数,但是反观...

    sean 评论0 收藏0
  • react-start到co源码(三)

    摘要:第三篇脚手架依赖的核心库的源码解析。该篇是这个系列文章的第三篇主要是对的源码进行分析讲解。的源码十分简单但实现的功能却是十分的强大。源码概括源码主要包含了两部分公共方法和私有方法。 react作为当前十分流行的前端框架,相信很多前端er都有蠢蠢欲动的学习它的想法。工欲善其事,必先利其器。这篇文章就简单的给大家介绍一下如何我快速的搭建一个react前端开发环境。主要针对于react小白,...

    wind5o 评论0 收藏0
  • React Native工程中TSLint静态检查工具的探索之路

    摘要:第六步,语法树解析无论是方法还是方法中的实现都传入了这个参数,这个相当于文件的根节点,然后通过方法遍历整个语法树节点。 背景 建立的代码规范没人遵守,项目中遍地风格迥异的代码,你会不会抓狂? 通过测试用例的程序还会出现Bug,而原因仅仅是自己犯下的低级错误,你会不会抓狂? 某种代码写法存在问题导致崩溃时,只能全工程检查代码,这需要人工花费大量时间Review代码,你会不会抓狂? 以上这...

    taohonghui 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<