摘要:會(huì)有一探源碼的想法。理想的情況是直接引用源文件,也就是上倉(cāng)庫(kù)中,目錄下的代碼,直接閱讀的代碼。所以需要配置打包成。坑概述至此,環(huán)境已經(jīng)配的差不多了。不過這個(gè)環(huán)境配置過程中并非一帆風(fēng)順。
前言
閱讀源碼時(shí),有許多變量在程序運(yùn)行過程中不斷的產(chǎn)生,其中存放著什么東西,一直是一個(gè)比較頭疼的問題。不停的推導(dǎo)增加了驗(yàn)算的負(fù)擔(dān),隨著代碼逐漸的深入,也會(huì)產(chǎn)生一定的記憶負(fù)擔(dān)。如果靠腦袋去記,簡(jiǎn)單點(diǎn)的代碼還好。復(fù)雜的代碼。。。你懂的。
隨著react被廣泛使用,很多人會(huì)好奇react是怎么實(shí)現(xiàn)的。會(huì)有一探源碼的想法。如果直接閱讀react.development.js是很簡(jiǎn)單,頁(yè)面引入就好了。但是react.development.js終于是經(jīng)過編譯工具編譯過的代碼,很多的代碼看起來并不直觀。理想的情況是直接引用源文件,也就是github上react倉(cāng)庫(kù)中,packages目錄下的代碼,直接閱讀es6的代碼。
但是es6代碼瀏覽器支持并不友好。所以需要配置webpack打包成es5。同時(shí)需要配上sourceMap。這樣,既可以讓源碼跑在瀏覽器環(huán)境,也可以直接讀es6的代碼,而且可以隨時(shí)打斷點(diǎn),查看變量里保存的值。
那么,閑言少敘,開始本章的主題。
目錄結(jié)構(gòu) 概述這是我目前用的一個(gè)簡(jiǎn)單的目錄結(jié)構(gòu)。此次調(diào)試的代碼為react 16.4.0
詳情node_modules 存放依賴的包
packages github上的packages文件夾直接拿來用
test-env 測(cè)試用的目錄
index.js #引用react、react-dom的啟動(dòng)文件
index.less
tpl.html # html模板文件
webpack的配置 概要webpack的配置就是常規(guī)的babel,和一堆loader。為了提高打包速度,可以使用Happypack插件。如果覺得速度還不夠快,可以再引入DLLplugin。此處webpack的使用不是重點(diǎn),在此只是簡(jiǎn)單給出打包需要的基本配置
代碼如下:
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來標(biāo)識(shí) happypack處理那里類文件 id: "happyBabel", //如何處理 用法和loader 的配置一樣 loaders: [{ loader: "babel-loader?cacheDirectory=true", }], //共享進(jìn)程池 threadPool: happyThreadPool, //允許 HappyPack 輸出日志 verbose: true, }), new HappyPack({ //用id來標(biāo)識(shí) happypack處理那里類文件 id: "happyLess", //如何處理 用法和loader 的配置一樣 loaders: ["style-loader","css-loader","less-loader"], //共享進(jìn)程池 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"], }入口文件 概述
為了簡(jiǎn)化項(xiàng)目流程,此處用了一個(gè)最簡(jiǎn)單的tpl.html模板文件,通過webpackhtmlplugin引入了打包好后的帶sourcemap的js。
其中,js只是用react實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的Hello world并且用react-render渲染到頁(yè)面上。
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() { returnhello world} } ReactDOM.render(, document.getElementById("root"));
其中@packages是我在webpack中配置的路徑別名,對(duì)應(yīng)packages目錄。
tpl.html坑 概述Document hello world;
至此,環(huán)境已經(jīng)配的差不多了。只是實(shí)際運(yùn)行的時(shí)候還是需要安裝一些包。此處忽略了裝包的過程。但是實(shí)際項(xiàng)目運(yùn)行中控制臺(tái)還是報(bào)了一些錯(cuò)。其中一個(gè)最糾結(jié)的地方
This module must be shimmed by a specific renderer.自環(huán)境配好后我遇到的第一個(gè)問題是這句話。起初以為是react的問題。糾結(jié)了好幾個(gè)小時(shí)候,才找到了問題的根源。
問題并不來react這個(gè)包既然問題不是react,那來自哪里呢。沒錯(cuò),來自react-dom,因?yàn)轫?yè)面上總共就引用了兩個(gè)包,非react則react-dom
問題解決思路通過錯(cuò)誤信息處函數(shù)調(diào)用堆棧可以看出,該錯(cuò)誤來源于一個(gè)ReactFiberHostConfig.js中。雖然不知道這里為什么會(huì)有這個(gè),但是還是想去源倉(cāng)庫(kù)找找答案。看了react官方實(shí)際使用了rollup去打包代碼。但是rollup里一大坨看不懂得代碼。那怎么辦呢。去搜索這個(gè)hostconfig.js是什么鬼。
貌似的答案react為了實(shí)現(xiàn)將同樣的結(jié)構(gòu),render到不同的平臺(tái),使用了react-reconciler做了一個(gè)中間層。提供接口可以讓用戶自定義render的實(shí)現(xiàn),并且給出了一個(gè)render-dom的示例。但是不管使用哪種render,都要提供一個(gè)hostconfig,源碼中這個(gè)react-reconciler文件夾中引用的config總是會(huì)拋出一段錯(cuò)誤,但是實(shí)際上,正確的config已經(jīng)在文件夾中給出,只要將拋錯(cuò)這段代碼給替換成引用正確的config即可。
歸納總結(jié)錯(cuò)誤調(diào)用棧 react-dom-》react-reconciler-》hostconfig error
解決
react-reconclier中src下的ReactFiberHostConfig中的報(bào)錯(cuò)改為引用正確的config。貼上引用代碼
export * from "./forks/ReactFiberHostConfig.dom";完結(jié)撒花
至此已經(jīng)可以在瀏覽器中調(diào)試es6版本的react代碼。不過這個(gè)環(huán)境配置過程中并非一帆風(fēng)順。首先遇到錯(cuò)首先以為是react的問題。糾結(jié)了好幾個(gè)晚上(下班后才開始想),網(wǎng)上查閱了很多資料,也沒想出所以然,最后發(fā)現(xiàn)是react-dom的問題,也糾結(jié)了好久,最終終于配起了這套環(huán)境。
喜歡的朋友點(diǎn)個(gè)贊哈。謝謝支持。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/96666.html
摘要:閱讀本期周刊,你將快速入門,開啟甜蜜之旅。然則的原理負(fù)責(zé)發(fā)送以及處理消息,創(chuàng)建消息隊(duì)列并不斷從隊(duì)列中取出消息交給,則用于保存消息。 showImg(/img/bVCN99?w=900&h=385); 2016 年 8 月,Android 7.0 Nougat(牛軋?zhí)牵┱桨l(fā)布,那么問題來了,你 Marshmallow 了么(? -? ?) Cupcake、Donut、Gingerbre...
摘要:我們先來看下這個(gè)函數(shù)的一些神奇用法對(duì)于上述代碼,也就是函數(shù)來說返回值是。不管你第二個(gè)參數(shù)的函數(shù)返回值是幾維嵌套數(shù)組,函數(shù)都能幫你攤平到一維數(shù)組,并且每次遍歷后返回的數(shù)組中的元素個(gè)數(shù)代表了同一個(gè)節(jié)點(diǎn)需要復(fù)制幾次。這是我的 React 源碼解讀課的第一篇文章,首先來說說為啥要寫這個(gè)系列文章: 現(xiàn)在工作中基本都用 React 了,由此想了解下內(nèi)部原理 市面上 Vue 的源碼解讀數(shù)不勝數(shù),但是反觀...
摘要:第三篇腳手架依賴的核心庫(kù)的源碼解析。該篇是這個(gè)系列文章的第三篇主要是對(duì)的源碼進(jìn)行分析講解。的源碼十分簡(jiǎn)單但實(shí)現(xiàn)的功能卻是十分的強(qiáng)大。源碼概括源碼主要包含了兩部分公共方法和私有方法。 react作為當(dāng)前十分流行的前端框架,相信很多前端er都有蠢蠢欲動(dòng)的學(xué)習(xí)它的想法。工欲善其事,必先利其器。這篇文章就簡(jiǎn)單的給大家介紹一下如何我快速的搭建一個(gè)react前端開發(fā)環(huán)境。主要針對(duì)于react小白,...
閱讀 1756·2021-11-25 09:43
閱讀 1792·2021-11-24 10:41
閱讀 3111·2021-09-27 13:36
閱讀 818·2019-08-30 15:53
閱讀 3575·2019-08-30 15:44
閱讀 871·2019-08-30 14:03
閱讀 2581·2019-08-29 16:38
閱讀 1005·2019-08-29 13:23