在以前的系列文章中,我已经介绍了如何用webpack实现多页面应用
的js,html,css的处理。今天就主要介绍如何处理静态资源,在web开发中最多见的静态资源就是图片。css
而由于在web中,图片有两种主要的引入方式,第一种是<img src="...">
,第二种是backgorund-image: url(...)
。前者在html中使用,后者在css中使用。html
图片常见的类型有jp(e)g,png,gif,包括如今广泛使用的svg以及webp。svg做为矢量图形,有必定的使用场景,而webp做为将来web开发的趋势,有必定的使用场景,好比:爱奇艺中的轮播图(carousel)中就是用webp,但其余的见到的很少。node
如今,web开发中使用最多的仍是jpg和png,处理他们,在构建工具中使用url-loader
和file-loader
就行了,其中file-loader负责图片的拷贝和输出,并会给图片名添加一个hash值。webpack
说到这里,不少人会想到字体图标
。之前处理web页面中的图标(icon),使用图片来处理,这样会带来一个性能问题就是http请求的增多,这样会形成服务器的负载压力,同时会带来用户体验的问题,由于会出现页面的局部空白和页面重绘的问题,固然一种解决方案使雪碧图(sprite),可是若是图片过大怎么解决,如何对图片进行分解(大变小的问题),图片的拼接比较困难,最要命的是在引用雪碧图时要进行计算,除此以外就是如何对雪碧图的组成图片进行自定义的删减,而使用字体图标这些问题,都会获得必定程度的解决,固然在构建工具中可使用webpack-spritesmith
这个插件来处理组成雪碧图的图片。css3
固然,有些特殊的状况,须要使用base64
,这里使用url-loader
便可。git
将图片处理为base64有使用场景,将图片转换为雪碧图亦有使用场景,单独的图片处理也有使用场景(这些使用场景的图片大小从左到右依次增大)。github
这些场景在一个web项目中都会涉及到。web
虽然使用字体图标能够替代雪碧图,由于字体图标有更小的尺寸,更自由的操做手法(如:图标颜色的自定义),可是一个DIY的web项目仍是有些图标仍是须要雪碧图。npm
可是,这里有一个问题,如何在一个项目中同时使用base64,雪碧图,字体图标,单独的图片。json
在构建多页面应用中,如何解决呢?
处理字体图标很简单,如:iconfont(阿里巴巴字体图标库),就像引用css那么简单。
base64的处理,使用url-loader
。
雪碧图的处理,可以使用webpack-spritesmith
这个插件
使用file-loader
,它负责拷贝url-loader
的处理结果,并输出。
上面就是咱们常见的图片处理,若是要处理svg能够参考svg-url-loader
,若是要处理webp能够参考webp-loader
对图片进行优化,会带来良好的用户体验。
熟悉图片优化的都知道渐进式(progressive),可参考nuwen.net
jp(e)g能够进行连续性
处理,这样可保证图片数据请求回来多少,就渲染多少,是自上而下的渲染,也是有模糊到清晰的状态。
png能够进行交叉
处理,这样也可保证图片数据请求回来多少,就渲染多少,它是总体的显示,并且是又模糊状态到清晰的状态。
gif图片通常使用小图,若是是大图会记号浏览器性能,还不如使用视频,或者用css动画来代替。我我的整理了一个css 动画集,有须要的能够看一下。
在构建多页面应用中,会使用到image-webpack-loader
来作优化处理。
其中,配置项options
中的mozjpeg
处理jp(e)g图片,pngquant
处理png图片,gifsicle
处理gif图片,webp
处理webp图片。
首先,看一下多页面应用中的目录结构图:
./src │ aboutUs.js │ contactUs.js │ css.js │ index.js │ recruitment.js │ ├─assets │ │ favicon.jpg │ │ │ ├─css │ │ │ index.scss │ │ │ │ │ ├─commons │ │ │ ├─container │ │ │ │ index.scss │ │ │ │ │ │ │ ├─footer │ │ │ │ index.scss │ │ │ │ │ │ │ └─header │ │ │ index.scss │ │ │ │ │ ├─productus │ │ │ index.scss │ │ │ productus-sprite.scss │ │ │ │ │ └─utils │ │ btn.scss │ │ form.scss │ │ inital.scss │ │ list.scss │ │ modeal.scss │ │ normalize.scss │ │ pagination.scss │ │ popover.scss │ │ table.scss │ │ text.scss │ │ tooltip.scss │ │ │ └─imgs │ ├─base64 │ │ fe.jpg │ │ │ ├─other │ │ float.jpg │ │ productus-sprite.png │ │ │ └─sprites │ └─productus │ product-us_01.png │ product-us_02.png │ product-us_03.png │ product-us_04.png │ product-us_05.png │ product-us_06.png │ product-us_07.png │ product-us_08.png │ product-us_09.png │ product-us_10.png │ product-us_11.png │ product-us_12.png │ ├─pages │ │ recruitment.pug │ │ template.pug │ │ │ └─components │ ├─commons │ │ ├─container │ │ │ index.pug │ │ │ │ │ ├─footer │ │ │ index.pug │ │ │ │ │ └─header │ │ index.pug │ │ │ └─productus │ index.pug │ └─utils load.js
跟之前的实例代码相比,此次的文件目录结构变化较大,这里将要处理的全部文件模块都放在了src
目录下。
可能有人会问,为何要要将目录分的这么细,下面我就说一下为何这么分。
aboutUs.js
, contactUs.js
, index.js
, recruitment.js
是四个路由页面,要用到的js代码,css.js
处理各个路由页面公用的css代码;productus
存放产品模块代码,根据开发的须要能够建立其余的模块目录,目录结构相似于commons
中的header
模块,其中utils
放置本身总结的工具模块代码,如table
,form
等。而后,指定style-loader
,css-loader
等样式相关的loader处理css样式文件,这样能够减小遍历,缩短构建时间。base64
,sprite
,ohter
等,为何要这样分?若是分的话file-loader
这个webapck的loader会复制并导出imgs
目下全部的图片,者在构建中并非咱们须要的,这样会增长构建的时间。若是让url-loader
处理base64
目录下的图片,file-loader
处理ohter
目录下的图片,webpack-spritesmith
处理sprite
目录下的图片,并将生成的图片放到ohter
目录下,用file-loader
进行二次处理。这样作,webpack处理更精确,能够减小没必要要的遍历,极大地减小构建的时间,一样方便对图片的管理,特别是对于须要改变sprite
的图片的管理。imgs
目录下建立base64
目录,sprite
目录,使用file-loader
指定处理ohter
目录,是为了不file-loader将全部的图片都拷贝一份并导出到dist
输出目录中,由于与base64
相关的文件已经在css
样式文件中了,再拷贝一份,已经没有意义,而sprite
相关的文件会被webpack-spritesmith
插件先处理生成一个文件,因此再拷贝它们也没有意义,还会让构建速度更慢。page
目录下,放置全部的html代码块(这里使用pug编译器生成相应的html代码块),它的目录分类和css
相相似,它们是一一对应的关系。注意:iamge-webpack-loader
,要先对全部的图片进行优化处理,而后再用其余loader处理。loader的执行顺序,若是你是style-loader!css-loader!sass-loader"
使用,它是从右到左方向前后执行,若是你是在配置文件中的rules: [...]
数组中,它也是从右到左的方向执行,若是你将全部的loader规则有回车符号隔开,那么它就是自下而上的执行。
针对<img src="...">
的图片使用,ul-loader
是不会处理html中的img引用,如今处理这样状况的loader或插件,也并无一个比较出名的。如今通用的作法就是将图片拷贝一份到生成目录中,copy-webpack-plugin
。参考配置代码以下:
new CopyWebpackPlugin([ { from: path.resolve(__dirname, 'assets/imgs/other/'), to: path.resolve(__dirname, 'dist/assets/imgs/other/'), ignore: ['.*'] } ]),
但这样,会带来另外一个问题就是图片的优化问题,如何使用 image-webpack-loader
?原本的目的是对项目中使用到的全部的图片进行优化,而如今只能对base64
和sprite
目录下的图片进行优化处理。不过,不要慌,能够经过建立一个新的npm脚本命令(本是里使用的是npm run img
)来对图片进行压缩处理,新建了一个目录static
用来保存优化前的图片,ohter
用来保存优化后的图片。
首先,须要安装imagemin
, imagemin-mozjpeg
, imagemin-optipng
, imagemin-gifsicle
:
yarn add imagemin imagemin-mozjpeg imagemin-optipng imagemin-gifsicle --dev
而后,在项目的根目录添加一个优化图片的文件optzing-img.js
,代码以下:
const path = require('path') const imagemin = require('imagemin'); const imageminMozjpeg = require('imagemin-mozjpeg'); const imageminOptipng = require('imagemin-optipng'); const imageminGifsicle = require('imagemin-gifsicle'); (async () => { await imagemin( [ path.resolve(__dirname, 'src/assets/imgs/static/*.jpg'), path.resolve(__dirname, 'src/assets/imgs/static/*.png'), path.resolve(__dirname, 'src/assets/imgs/static/*.gif') ], path.resolve(__dirname, 'src/assets/imgs/other/'), { use: [ imageminMozjpeg(), imageminOptipng(), imageminGifsicle() ] } ); console.log('图片优化完成!'); })();
最后,在package.json
文件中添加以下的npm命令:
... "scripts": { ... "img": "node optzing-img.js" }, ...
在控制输入npm run img
,而后按下回车键就能够获得你所须要的。
注:既然从新定义了图片优化的npm脚本命令,那么,是否须要去掉以前在webpack.config.js
中的image-webpakc-loader
,固然不须要。主要有两个缘由,一个是sprite雪碧图
它是用几张小图片合成了一张大图片,这张合成的图片还须要优化;另外一个是由于本项目对于存放图片的目录进行了细化。
在web开发中,自定义的字体也是比较常见的,在webpack中它的处理和图片相似,都是使用的 url-loader
和 file-loader
。参考代码以下:
... { include: path.resolve(__dirname, 'assets/fonts/'), test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, use: [{ loader: 'url-loader', options: { limit: 10000, name: isDev ? '[name].[ext]' : '[name].[hash].[ext]', outputPath: 'assets/fonts/' } }] }, ...
新建立了一个fonts
目录又来存放项目开发过程当中使用的字体。
此后,webpack构建多页面应用系列文章的源代码,都在这个github项目中,webpack3.x multi-page再也不维护。