《深刻浅出webpack》有感

对于前端仔来讲,相信你们对webpack都再熟悉不过了,可是你对webpack的了解程度又有多深呢,笔者花了几天时间看了一下《深刻浅出webpack》,虽说书中大部分介绍的是配置和使用相关的,可是若是你对webpack的配置、使用、原理和构建流程更加熟悉的话,对于你的开发能够说是百里无一害!本文不会局限于介绍配置,也不会详细介绍打包原理(后面打算写一篇有关webpack打包原理的~),更多着重于webpack打包的思想介绍。

没有打包构建的日子

nodejs的出现对于构建工具具备重要的意义,在没有nodejs以前,js只能执行在浏览器环境下,因此意味着对发布前的js文件要进行处理,十分局限,没有打包工具,只能用PHP脚原本处理文件,甚至还须要借助一些在线压缩网站,开发体验十分差劲,在史前时代存在如下几个痛点:
一、缺少文件处理工具,对文件进行编译或其余预处理,进行打包压缩等工做;
二、缺少文件的模块化,引入第三方库直接用cdn引入,须要处理依赖管理,人为控制脚本的加载顺序,而且存在全局变量命名冲突的问题;
三、缺少代码校验和自动化测试,在代码被提交到仓库前须要校验代码是否符合规范,以及单元测试是否经过。html

有了打包构建工具的日子

随着nodejs的诞生,咱们能够在开发环境下书写nodejs代码脚本,对咱们的前端代码作预处理,编译压缩等工做,最初诞生的是grunt和gulp,Grunt和Gulp都属于任务流工具Tast Runner,二者都是经过配置好配置文件,可是相比之下,gulp经过函数式编写配置文件,以及前端人员所熟悉的链式调用,让你们以为更易懂更易上手,gulp自己借鉴了grunt的经验进行升级和加入一些新特性。正由于流管理多任务配置输出方式的提升,人们逐渐选择使用Gulp而放弃grunt。
有了grunt和gulp,文件压缩处理的工做解决了,代码校验和测试也能够处理了,可是模块化仍没有结果?
其实前端的痛点还远不止模块化那么简单,频繁的DOM节点处理,JS里杂糅了交互逻辑、请求逻辑、数据处理和校验逻辑、DOM操做逻辑,致使JQ书写的代码就更意大利炒大便,呸!意大利炒面同样。在团队开发中,可能你的代码要给别人维护,这就很是痛苦了。前端

clipboard.png

webpack诞生记

一、模块化思想

隔离不一样的js文件,模块化开发,仅暴露当前模块所须要的其余模块,这是模块化思想一想要传递给咱们的。nodejs诞生后,后端所采起的模块化思想是commonjs,然而,不一样于后端,前端的代码运行在浏览器端,有两点不一样之处:
一、没有nodejs执行环境,不支持module.exports的书写格式;
二、后端require一个文件,是读取本地文件的形式,速度极快,而对于前端而言,须要去动态加载一个js文件,存在额外耗时。
因而AMD思想应运而生,对此的相应实现是requireJS,容许你定义好模块名称、模块依赖以及当前的模块代码(function),经过广度优先遍历的方式,递归加载父模块所依赖的子模块,可是这也暴露出了一些问题:
一、经过js加载执行后再去加载其依赖的子模块,这个递归加载过程自己是耗时的;
二、模块化思想提倡咱们分隔逻辑,管理好各个js文件内的逻辑,一旦分割的JS文件过多,最终形成前端资源加载压力。
不过不用担忧,requireJS提供了r.js来处理发布前的模块合成,帮助你把多个JS文件打包成一个文件。
再到后来,国内出现了CMD的思想,不一样于AMD的声明依赖的形式,容许你动态加载依赖,可是其实现以及具体的运行结果被你们诟病。
再到后后来,为了解决这种不一样库的模块实现不一致的问题,提出了UMD,其实很简单,只是写一段hack,让你的模块可以兼容不一样的模块加载场景,不管是commonjs仍是AMD,若是都没有的话就直接声明为一个全局变量的形式。
下面引用一段UMD的代码:vue

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.Vue = factory());
}(this, function () { 
  'use strict';
  //your code here
}

再到后后后来,将来的大一统,es6中所提出的import和export的形式来统一先后端的模块化加载方式。相比以往的实现,import/export的形式,在模块化加载JS文件的时候,保留动态的执行引用,其次,不容许动态控制加载依赖,使得tree-shaking成为可能。node

二、组件化思想

组件化的思想并不是前端所特有,在客户端也会面临相同的问题。想象一下,A跟B被同时分配一块儿开发完成一个首页页面,包括导航栏、轮播图、网站列表数据,登陆框等,两人须要如何分工协做?导航栏、列表这种须要在多个页面复用的HTML怎么办?假如在没有组件化处理的状况下:
一、A和B分工困难麻烦,代码提交时会处理大量的冲突;
二、导航栏、列表等多处复用的地方,须要cv大法直接复制粘贴到另外一个页面中去使用。
组件化思想,让咱们把页面划分为一个个组件,组件内部维护本身的UI展现、交互逻辑,组件间能够进行数据通讯,实现一种变相的相互隔离,便不会出现A和B两人一块儿编辑一段html的难受场景,同时,提升了代码的可维护性和复用性,这是其解决的关键痛点。
引用vue官网的一张有关组件化思想的图:react

clipboard.png

三、MVC框架、MVVM框架的流行

在模块化和组件化的基础上,实现了页面组件之间的隔离和各自维护,可是面临的最大的一个痛点问题,仍然是前面所说的,前端的JS逻辑中杂糅了各类处理逻辑,交互逻辑、请求逻辑、数据处理和校验逻辑、DOM操做逻辑;而其实这一切能够划分为两个层次,一个是数据层,一个是视图层,如何避免重复的书写操做DOM的逻辑,若是说早期的各类模板引擎给了咱们初期的解决方案,那么vue、react以及angular就是在模板引擎的基础上的上层建筑。
为了让咱们更加专一于数据的处理,MVC框架和MVVM框架帮咱们作了如下两件事:
一、监听页面操做事件,触发相应的事件钩子,执行代码逻辑,即V层到M层的过程;
二、执行代码逻辑后,数据层发生修改,帮咱们更新渲染页面,即M层到V层的过程;vue中经过vm实现,react中经过触发setState通知。
如此,咱们只须要书写一次html,在html中写明绑定或展现的数据,同时绑定好事件监听器,后续便不须要再处理视图层相关的操做,只须要关注于本身的业务逻辑代码、数据层的处理等。
MVVM架构流程图:webpack

clipboard.png

四、代码打包构建

前面介绍了grunt、gulp打包构建工具,其实webpack本质也是打包构建工具,可是webpack呈现出来的功能更为强大和成熟。对于代码的预处理、模块化加载、代码分割等,webpack具备更大的优点。es6

webpack诞生!

clipboard.png

读者读到这里,可能仍有些许疑惑,前面讲了这么多,为啥仍是没有介绍到webpack相关的,其实否则,仔细回想一下前面所介绍的思想,以及你平时使用webpack来打包构建的时候,其实webpack正是帮你处理了这些繁杂琐碎的事情。
若是代码预处理压缩足以,那么grunt和gulp已经知足了;
若是说模块化开发足以,那么requireJS和Browserify已经知足了;
若是说组件化开发、MV*框架足以,那么只须要在页面内引入相应的vue或react框架,足矣。
笔者写这边文章,更可能是想让你们可以思考工具或者框架背后,所呈现出来的思想,webpack就像是一个巨无霸,集大成者,它解决了打包构建,它处理了模块化开发,它帮助你和其余框架完美融合实现组件化开发;而这几年来MV*框架的流行对于webpack市场的迅速扩展有着不小的贡献。web

webpack为咱们作了如下这些事:(引自《深刻浅出webpack》)
代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。
文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等。
代码分割:提取多个页面的公共代码、提取首屏不须要执行部分的代码让其异步加载。
模块合并:在采用模块化的项目里会有不少个模块和文件,须要构建功能把模块分类合并成一个文件。
自动刷新:监听本地源代码的变化,自动从新构建、刷新浏览器。
代码校验:在代码被提交到仓库前须要校验代码是否符合规范,以及单元测试是否经过。 gulp

其实以小见大,你能窥见的不只是webpack的思想,更多的是前端的发展,从最初的土法炼钢,不规范,到现在的模块化、组件化、MV*框架,是前端思想的进步。做为一个前端仔,咱们应该探索和研究的是如何磨刀、磨好刀,而不是砍柴而已。后端

谢谢观看~

相关文章
相关标签/搜索