浅谈webpack

Posted 不懂艺术的程序员不是好的攻城狮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈webpack相关的知识,希望对你有一定的参考价值。

身处前端编程的你,肯定听说过webpack这个神器,至于为什么说它是神器呢,因为它让我们这些程序猿们又爱又恨,爱它是因为它太tm强大了,恨他也是因为它tm太强大了,强大到看见它时更多是一脸懵逼。。。


这个系列的文章都围绕webpack展开,我会说webpack是如何兴起的,又解决了哪些问题,又是如何和前端三大框架结合的。。。不过这篇文章主要说说webpack的由来历史,这样咱后续再用它的时候,心中就有了一个清醒的认识了。

下图就是webpack的图示介绍:

那首先咱就吧啦吧啦为什么会有webpack吧?大家一定要相信,世间万物存在即合理,因此webpack的出现也是有一定原因的,因为前端构建工具的良莠不齐,不得人心,webpack才崭露头角。那何为构建工具呢?


所谓构建工具:是一个把源代码生成可执行应用程序的过程自动化的程序。构建包括编译、连接跟把代码打包成可用的或可执行的形式等几个步骤。


咋一看定义,我嚓,怎么都和前端关联的很少,更多是安卓,ios及后端开发关联多一些,这也是因为js是一门很年轻的语言,设计之初也并非针对大型应用,但随着js应用越来越广泛,因此需要借鉴一下比较成熟的编程理念才可以支撑大规模的应用,这些成熟的编程理念便来自客户端安卓,ios及java后台等。。。


为了便于理解,先来捋捋之前前端是如何组织并发布代码的吧?

1,首先确定项目要使用哪些技术来实现,然后开始规划项目目录,接着就需要下载并添加第三方依赖,如前端ui框架bootstrap的css库及html代码等,以及js工具库中的战斗机jquery等等。这个下载,拷贝,引入的过程多数是重复并且没有意义的。

2,然后开始编辑器编码,浏览器各种调试debug。。。

3,编码结束,要进行语法检查,文件合并,压缩,打包等等,比如:

    HTML去掉注析、换行符 - HtmlMin

    CSS文件压缩合并 – CssMinify

    JS代码风格检查 – JsHint

    JS代码压缩 – Uglyfy

    image压缩 - imagemin

上面的过程都是在重复无用且繁琐的,因此就有勇士站出来,这特么不是在浪费时间吗,然后一通捣鼓之后。。。一系列的自动化构建工具就出现了,比如gulp,grunt,bower等,虽然他们都或多或少的解决了一些问题,但还远远不够,webpack也就在这种场景下应运而生,但为了更好的了解webpack,这里还是简单的说说各个构建工具吧。。。

先说gulp吧,直接上一张gulp官网的图片,看它是如何解释自己的。

浅谈webpack(一)

我嚓,还是有点抽象有木有。。。其实gulp是基于nodejs的自动化任务运行器,它能自动化地完成js/sass/less/html/image/css等文件的测试,检查,合并,压缩,格式化,浏览器自动刷新,部署文件生成,并监听文件改动等。


使用gulp的优势是利用数据流的方式进行文件的处理,类似管道(pipe)机制,前面步骤的输出,就是后面步骤的输入,通过管道将多个任务和操作连接起来,因此只有一次I/O的过程,流程比较清晰,也更加纯粹。gulp去除了中间文件,只将最后的输出写入磁盘,因此整个过程变得更快。


使用gulp,可以避免浏览器缓存机制,性能优化(文件合并,减少http请求,文件压缩)以及效率提升(如自动添加css3前缀,代码分析检查等)。

但其还是停留在指定文件类型,然后处理成对应类型文件的阶段,如下图:

浅谈webpack(一)

具体的使用方法请参看官网。。。


再来看看grunt,先来看官网的介绍:

浅谈webpack(一)

grunt这里就说了,对于需要反复重复的任务,如:压缩,编译,单元测试,代码检查等,自动化工具可以简化这些工作,只需在Gruntfile文件中正确配置好任务,任务运行器就会自动完成指定的工作。


grunt是一个基于任务的工具,意味着如果你不定义任务列表,基本上grunt就是个摆设。之所以这样是因为,grunt的任务模式不是使用js的代码来定义的,而是通过一系列的配置对象来声明式定义的,为了保持grunt核心包的大小,它的所有配置对象都是插件化的,从监控文件变化到复制,串联文件等。


这种方式的优势在于grunt有成千上万的插件,基本上不用再编写任何代码,针对不同的需求,任选取其一,直接拿来用即可。但也有一个很大的问题,就是如果想调整插件的输出效果时,通过编写纯js代码是无法实现的,必须为此重写一个grunt插件才可以。。。


那gulp和grunt有神马区别呢?


首先他们两个都是基于任务的自动化运行器,最大的不同在于grunt是使用配置对象来声明任务的运行方式,而gulp是使用js函数来定义任务。看一下他们的配置文件就知道了,如下:

下图是gulp的配置文件:

浅谈webpack(一)

下图是grunt的配置文件:

浅谈webpack(一)

也正是由于gulp知道如何处理js返回的streams和promises,这使得在编写任务时变得异常强大。二者都有丰富的插件库资源,不过gulp提供的插件资源偏基础性的功能,但也可以通过引用node模块来完善gulp任务体系。


因此我们可以根据项目情况自行选择构建工具。上面说的两种是构建工具,说白了,上面的构建工具其实就是代码转化了一下样式,本质仍然是代码,如果想最终让计算机和浏览器等识别,还需要编译器,包管理器等等。


------------编译器-----------

再来说说编译器,源码要运行,必须先转换成二进制的机器码。其实这个过程和翻译职位的作用差不多,比如你听不懂俄语,找个俄语翻译,把俄语翻译成汉语,然后你就可以看懂那伙计说的是啥了。对于计算机也是同样,程序员认识编程语言,比如js,java,python,php等,但计算机其实是不认识的,计算机底层其实只认识0和1,为了让计算机认识,就出现了编译器。。。


编译器在开始工作之前,需要知道当前系统环境(window,mac,linux等等),比如标准库在哪里,软件的安装位置在哪里,需要安装哪些组件等,这是因为不同计算机的系统都不太一样,通过制定不同的编译参数,编译器就可以灵活适应不同环境,编译出各种环境都能运行的机器码。。。


但我这里说的编译器,编的不是那么彻底,而是将一种高级的语言编译成低一级的语言,以支持更多的应用环境。比如babel,看下图

官网自己就解释说,今天就开始使用下一代js语法吧,再看看上图的代码,左侧是更高级的语法,但很多浏览器不兼容,因此通过babel这个编译器就可以编译成另外一种稍微低级的语法。


从上图也可以看出,高级语法更加简洁优雅,但是浏览器要兼容这些特性还有一定的滞后性,因此也就出现Babel这样的编译器,一些开发人员甚至在此基础上,增加了一些更加高级的特性,比如typeScript,coffeeScript,flow等,但这里面最接近js官方代码风格的,依然属Babel最优秀。但不管怎样,这些编译器都是让js这门语言更加强大,更加适合开发大型,复杂的应用。。。


尽管Babel在转换js代码方面很优秀,但除此之外,它不能帮助我们做任何事情,比如不能通过ES6的import和export表达式,将我们的多个文件进行合并打包等。。。因此还需要另外一个神器:包管理器


------------包管理器-----------

多数的项目,无论规模大小,程序猿都习惯将代码拆分到多个文件之中,需要使用的时候,再通过堆积木的方式组合起来,这样不但便于维护单个文件,也能减少单个页面的代码量,避免了重复造轮子。当然,也可以用传统的script标签,来逐个引入这些单独的js文件,但是最终还是需要基于不同文件的依赖关系来决定他们引入的先后顺序。在这件事上,无疑工具比人做的更好,这也就催生了包(模块)管理器,来将一些文件自动化地打包进一个单独的文件,并自动组织相互之间的依赖关系。


在浏览器端主要有Browserify,Bower等,他们可以使得原本应用在后端的包获得浏览器的支持,当然也可以将我们的web应用打包成一个node层面的包。


这种以node为中心的思想,有很多的好处,使用Bowserify等来打包一个应用是非常容易的,同时还可以使用node内置的模块,例如path,fs等,还可以引用之前在node项目中写过的任何代码。当然缺点就是,单页面应用通常需要的资源,正好是node项目不需要的,例如css,图片及字体等。


虽然上面的问题也可以通过插件来解决,使得Browserify可以打包这些资源,这些插件还可以将ES6转换ES5,打包css,分离代码到单个文件之中等等,但是这样就违背了Browserify这一构建工具的设计初衷,也使得配置更加复杂。。。


因此鉴于此,webpack诞生了,比如现在流行的单页面应用,使用webpack就可以将许多的js模块以及它的相关依赖打包进一个单独文件中,而且它也不需要你给出这些模块的依赖具体是哪些,只要它能够打包成js模块即可。这里的模块不单单是js模块,还可以是css和图片等,实现方法就是通过各种loaders来将各种资源文件都转换成js模块,因此在webpack世界,万物皆模块。。。


loaders是一种能够处理不同资源文件的转换器,它们能够接收任何形式的资源文件,也能输出任何形式的资源文件,而不仅仅局限于js,而且这种操作还是链式的,如可以先将scss文件转换成css,然后将css转换成js模块,然后webpack再对这些js模块统一打包处理,生成一些列的静态文件,然后这些静态文件传到服务器,就可以被访问了。。。


------------spa单页应用-----------



再来说说spa实现的原理:

如果是hash模式的话,当url的hash发生变化时,触发hashchange事件注册的回调,回调中执行相应的js操作,从而展示不同的内容。当然利用html5 中的history API中的pushState也是同样道理。


spa的优点:

1,传输数据量小,减轻后端压力,服务端只管出数据就可以,不用管展示逻辑和页面合成,吞吐能力能提高几倍。

2,良好的交互体验,用户不用重新刷新页面就可以实现刷新或局部刷新,获取数据也是通过ajax异步获取,更短的网络延迟。

3,良好的前后端分离模式,单页web应用可以与restful规范一起使用,通过restful api提供接口数据,并使用ajax异步获取,有助于分离客户端和服务器端工作,更进一步,在客户端也可以分解为静态页面和页面交互页面两种。


缺点:

1,seo难度大,单页应用的dom结构都是js动态构建出来的,而搜索引擎抓取的时候是不管js的,也就意味着爬虫爬取不到页面更多的信息,因此spa应用不利于seo,但也有爬虫工具可以分析js渲染出来的dom结构,但还是不便。

2,由于单页web应用在一个页面中显示所有内容,所以无法利用浏览器的前进和后退键,所有的页面切换需要自己建立堆栈管理。

3,初次加载耗时多,为实现单页web应用功能及显示效果,需要在加载页面的时候将js,css统一加载。加载耗时多,也就意味着首屏白屏时间较长。


------------PWA渐进web应用-----------

再来说说,web应用以后的趋势吧。。。但以后的事谁也说不准,这里先了解一下吧


前端最近这几年之所以挺火,很重要的原因是跨平台,快速迭代,没有应用商店的繁琐流程等等,但前端给人感觉总是局限于看的见的页面,因此难免让人感觉肤浅,同时严重依赖网速的浏览器打开方式,也让很多人对前端页面抛来蔑视的眼神,感觉前端页面和app应用完全是两个世界的东西。但我在这里想说的是,就是未来如果有一种可能,就是前端页面也能独立成为一个app应用,并且还可以安装在手机或其他终端上。。。你还蔑视它吗?

对没错,伴随着http2.0以及service worker技术的兴起,还有全世界的网络大提速,这种可能正在逐渐成为可能,PWA(progressive web app,渐进式web应用)就是其雏形,这种全新的网页技术,让网站的离线体验更好,网络连接即使断断续续也有更佳体验,还可以模拟原生的功能,利用框架,让网页应用呈现和原生应用相似的体验。


但PWA仍然不包含原生OS(operating system,操作系统)相关代码,但现在技术正在向支持OS层面倾斜,现阶段PWA仍然是网站级应用,只是在缓存,通知,后台功能等方面表现更好。。。


在这个逐利的时代,有时候更好的技术并不一定会得到全部厂家的支持,很重要的原因就是新的方式阉割了他们之前盈利的方式,但谁又能说的准呢,借之前阿里收购大润发时比较流行一句话:时代抛弃了你,连句再见都不会说。。。未来充满不确定,但能给人带来便利并提高效率的技术,肯定是不会错的!!!


以上扯了很多关于构建一系列相关的东西,还有SPA,PWA方面的内容,大家可以了解一下,也算是对前端有了一个大概的了解,我也是多方搜罗才写的这篇文章,如果哪位博客主看到,还请见谅别告我侵权就行。。。当然肯定有说的不到位或者理解错的地方,评论区已开发,欢迎大家指正,我也会及时更正。。。



以上是关于浅谈webpack的主要内容,如果未能解决你的问题,请参考以下文章

webpackwebpack.base.conf.js基础配置

Webpackwebpack5 模块联邦(Module Federation)

Webpackwebpack5 模块联邦(Module Federation)实践

webpackwebpack的html-webpack-plugin中的title不起作用?(已解决)

webpackwebpack-dev-server生猛上手——让我们来搭一个webpack的微服务器吧!

浅谈Yolo