本文转载自微信公众号《前端分享》,作者前端分享。转载本文请联系前端分享♂。1前言提到源码,脑海中可能会浮现四个字。我太难了。阅读源码对于我们来说似乎是遥不可及的事情,因为在日常工作中,我们基本已经熟练到可以满足工作需要了。即使我们想阅读源码,也会被源码复杂的逻辑拒之门外。阴影在我们脑海中挥之不去。那么我们真的有必要阅读源码吗?从经历过的人的角度来看,答案是肯定的。阅读源码不仅仅是在源码层面,还会带来一些额外的价值。笔者阅读了大量源码,主流的前端框架vue2.0、vue3.0、react、node框架express、koa,及其衍生生态react-router、react-redux、dva等。阅读源码的过程痛苦吗?感觉过程是痛苦的,但是看完之后觉得收获很多,觉得付出是值得的。下面我们一起讨论,一起阅读源码。二为什么要阅读源代码?1考虑面试的面试问题?假设这是一次采访。面试官:说说vue2.0的响应式原理?第一申请人:object.defineproperty()拦截器属性,拦截set,get。打分:4-5分这种回答似乎很难让我信服,只能证明面试官对这个知识点有所准备。第二申请人:在第一申请人的基础上,他提到了收集依赖的dep对象,负责渲染更新的渲染观察者,递归响应等,能够介绍他们的原理和作用。打分:6-7分这样的回答已经符合标准了。至少讲了vue响应式的核心,说明应聘者至少有深入的了解。第三申请人:一方面,从初始化数据开始,到解析模板模板,收集依赖。另一方面可以解释从数据变化,通知渲染watcher更新,到页面变化的全过程。打分:8-10分这种回答非常完美。可以从源码的角度入手,说明申请者对原理的理解很深,并且看过源码。从一道面试题中,可以看出应聘者对框架的认知程度。而阅读源码是从底层全面理解框架的最好方式。而且如果你把源代码弄清楚了。能打动面试官。竟然能‘吊’面试官????。2.在使用框架的过程中更清晰的阅读源码,可以了解底层是如何工作的。如果你在工作中遇到某些问题,如果你阅读了源代码,你就会找到解决方案,问题也就迎刃而解了。bug案例引发的思考之前看到有同事遇到过这样的问题。可能业务场景比这个更复杂,大致如上。有一个问题就是每次改变列表然后重新选择选项,你会发现绑定的值数据改变了,但是视图没有改变。如果你对vue中的diff算法没有一定的了解,肯定会被这种现象蒙蔽。明明数据变了,为什么视图没有变呢?什么?如果你看过diff算法和子节点patch过程,就会知道发现这个问题主要来自于使用index作为key。在一次更新中,虽然数据发生了变化,但是根据索引,重用了错误的元素节点,导致视图与数据不对应的情况。对于框架或者开源库,如果我们在使用中遇到问题,与其在GitHub上提issue等待解决,不如亲自去看看源码,说不定答案就在里面。俗话说,蓦然回首,那人在灯火阑珊处。3提高编程能力,拓展知识盲点我个人认为阅读源码绝对是提高编程能力,拓展知识点的捷径。为什么这么说。先来看两个简短的经典代码片段:no1reduxcomposeexportdefaultfunctioncompose(...funcs){if(funcs.length===0){returnarg=>arg}if(funcs.length===1){returnfuncs[0]}returnfuncs.reduce((a,b)=>(...args)=>a(b(...args)))}这是一个前端领域的经典中间件案例,代码虽是简化,却堪称神来之笔。我们可以学习源码中的编程技巧,即使写不出上面这么经典的功能,也能明白什么时候用继承,什么时候用闭包。在阅读源码的过程中,会有很多高级用法,我们很少用到api,可以有效的扫盲知识点。vue3.0/reactivity/src/reactive.tsconstrawToReactive=newWeakMap()constreactiveToRaw=newWeakMap()constrawToReadonly=newWeakMap()constreadonlyToRaw=newWeakMap()vue3.0中保存依赖收集关系的几个WeakMap引发了我对WeakMaps和垃圾收集机制的思考?WeakMaps维护的是对key名引用的对象的弱引用,即垃圾回收机制不考虑这个引用。一旦对被引用对象的其他引用被清除,垃圾回收机制就会释放该对象占用的内存。也就是说,一旦不再需要,WeakMap中的键对象和对应的键值对就会自动消失,不需要手动删除引用。阅读源码,一方面帮助我们写出如诗如画的代码,另一方面也增长了知识面。总之,真的很香!4培养设计思维和架构能力优秀的源码有全局观、战略思维、架构能力的中流砥柱,这是一个正在进阶或计划进阶的工程师最缺乏的。也许你正在疯狂补习这个知识点,疯狂看这篇博客,疯狂刷编程题,但是当你接手一个大型的工程项目时,你还是会手足无措,最终会乱七八糟。为什么是这样?或许真的是缺乏设计思维和架构能力。人生三境界与阅读源码的三境界相同。慢慢地,你自己的编程能力就会潜移默化地受到影响。刚开始看源码的时候,看自己的代码还是自己的代码。但是慢慢的,你会发现你写的代码已经受到了源码的影响,已经不是当初的样子了。当你日复一日的坚持,你就会明白源码真正的架构设计,并且能够自己设计架构,代码是有灵魂的,你会发现你的代码还是你自己的代码,原因就在于你进步了,你能够掌控全局。三如何阅读源码上面介绍了阅读源码的好处,接下来我们就来说说如何有效地阅读源码。1打散整体冻三尺非一日之寒,阅读源码也非一朝一夕之事。我们必须计划阅读源代码。一天抽出时间看一点,然后重点做笔记,可以是md,也可以是手写笔记。总之,要记录核心内容,因为第一,好记不如烂笔,更能加深印象。二是每次阅读前把上次的笔记拿出来,做到完美衔接。把整个源码分成多个模块,一点一点消化。不要想着一口气看完源码。这是不现实的。这是笔者在阅读分析vue3.0源码过程中记录的笔记。在阅读分析react源码的过程中,笔记记录:2三思而后行。这就是笔者阅读源码的精髓所在。仔细想想,看源码的时候问why?带着问题去看源码,事半功倍。你为什么这么说?如果不带着问题去阅读,就会处于一种漫无目的、盲目的状态,尤其是在看枯燥繁琐的源代码时,会注意力不集中,久而久之就会昏昏欲睡,而你将无法坚持。在阅读源码之前,先思考几个问题,带着这些问题去源码中寻找答案。例1:在介绍vue3.0响应式原理之前,先问几个问题:1如何构建vue3.0的响应式,reactiveAPI到底是做什么的?2effect和reactive之间有什么关系?effect如何替换watcher?3如何收集依赖?4如何通过this.achange更新视图。例2在阅读react-redux时,我首先会问这些问题:1为什么在root根组件上使用react-reduxProvider组件包?2react-redux如何配合redux实现状态变化更新视图呢?3provide如何存储当前的reduxstore,如何传递给各个需要订阅状态的组件?4connect如何连接我们的业务组件,然后更新订阅的组件?5connect如何通过第一个参数mapStateToProps订阅对应的状态?6connect如何结合props和redux状态?带着这些问题去阅读源码,你会仔细的通过源码找到这些问题的答案,找到答案并把原理讲清楚,也会有很好的成就感。3提取精华这一步对于阅读源码也是非常重要的。我们必须学会从源代码中提取精华。以react为例,react的单个函数可能有几百行,甚至几千行,但不包括服务端渲染和开发环境警告。__dev__,上下文处理,还有一些判断等等,真正核心的逻辑代码,可能就几行,也可能十几行,所以我们不需要把源码中的每一行代码都推掉,只需要搞清楚核心逻辑不错。我们以react的源码为例:在文件react/react-reconciler/ReactFiberClassComponent.js下,有一个constructClassInstance方法来新建我们的组件实例。这个方法有200行左右,但是经过我细化后,代码如下,context);/*对于当前组件实例,挂起组件渲染update的updater对象*/adoptClassInstance(workInProgress,instance);}核心代码只有几行,所以阅读源码的过程当中,炼化精华也很重要。4真枪实弹的实践是检验真理的唯一标准。要想搞清楚源码,千万不要停留在光看的层面,还要真正把源码跑起来。这样我们就可以在github上clone源码了。然后在关键上下文中,您可以调试器或控制台。以下是步骤:从github下载文件。然后运行调试器或控制台。接下来将源码单独解压打包。放入我们的demo工程中进行验证。此时我们必须改变路径。因为我们的包本来是放在node_modules里面的,现在路径变了,所以要注意路径问题。5因材施教并不是所有的框架源码都需要固定的模式来解析。笔者在这一点上吃了不少苦头。让我们从一些背景开始。笔者阅读的是vue2.0,采用的是集中阅读,即从新的vue为入口,逐步深入到代码中。最后串联模块。看完vue2.0的核心原理,想用同样的模式看react,发现这个方案根本行不通,因为react有很多模块,react,react-reconciler,react-dom,scheduler,有几千个函数和方法,看着就蒙了。即使是调试器,作用也很小,也不可能将各个模块的功能串联起来形成一个系统。后来开始看一些大佬的文章,先了解一下每一块是干什么的,干什么的,然后一块块串起来。最后去阅读源码,发现效果很好。案例:vue和reactvue集中阅读源码vue源码适合集中阅读,从newvue()开始,到初始化数据,构建responsive,patchelement节点,解析template模板,注入依赖,挂载真实dom,一应俱全走,一条线串在一起。react发散阅读源码,react需要发散阅读的方法,就是你需要先了解,reconciler,scheduler,expirationtime,requestkeyframe等等,它是干什么的,干什么的,然后像搭积木一样,建立起来。6水滴石穿,坚持做值得做的事,然后努力把坚持做的事做好。既然选择阅读源码,就必须坚持下去。刚开始看源码的时候,很痛苦。好几次想放弃,后来还是按照上面的方法坚持了下来。终于,我养成了一个好习惯。现在我可以完全专心阅读源码,过程也没有以前那么枯燥了。我听说过21天的效果。日复一日地坚持下去,很快就会养成阅读源码的好习惯。我相信那个时候,当我们尝试使用一个新的包时,例如,我们会情不自禁地先去github上看看。拉下源码看看。四收获与总结看源码收获的习惯坚持了快两年了,收获感觉还是挺多的。首先,在知识储备、编程和设计架构方面有了很大的进步,也尝试写了自己的开源项目,并下定决心要维护。Rux是一个redux和react-redux状态管理工具react-keepalive-router缓存页面路由总结以上是我在阅读源码过程中的感受和理解,如果你能坚持下去,就会有一道美丽的风景。