Webpack原理+React原理+Redux+React Router

一、webpack原理+步骤

模块函数是webpack能处理的最小单位,对应打包前的一个文件,具体格式是:function(module)

webpack的工作原理:
webpack为每个require的资源生成一个唯一的moduleId,这样在打包的时候,即使多处引用了某资源,也只会打包一份,而不会重复打包。最后打包生成的chunkId,作用是在加载的时候,防止重复加载的模块,优先取缓存。

1、全局注册一个启动函数window.webpackJsonp(chunkIds,modules,立即执行的moduleIds)
2、打包后生成的每个chunk都是 webpackJsonp([1], [,,,,(function(module, exports, __webpack_require__){...}),,], [58]) 这样的格式:
    第一个参数是当前chunk的id,以及当前chunk依赖的chunkIds,
    第二个参数是打包到当前chunk的模块函数,所有chunk的第二个参数长度应该是一样的,因为为了防止模块重复加载,所以模块id都是唯一的,比如:某次打包一共有2个chunk、15个module,模块0-9打包到chunk0下,则chunk0的第二个参数的0-9都是模块函数对象,而chunk1的第二个参数的0-9则是空,其10-14又是具体的模块函数对象
    第三个参数是当前chunk加载完成后 立即执行的模块id,一般入口chunk都是有第三个参数的。
3、全局webpackJsonp执行的过程中,会记录下已经加载过得chunk和模块以及所有的模块函数对象,分别保存在installedChunk、installedModule和modules对象中,每次访问某个chunk或者模块时,优先读取缓存,提高性能。
4、__webpack_require__函数是用于读取模块的。

webpack具体的打包流程是:

1、利用optimist整合webpack.config.js和命令行中的所有参数,生成options对象,传入webpack webpack启动,执行run函数
2、生成compiler编译对象:主要完成模块的构建,包括依赖模块的构建(AST依赖抽象树),中间结合各种loaders\plugins来进行处理不同的资源,统一转化成js模块
3、构建完成后,根据配置进行代码分割、提取、封装
4、利用不同的模板:主入口模板mainTemplate、非入口模板chunkTemplate生成编译打包后的文件(mainTemplate与chunkTemplate的区别在于带不带启动代码)
5、最后完成文件的输出

      webpack源码分析---后续总结
      webpack启动后,创建compiler对象,开始compile,主要包含下面的几步:
      1、make -> build:(建立模块,loader处理,分析依赖)分析配置的主入口,生成模块对象,调用loaders处理成js模块,构建AST抽象树,分析模块的依赖数组
      2、seal:(封装结果)封装 根据模块依赖关系+配置(如提取公共模块)等,将所有的modules对象进行封装,module分配进不同的chunk中;并输出webpack模块加载器(一段代码:注册webpackJsonp)
      3、emit:(输出文件)输出 将最终的chunk文件输出到配置好的输出路径下。根据chunk类型的不同,使用不同的模板生成最终的chunkjs

参考:
细说 webpack 之流程篇---淘宝前端团队
这篇文章讲了webpack的原理 其中manifest讲的比较清晰

webpack热更新原理(websocket貌似过时了):
1、利用html5的websocket协议,在客户端和服务器端建立起一个长链接,当服务器端检测到文件变化时,主动向浏览器端发起一个更新的消息,浏览器收到消息,判断是css更新还是js、html更新以进行局部更新或者全局更新,从而减少开发者手动刷新浏览器的繁琐。
【参考】

2、EventSource 是 HTML5 中 Server-sent Events 规范的一种技术实现。EventSource 接口用于接收服务器发送的事件。它通过HTTP连接到一个服务器,以text/event-stream 格式接收事件, 不关闭连接。通过 EventSource 服务端可以主动给客户端发现消息,使用的是 HTTP协议,单项通信,只能服务器向浏览器发送; 与 WebSocket 相比轻量,使用简单,支持断线重连。
【参考】

loader的原理:
将各种不同类型的资源最终都整合成js模块,以便webpack处理。

二、React的背景+原理:

传统的web开发是从服务器接收到数据,然后进行dom的更新,比如之前的jQuery方式,每次数据的更新,都需要获取到dom元素,进行相应的增删改操作。这种方式在频繁的数据刷新下会导致性能问题,体验很差。React的产生极大的解决了这个问题,它采用了虚拟dom算法,初次渲染生成一颗虚拟dom树,每次收到新数据render前,将新数据下的dom树和之前的dom树进行对比,只将发生变化的部分进行dom更新,而且会将临近的几次dom更新进行合并处理,极大的避免了频繁的dom更新导致的性能问题。

具体的dom diff算法关键点有:

  1. 对dom树只进行同层的比较,秉承不同类型肯定是不同元素的原则,只要类型不同即替换整棵树,后续的子节点不再进行比较,降低算法复杂度;
  2. 对于列表节点,使用key属性,在每次渲染更新的时候,可以最大限度的进行dom元素复用;

三、redux相关
react等组件里面,都是以state、props等进行数据的存储和传递的,要想让几个组件共享数据,就只能在父级组件的state内存储数据,一级一级的向子组件传递。当项目很大、组件很多时,一级一级的传递就显得很繁琐。redux解决了这个问题,可以把redux理解成一个状态机,是最顶层父级组件里的state,通过一些机制,可以直接通过mapStateToProps、connect将顶级state直接作为props传递给需要的组件。其中相关的概念有reducer同步改变数据、effect异步改变数据、action发起请求、dispatch等。

四、react router原理
底层利用history模块实现。具体如何做到url与UI保持一致的:history监测到url的变化,发起ajax获取对应的component,实现UI的更新,同时进行url的替换,具体的底层是调用history.pushState、popState、replaceState等api实现浏览器前进、回退的。
【参考】

推荐阅读更多精彩内容