第581期Webpack——令人困惑的地方

Posted 前端早读课

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第581期Webpack——令人困惑的地方相关的知识,希望对你有一定的参考价值。

前言

周末部门去福州云顶山拓展,整个拓展挺轻松的,边做任务边pk,不同以往的军事化拓展。Ok,上周末两篇“前端经”大家觉得如何呢?今天早读君又带来了一篇关于前端构建打包的工具webpack,虽然这个工具之前也有分享过,但最近又开始折腾,准备投入到下一个项目中了。那么今天我们就来看看由@dmydang带来的分享。


正文从这开始~

 

Webpack是目前基于ReactRedux开发的应用的主要打包工具。我想使用Angular2或其他框架开发的应用也有很多在使用Webpack


当我第一次看到Webpack的配置文件时,它看起来非常的陌生,我非常的疑惑。经过一段时间的尝试之后我认为这是因为Webpack只是使用了比较特别的语法和引入了新的原理,因此会让使用者感到疑惑。这些也是导致Webpack不被人熟悉的原因。


因为刚开始使用Webpack很让人疑惑,我觉得有必要写几篇介绍Webpack的功能和特性的文章以帮助初学者快速理解。此文是最开始的一篇。


Webpack的核心原理

Webpack的两个最核心的原理分别是:

1. 一切皆模块

正如js文件可以是一个模块(module一样,其他的(如cssimagehtml)文件也可视作模 块。因此,你可以require('myJSfile.js')亦可以require('myCSSfile.css')。这意味着我们可以将事物(业务)分割成更小的易于管理的片段,从而达到重复利用等的目的。


2. 按需加载

传统的模块打包工具(modulebundlers)最终将所有的模块编译生成一个庞大的bundle.js文件。但是在真实的app里边,“bundle.js”文件可能有10M15M之大可能会导致应用一直处于加载中状态。因此Webpack使用许多特性来分割代码然后生成多个“bundle”文件,而且异步加载部分代码以实现按需加载。

好了,下面来看看那些令人困惑的部分吧。


1. 开发模式和生产模式

首先要知道的是Webpack有许许多多的特性,一些是开发模式下才有的,一些是生产模式下才有的,还有一些是两种模式下都有的。



通常使用到Webpack如此多特性的项目都会有两个比较大的Webpack配置文件

为了生成bundles文件你可能在package.json文件加入如下的scripts项:

【第581期】Webpack——令人困惑的地方


2. webpack CLI webpack-dev-server

值得注意的是,Webpack作为模块打包工具,提供两种用户交互接口:

  • Webpack CLI tool:默认的交互方式(已随Webpack本身安装到本地)

  • webpack-dev-server:一个Node.js服务器(需要开发者从npm自行安装)


Webpack CLI(有利于生产模式下打包)

这种方式可以从命令行获取参数也可以从配置文件(默认叫webpack.config.js)获取,将获取到的参数传入Webpack来打包。


当然你也可以从命令行(CLI)开始学习Webpack,以后你可能主要在生产模式下使用到它。

用法:

【第581期】Webpack——令人困惑的地方


webpack-dev-server(有利于在开发模式下编译)

这是一个基于Express.js框架开发的web server,默认监听8080端口。server内部调用Webpack,这样做的好处是提供了额外的功能如热更新“Live Reload”以及热替换“Hot Module Replacement”(即HMR)。

用法:

【第581期】Webpack——令人困惑的地方


Webpack VSWebpack-dev-server选项

注意像inlinehot这些选项是Webpack-dev-server特有的,而另外的如hide-modules则是CLI模式特有的选项。


webpack-dev-serverCLI选项和配置项

另外值得注意的是你可以通过以下两种方式向webpack-dev-server传入参数:

  • 通过webpack.config.js文件的"devServer"对象

  • 通过CLI选项


【第581期】Webpack——令人困惑的地方


我发现有时devServer配置项(hot: true inline: true)不生效,我更偏向使用如下的方式向CLI传递参数:

【第581期】Webpack——令人困惑的地方

注意:确定你没有同时传入hot:true-hot


webpack-dev-server“hot” “inline”选项

“inline”选项会为入口页面添加热加载功能,“hot”选项则开启热替换(Hot ModuleReloading,即尝试重新加载组件改变的部分(而不是重新加载整个页面)。如果两个参数都传入,当资源改变时,webpack-dev-server将会先尝试HRM(即热替换),如果失败则重新加载整个入口页面。

【第581期】Webpack——令人困惑的地方


3. “entry”:值分别是字符串、数组和对象的情况

Enter配置项告诉Webpack应用的根模块或起始点在哪里,它的值可以是字符串、数组或对象。这看起来可能令人困惑,因为不同类型的值有着不同的目的。


像绝大多数app一样,倘若你的应用只有一个单一的入口,enter项的值你可以使用任意类型,最终输出的结果都是一样的。

【第581期】Webpack——令人困惑的地方


enter:数组类型

但是,如果你想添加多个彼此不互相依赖的文件,你可以使用数组格式的值。

例如,你可能在html文件里引用了“googleAnalytics.js”文件,可以告诉Webpack将其加到bundle.js的最后。

【第581期】Webpack——令人困惑的地方


enter:对象

现在,假设你的应用是多页面的(multi-pageapplication)而不是SPA,有多个html文件(index.htmlprofile.html)。然后你通过一个对象告诉Webpack为每一个html生成一个bundle文件。


以下的配置将会生成两个js文件:indexEntry.jsprofileEntry.js分别会在index.htmlprofile.html中被引用。

【第581期】Webpack——令人困惑的地方

用法:

【第581期】Webpack——令人困惑的地方

注意:文件名取自“entry”对象的键名。


enter:混合类型

你也可以在enter对象里使用数组类型,例如下面的配置将会生成3个文件:vender.js(包含三个文件),index.jsprofile.js文件。【第581期】Webpack——令人困惑的地方


4. output“path”项和“publicPath”

output项告诉webpack怎样存储输出结果以及存储到哪里。output的两个配置项“path”“publicPath”可能会造成困惑。


“path”仅仅告诉Webpack结果存储在哪里,然而“publicPath”项则被许多Webpack的插件用于在生产模式下更新内嵌到csshtml文件里的url值。

【第581期】Webpack——令人困惑的地方


例如,在localhost(译者注:即本地开发模式)里的css文件中边你可能用“./test.png”这样的url来加载图片,但是在生产模式下“test.png”文件可能会定位到CDN上并且你的Node.js服务器可能是运行在HeroKu上边的。这就意味着在生产环境你必须手动更新所有文件里的urlCDN的路径。


然而你也可以使用Webpack“publicPath”选项和一些插件来在生产模式下编译输出文件时自动更新这些url

【第581期】Webpack——令人困惑的地方

【第581期】Webpack——令人困惑的地方


5. 模块加载和链式模块加载

模块加载器是可自由添加的Node模块,用于将不同类型的文件“load”“import”并转换成浏览器可以识别的类型,如jsStylesheet等。更高级的模块加载器甚至可以支持使用ES6里边的“require”“import”引入模块。


例如,你可以使用babel-loader来将使用ES6语法写成的文件转换成ES5

【第581期】Webpack——令人困惑的地方

链式(管道式)的加载器(从右往左执行)


多个loader可以用在同一个文件上并且被链式调用。链式调用时从右到左执行且loader之间用“!”来分割。


例如,假设我们有一个名为“myCssFile.css”css文件,然后我们想将它的内容使用style标签内联到最终输出的html里边。我们可以使用css-loaderstyle-loader两个loader来达到目的。【第581期】Webpack——令人困惑的地方


这里展示它是如何工作的:

【第581期】Webpack——令人困惑的地方

Webpack在模块颞部搜索在css的依赖项,即Webpack检查js文件是否有“require('myCssFile.css')”的引用,如果它发现有css的依赖,Webpackcss文件交给“css-loader”去处理


css-loader加载所有的css文件以及css自身的依赖(如, 其他css)到JSON对象里,Webpack然后将处理结果传给“style-loader”


style-loader接受JSON值然后添加一个style标签并将其内嵌到html文件里


6. loader自身可以配置

模块加载器(loader)自身可以根据传入不同的参数进行配置。

在下面的例子中,我们可以配置url-loader来将小于1024字节的图片使用DataUrl替换而大于1024字节的图片使用url,我们可以用如下两种方式通过传入“limit“参数来实现这一目的:

【第581期】Webpack——令人困惑的地方


7. .babelrc 文件

babal-loader使用”presets“配置项来标识如何将ES6语法转成ES5以及如何转换ReactJSXjs文件。我们可以用如下的方式使用”query“参数传入配置:

【第581期】Webpack——令人困惑的地方


然而在很多项目里babal的配置可能比较大,因此你可以把babal-loader的配置项单独保存在一个名为”.babelrc“的文件中,在执行时babal-loader将会自动加载.babelrc文件。


所以在很多例子里,你可能会看到:

【第581期】Webpack——令人困惑的地方


8. 插件

插件一般都是用于输出bundlenode模块。


例如,获取bundle.js然后压缩和混淆内容以减小文件体积。

类似的内部使用css-loaderstyle-loader来收集所有的css到一个地方最终将结果提取结果到一个独立的”styles.css“文件,并且在html里边引用style.css文件。

【第581期】Webpack——令人困惑的地方


注意:如果你只是想把css使用style标签内联到html里,你不必使用extract-text-webpack-plugin,仅仅使用css loaderstyle loader即可:

【第581期】Webpack——令人困惑的地方


9. 加载器(loader)和插件

你可能已经意识到了,Loader处理单独的文件级别并且通常作用于包生成之前或生成的过程中。


而插件则是处理包(bundle)或者chunk级别,且通常是bundle生成的最后阶段。一些插件如甚至更直接修改bundle的生成方式。


10. 处理文件的扩展名

很多Webpack的配置文件都有一个resolve属性,然后就像下面代码所示有一个空字符串的值。空字符串在此是为了resolve一些在import文件时不带文件扩展名的表达式,如require('./myJSFile')或者import myJSFile from './myJSFile'(译者注:实际就是自动添加后缀,默认是当成js文件来查找路径)


就这么多。

 

后语

我们可以来参与个调查,你们项目有在使用webpack吗?

 

关于本文

原文链接:https://segmentfault.com/a/1190000005089993


另:@dmyang在前端早读课更多的文章:

 


 


以上是关于第581期Webpack——令人困惑的地方的主要内容,如果未能解决你的问题,请参考以下文章

第1082期关键CSS和Webpack: 减少阻塞渲染的CSS的自动化解决方案

第1186期Webpack v4 beta 版本发布

第1206期看清楚真正的 Webpack 插件

车辆检测基于matlab yolo v2车辆检测识别含Matlab源码 581期

支持向量机如何处理令人困惑的特征向量?

第835期Webpack 的静态资源持久缓存