<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[dennis_jiang的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/dennis_jiang</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; dennis_jiang]]></copyright><item><title><![CDATA[使用mono-repo实现跨项目组件共享]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/112181925</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/112181925</guid><author>dennis_jiang</author><pubDate>Mon, 04 Jan 2021 15:49:01 +0800</pubDate><description><![CDATA[本文会分享一个我在实际工作中遇到的案例，从最开始的需求分析到项目搭建，以及最后落地的架构的整个过程。最终实现的效果是使用mono-repo实现了跨项目的组件共享。在本文中你可以看到：

从接到需求到深入分析并构建架构的整个思考过程。
mono-repo的简单介绍。
mono-repo适用的场景分析。
产出一个可以跨项目共享组件的项目架构。

本文产出的架构模板已经上传到GitHub，如果你刚好需要一个mono-repo + react的模板，直接clone下来吧：https://github.com/den]]></description><category></category></item><item><title><![CDATA[轻松理解HTTP缓存策略]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/111589275</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/111589275</guid><author>dennis_jiang</author><pubDate>Wed, 23 Dec 2020 14:25:23 +0800</pubDate><description><![CDATA[上一篇文章我写了koa-static的源码解析，其中用到了HTTP的缓存策略，给返回的静态文件设置了一些缓存的头，比如Cache-Control之类的。于是我就跟朋友讨论了一下HTTP的缓存策略：
朋友说：“HTTP里面控制缓存的头(header)太多了，啥Cache-Control，ETag，Last-Modified，一大堆，乱七八糟的，而且之间逻辑关系不强，要掌握基本靠背！”
我有点惊讶：“为什么要去背这个呢？所有的技术都是为了解决问题而存在的，不了解问题而去单纯的学习技术，去，背，去，死记，确实很枯]]></description><category></category></item><item><title><![CDATA[手写koa-static源码，深入理解静态服务器原理]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/110805331</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/110805331</guid><author>dennis_jiang</author><pubDate>Mon, 07 Dec 2020 11:51:38 +0800</pubDate><description><![CDATA[这篇文章继续前面的Koa源码系列，这个系列已经有两篇文章了：

第一篇讲解了Koa的核心架构和源码：手写Koa.js源码
第二篇讲解了@koa/router的架构和源码：手写@koa/router源码

本文会接着讲一个常用的中间件----koa-static，这个中间件是用来搭建静态服务器的。
其实在我之前使用Node.js原生API写一个web服务器已经讲过怎么返回一个静态文件了，代码虽然比较丑，基本流程还是差不多的：

通过请求路径取出正确的文件地址
通过地址获取对应的文件
使用Node.js的API]]></description><category></category></item><item><title><![CDATA[速度提高几百倍，记一次数据结构在实际工作中的运用]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/110078575</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/110078575</guid><author>dennis_jiang</author><pubDate>Tue, 24 Nov 2020 14:48:42 +0800</pubDate><description><![CDATA[这段时间写了一堆源码解析，这篇文章想换换口味，跟大家分享一个我工作中遇到的案例。毕竟作为一个打工人，上班除了摸鱼看源码外，砖还是要搬的。本文会分享一个使用恰当的数据结构来进行性能优化，从而大幅提高响应速度的故事，提高有几百倍那么多。
事情是这样的，我现在供职一家外企，我们有一个给外国人用的线下卖货的APP，卖的商品有衣服，鞋子，可乐什么的。某天，产品经理找到我，提了一个需求：需要支持三层的产品选项。听到这个需求，我第一反应是我好像没有见到过三层的产品选项，毕竟我也是一个十来年的资深剁手党，一般的产品选项好像]]></description><category></category></item><item><title><![CDATA[手写@koa/router源码]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/109720230</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/109720230</guid><author>dennis_jiang</author><pubDate>Mon, 16 Nov 2020 14:19:27 +0800</pubDate><description><![CDATA[上一篇文章我们讲了Koa的基本架构，可以看到Koa的基本架构只有中间件内核，并没有其他功能，路由功能也没有。要实现路由功能我们必须引入第三方中间件，本文要讲的路由中间件是@koa/router，这个中间件是挂在Koa官方名下的，他跟另一个中间件koa-router名字很像。其实@koa/router是fork的koa-router，因为koa-router的作者很多年没维护了，所以Koa官方将它fork到了自己名下进行维护。这篇文章我们还是老套路，先写一个@koa/router的简单例子，然后自己手写@ko]]></description><category></category></item><item><title><![CDATA[手写Koa.js源码]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/109572824</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/109572824</guid><author>dennis_jiang</author><pubDate>Mon, 09 Nov 2020 11:23:39 +0800</pubDate><description><![CDATA[用Node.js写一个web服务器，我前面已经写过两篇文章了：

第一篇是不使用任何框架也能搭建一个web服务器，主要是熟悉Node.js原生API的使用：使用Node.js原生API写一个web服务器
第二篇文章是看了Express的基本用法，更主要的是看了下他的源码：手写Express.js源码

Express的源码还是比较复杂的，自带了路由处理和静态资源支持等等功能，功能比较全面。与之相比，本文要讲的Koa就简洁多了，Koa虽然是Express的原班人马写的，但是设计思路却不一样。Express更多]]></description><category></category></item><item><title><![CDATA[手写Express.js源码]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/109446832</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/109446832</guid><author>dennis_jiang</author><pubDate>Mon, 02 Nov 2020 12:36:45 +0800</pubDate><description><![CDATA[上一篇文章我们讲了怎么用Node.js原生API来写一个web服务器，虽然代码比较丑，但是基本功能还是有的。但是一般我们不会直接用原生API来写，而是借助框架来做，比如本文要讲的Express。通过上一篇文章的铺垫，我们可以猜测，Express其实也没有什么黑魔法，也仅仅是原生API的封装，主要是用来提供更好的扩展性，使用起来更方便，代码更优雅。本文照例会从Express的基本使用入手，然后自己手写一个Express来替代他，也就是源码解析。
本文可运行代码已经上传GitHub，拿下来一边玩代码，一边看文章]]></description><category></category></item><item><title><![CDATA[使用Node.js原生API写一个web服务器]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/109288949</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/109288949</guid><author>dennis_jiang</author><pubDate>Mon, 26 Oct 2020 14:22:16 +0800</pubDate><description><![CDATA[Node.js是JavaScript基础上发展起来的语言，所以前端开发者应该天生就会一点。一般我们会用它来做CLI工具或者Web服务器，做Web服务器也有很多成熟的框架，比如Express和Koa。但是Express和Koa都是对Node.js原生API的封装，所以其实不借助任何框架，只用原生API我们也能写一个Web服务器出来。本文要讲的就是不借助框架，只用原生API怎么写一个Web服务器。因为在我的计划中，后面会写Express和Koa的源码解析，他们都是使用原生API来实现的。所以本文其实是这两个源码]]></description><category></category></item><item><title><![CDATA[手写Redux-Saga源码]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/109161548</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/109161548</guid><author>dennis_jiang</author><pubDate>Mon, 19 Oct 2020 15:22:28 +0800</pubDate><description><![CDATA[上一篇文章我们分析了Redux-Thunk的源码，可以看到他的代码非常简单，只是让dispatch可以处理函数类型的action，其作者也承认对于复杂场景，Redux-Thunk并不适用，还推荐了Redux-Saga来处理复杂副作用。本文要讲的就是Redux-Saga，这个也是我在实际工作中使用最多的Redux异步解决方案。Redux-Saga比Redux-Thunk复杂得多，而且他整个异步流程都使用Generator来处理，Generator也是我们这篇文章的前置知识，如果你对Generator还不熟悉，]]></description><category></category></item><item><title><![CDATA[Redux异步解决方案之Redux-Thunk原理及源码解析]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/108484304</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/108484304</guid><author>dennis_jiang</author><pubDate>Wed, 09 Sep 2020 10:33:39 +0800</pubDate><description><![CDATA[前段时间，我们写了一篇Redux源码分析的文章，也分析了跟React连接的库React-Redux的源码实现。但是在Redux的生态中还有一个很重要的部分没有涉及到，那就是Redux的异步解决方案。本文会讲解Redux官方实现的异步解决方案----Redux-Thunk，我们还是会从基本的用法入手，再到原理解析，然后自己手写一个Redux-Thunk来替换它，也就是源码解析。
Redux-Thunk和前面写过的Redux和React-Redux其实都是Redux官方团队的作品，他们的侧重点各有不同:

Re]]></description><category></category></item><item><title><![CDATA[手写一个React-Redux，玩转React的Context API]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/107222438</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/107222438</guid><author>dennis_jiang</author><pubDate>Thu, 09 Jul 2020 10:30:12 +0800</pubDate><description><![CDATA[上一篇文章我们手写了一个Redux，但是单纯的Redux只是一个状态机，是没有UI呈现的，所以一般我们使用的时候都会配合一个UI库，比如在React中使用Redux就会用到React-Redux这个库。这个库的作用是将Redux的状态机和React的UI呈现绑定在一起，当你dispatch action改变state的时候，会自动更新页面。本文还是从它的基本使用入手来自己写一个React-Redux，然后替换官方的NPM库，并保持功能一致。
本文全部代码已经上传GitHub，大家可以拿下来玩玩：https:]]></description><category></category></item><item><title><![CDATA[手写一个Redux，深入理解其原理]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/107104559</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/107104559</guid><author>dennis_jiang</author><pubDate>Fri, 03 Jul 2020 14:04:35 +0800</pubDate><description><![CDATA[Redux可是一个大名鼎鼎的库，很多地方都在用，我也用了几年了，今天这篇文章就是自己来实现一个Redux，以便于深入理解他的原理。我们还是老套路，从基本的用法入手，然后自己实现一个Redux来替代源码的NPM包，但是功能保持不变。本文只会实现Redux的核心库，跟其他库的配合使用，比如React-Redux准备后面单独写一篇文章来讲。有时候我们过于关注使用，只记住了各种使用方式，反而忽略了他们的核心原理，但是如果我们想真正的提高技术，最好还是一个一个搞清楚，比如Redux和React-Redux看起来很像，]]></description><category></category></item><item><title><![CDATA[手写React的Fiber架构，深入理解其原理]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106928259</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106928259</guid><author>dennis_jiang</author><pubDate>Tue, 23 Jun 2020 17:29:48 +0800</pubDate><description><![CDATA[熟悉React的朋友都知道，React支持jsx语法，我们可以直接将HTML代码写到JS中间，然后渲染到页面上，我们写的HTML如果有更新的话，React还有虚拟DOM的对比，只更新变化的部分，而不重新渲染整个页面，大大提高渲染效率。到了16.x，React更是使用了一个被称为Fiber的架构，提升了用户体验，同时还引入了hooks等特性。那隐藏在React背后的原理是怎样的呢，Fiber和hooks又是怎么实现的呢？本文会从jsx入手，手写一个简易版的React，从而深入理解React的原理。
本文主要实]]></description><category></category></item><item><title><![CDATA[不知道怎么提高代码质量？来看看这几种设计模式吧！]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106573040</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106573040</guid><author>dennis_jiang</author><pubDate>Fri, 05 Jun 2020 16:18:17 +0800</pubDate><description><![CDATA[提高代码质量的目的
程序猿的本职工作就是写代码，写出高质量的代码应该是我们的追求和对自己的要求，因为：


高质量的代码往往意味着更少的BUG，更好的模块化，是我们扩展性，复用性的基础
高质量的代码也意味着更好的书写，更好的命名，有利于我们的维护


什么代码算好的质量
怎样来定义代码质量的"好"，业界有很多标准，本文认为好的代码应该有以下特点：


代码整洁，比如缩进之类的，现在有很多工具可以自动解决这个问题，比如eslint。
结构规整，没有漫长的结构，函数拆分合理，不会来一个几千行的函数，也不会有几十]]></description><category></category></item><item><title><![CDATA[不知道怎么提高代码可扩展性？来看看优秀框架源码中的这几种设计模式吧!]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106427560</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106427560</guid><author>dennis_jiang</author><pubDate>Fri, 29 May 2020 16:08:24 +0800</pubDate><description><![CDATA[为什么要提高代码扩展性
我们写的代码都是为了一定的需求服务的，但是这些需求并不是一成不变的，当需求变更了，如果我们代码的扩展性很好，我们可能只需要简单的添加或者删除模块就行了，如果扩展性不好，可能所有代码都需要重写，那就是一场灾难了，所以提高代码的扩展性是势在必行的。怎样才算有好的扩展性呢？好的扩展性应该具备以下特征:


需求变更时，代码不需要重写。
局部代码的修改不会引起大规模的改动。有时候我们去重构一小块代码，但是发现他跟其他代码都是杂糅在一起的，里面各种耦合，一件事情拆在几个地方做，要想改这一小块必]]></description><category></category></item><item><title><![CDATA[设计模式第二弹: 不知道怎么提高代码复用性？看看这几种设计模式吧！]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106333032</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106333032</guid><author>dennis_jiang</author><pubDate>Mon, 25 May 2020 14:45:01 +0800</pubDate><description><![CDATA[本文是设计模式的第二篇文章，第一篇文章是不知道怎么封装代码？看看这几种设计模式吧！，后面还会有提高扩展性，提高代码质量的设计模式，点个关注不迷路，哈哈~
想必大家都听说过DRY原则，其实就是Don't repeat yourself(不要重复你自己)，意思就是不要重复写一样的代码，换句话说就是要提高代码的复用性。那什么样的代码才算有好的复用性呢？


对象可以重复利用。这个其实有点像我们关系型数据库的设计原则，数据表和关系表是分开的，数据表就是单纯的数据，没有跟其他表的关系，也没有业务逻辑，关系表才是存储具]]></description><category></category></item><item><title><![CDATA[不知道怎么封装代码？看看这几种设计模式吧！]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106280518</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106280518</guid><author>dennis_jiang</author><pubDate>Fri, 22 May 2020 15:09:47 +0800</pubDate><description><![CDATA[为什么要封装代码？
我们经常听说：“写代码要有良好的封装，要高内聚，低耦合”。那怎样才算良好的封装，我们为什么要封装呢？其实封装有这样几个好处：


封装好的代码，内部变量不会污染外部。
可以作为一个模块给外部调用。外部调用者不需要知道实现的细节，只需要按照约定的规范使用就行了。
对扩展开放，对修改关闭，即开闭原则。外部不能修改模块，既保证了模块内部的正确性，又可以留出扩展接口，使用灵活。


怎么封装代码？
JS生态已经有很多模块了，有些模块封装得非常好，我们使用起来很方便，比如jQuery，Vue等。如]]></description><category></category></item><item><title><![CDATA[JS作用域和变量提升看这一篇就够了]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106157904</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106157904</guid><author>dennis_jiang</author><pubDate>Sat, 16 May 2020 13:15:45 +0800</pubDate><description><![CDATA[作用域是JS中一个很基础但是很重要的概念，面试中也经常出现，本文会详细深入的讲解这个概念及其他相关的概念，包括声明提升，块级作用域，作用域链及作用域链延长等问题。
什么是作用域
第一个问题就是我们要弄清楚什么是作用域，这不是JS独有的概念，而是编程领域中通用的一个概念。我们以下面这个语句为例:
let x = 1;

这一个简单的语句其实包含了几个基本的概念:


变量(variable)：这里x就是一个变量，是用来指代一个值的符号。
值(value)：就是具体的数据，可以是数字，字符串，对象等。这里1就是]]></description><category></category></item><item><title><![CDATA[JS做类型检测到底有几种方法？看完本文就知道了！]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/106020074</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/106020074</guid><author>dennis_jiang</author><pubDate>Sat, 09 May 2020 15:22:47 +0800</pubDate><description><![CDATA[JS有很多数据类型，对于不同数据类型的识别和相互转换也是面试中的一个常考点，本文主要讲的就是类型转换和类型检测。
数据类型
JS中的数据类型主要分为两大类：原始类型(值类型)和引用类型。常见的数据类型如下图所示：

原始数据类型存在栈中，引用类型在栈中存的是一个引用地址，这个地址指向的是堆中的一个数据对象。需要注意的是null在这里我们算在原始类型里面，但是你用typeof的时候会发现他是object，原因是就算他是一个对象，那他应该在栈中存一个引用地址，但是他是一个空对象，所以这个地址为空，也就是不对应堆]]></description><category></category></item><item><title><![CDATA[从Generator入手读懂co模块源码]]></title><link>https://blog.youkuaiyun.com/dennis_jiang/article/details/105656251</link><guid>https://blog.youkuaiyun.com/dennis_jiang/article/details/105656251</guid><author>dennis_jiang</author><pubDate>Tue, 21 Apr 2020 13:35:31 +0800</pubDate><description><![CDATA[这篇文章是讲JS异步原理和实现方式的第四篇文章，前面三篇是：
setTimeout和setImmediate到底谁先执行，本文让你彻底理解Event Loop
从发布订阅模式入手读懂Node.js的EventEmitter源码
手写一个Promise/A+,完美通过官方872个测试用例
本文主要会讲Generator的运用和实现原理，然后我们会去读一下co模块的源码，最后还会提一下async/aw...]]></description><category></category></item></channel></rss>