我对 Webpack 的理解

见证打卡团小程序的Server,用的是一门特别小众的语言,叫Elixir,用的是一个特别小众的框架,叫Phoenix(这是个错误,后面有时间可以谈谈,简单来说,don’t fix problems you don’t have)。Phoenix的前端assets pipeline用的是一个不再维护更新的build工具,叫brunch。根据Phoenix的creator Chris McCord说,当时他刚开始写Phoenix的时候,webpack还wasn’t a thing。相比之下,brunch的文档和各方面都比较完善,所以选用了webpack。

时过境迁,如今webpack已经是前端开发的de facto standard build tool了,然而Phoenix依然在沿用brunch。因此,有必要把它换掉,换成webpack。然而根据网上搜出来的文章尝试了好几次,都没有成功。后来想到,是不是因为自己不够了解webpack,所以才这样呢?于是,今天决定抽点时间彻底研究一下webpack,然后再试试。

事实证明,确实如此。把webpack了解了个大概之后,很快就把brunch换掉了。

下面,就说一下经过这次的学习,我对webpack的理解。

首先,webpack的终极目标是:用模块化的方式,来打包静态资源。

这里有三个关键词:1. 模块化;2. 静态资源;3. 打包

模块化

首先讲讲模块化,要解释模块化是什么,以及为什么要这么做,最好的办法莫过于webpack的官方guide上面的例子来说明。

以javascript为例。在没有模块化的时代,我们是这么使用javascript的。把某一个html(假设为)需要用到的javascript,写在一个单独的javascript文件里面(假设为),然后在里面通过script tag把 link进来。如果在这个里面,我们要用到的东西,则我们需要在引用之前,也通过script tag的方式把 进来,不然的话,在运行的时候,是会出错的。

但是这样的话,就会出现两个问题。一是当在里面没有正确的引用的时候,运行就会出错。引用不正确的原因有很多,比如说拼写错了,或者是引用的位置不对,把对jquery的引用放到后面了等等。第二个问题是,当某一天,你的里面不需在要的时候,你可能不会记得,要去把里面,对的引用去掉。而且很多时候,你也不知道能不能去掉,因为虽然index.js不需要jQuery了,但是其他的js文件可能依然需要。这样的话,可能会导致,哪怕没有任何地方用到,里面也依然加载了,从而增加不必要的加载时间和流量。

那么怎么解决这两个问题呢?答案就是模块化加载:把变成一个模块,然后如果里面需要用到这个模块,就通过或者等方式显式的加载进来(以下统一用举例)。使用这种方式,是不需要在的任何地方引用的,从而避免了第一个问题。同时,如果哪天里面不需要用到了,那么把引用的import那一行代码删了就好了。删了以后,jquery不会再被加再进来,如此,就避免了第二个问题。

这就是模块化。

静态资源

但是,webpack自身是只能识别js文件的,它只支持把一个js文件变成一个模块。js只是静态资源的一种。我们刚刚说的三个关键词,其中一个是“静态资源”,那么其他的静态资源,比如css、图片文件等等怎么办呢?怎么样把他们也变成一个模块,让开发者可以像import一个js模块一样,import这些静态资源呢?

这就是各种loader的作用。webpack有一套loader系统,开发者可以通过这个loader系统,写出“把某种资源文件变成一个模块,让开发者可以在js文件里面”的loader。一般来说,常见的资源文件,都已经有对应的loader存在了。比如css-loader,可以把一个css文件变成一个js模块。然后,如果里面需要用到这个css文件,就在对应的js文件()里面import这个css文件,就跟import一个js模块一样。

打包

上文提到的静态资源模块化,是webpack在方便开发者开发的这个方向做的事情。然而我们一般说,webpack是个打包工具,意思就是说,当我们开发完了之后,可以用webpack来对源代码进行“打包”,最终生成一个用于发布到线上的最终文件。

但是webpack怎么知道我们要对哪个/哪些文件进行处理,以及把处理之后的最终文件放到哪呢?很简单,我们通过一个配置文件(),告诉webpack。在这个配置文件中,我们在这个配置项,指定让webpack对哪个/哪些文件进行处理。同样的,我们在这个配置项,指定打包好的最终文件放到哪个目录,文件名叫什么。

假如我们指定webpack对上文中的index.js进行处理,则当webpack看到我们的index.js里面有 这样的代码时候,会把jquery这个资源一并整合到最终的结果文件里面去。这样的话,里面用到jquery的地方就能正确运行了。同样的,如果jquery里面import了别的东西,webpack也会作同样的处理。最终,形成一个“依赖树”。一般来说,Entry会指定为这个“依赖树”的根节点。

最后,在webpack对及其直接或间接依赖到的模块进行打包的过程中,我们可能想要加入一些自己的处理。比如把文件进行压缩、使用gzip加密,让文件变得更小等等。想要达到这样的目的,我们需要指定让webpack使用一些plugin来达到。这就是webpack的plugin系统。

也就是说,plugin,是一些用于控制webpack的打包过程的东西。

Entry、output、loader、plugin,这就是所谓的webpack四大核心。理解了这几个东西,对webpack就有了一个总体的了解。当然,这篇文章写的都是一些大概的理解,不全面,也不是百分百准确。比如说,loader和plugin的功能界限其实是比较模糊的。但是,如果你之前从来没接触过webpack,当你看到一个,可能会觉得慌得一笔,这么多配置选项,到底是干嘛的?为什么有的地方教你安装plugin,而有的地方却叫你安装loader?希望看完这篇文章,你能有一个整体的理解,知道各个部分到底起的是什么作用。再去看webpack的配置文件,不用那么慌得一笔。

关注小创的作品,小创作

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180715G1DX0600?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券