走近webpack(3)--图片的处理
上一章,咱们学了如何用webpack来打包css,压缩js等。这一篇文章咱们来学习一下如何用webpack来处理图片。废话不多说,咱们开始吧。
首先,咱们随便找一张你喜欢的图片放到src/images目录下,然后把图片设置为背景图片,代码是这个样子。
src/index.html:
<div id="title"></div> <div id="name"></div> <div id="img"></div> <script src="./entry1.js"></script> <script src="./entry2.js"></script>
src/css/index.css:
body{ background:red; } #title{ background:orange; color:blue; } #img{ background: url(../images/dog.jpg); width: 500px; height: 500px; }
ok,我们写完了代码,现在webpack是无法解析的,我们可以打包试一下,发现会报错。嗯,没有加入loader肯定会报错的!
那么,接下来我们来安装一下打包图片需要用到的loader:
npm install --save-dev file-loader url-loader
在等待安装之际,我们先解释一下这两个loader分别都是做什么的:
file-loader:解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。
url-loader:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。其实简单来说,url-loader的作用就是根据配置来判断图片是否需要转换成字符串编码,来使项目的性能和速度更快。
那么,接下来我们在module中配置一下loader,现在我们的module看起来是这样的,其中limit参数就是用来判断需要把图片转换成字符串编码的大小范围,单位是B。
module:{ rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },{ test:/\.(png|jpg|gif)/ , use:[{ loader:'url-loader', options:{ limit:500000 } }] } ] },
唉?不对啊,你安装了两个loader,为什么只用了url-loader啊?!因为url-loader内置了file-loader。这里安装file-loader是为了方便下面用到的时候不用再安装了。
OK,咱们来打包一下看看会发生什么吧。打开页面发现我们引入的图片已经显示了。
下面说一下怎么把css从js中分离出来,我们上面的css都是通过import引入到js中再进行打包的,这样不利于维护,也违背了js,css,html互相分离的基本原则。但是一旦分离了css,那么原本的图片路径就会出现问题。我们下面来解决一下。但是webpack官方认为css就应该打包进js中以减少http请求。所以,仁者见仁智者见智,怎么做看具体情况来选择吧。
其实要解决这个问题很简单,用插件,extract-text-webpack-plugin。怎么安装就不说了,已经说了好多遍了,跟上面的安装方法一样,改个名字而已。
既然是插件,我们就需要在config中引入并且new一个实例之后才可以使用:
module:{ rules: [ { test: /\.css$/, /*修改了一下使用的方式*/ use: extractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) },{ test:/\.(png|jpg|gif)/ , use:[{ loader:'url-loader', options:{ limit:500000 } }] } ] }, //插件,用于生产模版和各项功能 plugins:[ new uglify(), new htmlPlugin({ minify:{ removeAttributeQuotes:true }, hash:true, template:'./src/index.html' }), /*这里new了一个插件的实例*/ new extractTextPlugin("css/index.css") ],
ok,我们兴致勃勃地去打包一下,竟然报错了,报错的主要原因是extract-text-webpack-plugin当前还没有支持webpack4.x,那么我们该怎么办呢?别急,咱们想想办法解决:
npm install --save-dev extract-text-webpack-plugin@next /*更新版本*/
这样就可以打包了,但是我们打包完成之后发现index.html并没有引入相应的css,页面没有任何css,别急,我们来进行下一步解决这个问题。
我们在config中定义一个路径变量:
var webpath={ publicPath:"http://192.168.199.124:9090/" } /*就是你在devServer中定义的host和端口*/
然后在output属性中定义一个publicPath属性:
output:{ path:path.resolve(__dirname,'dist'), filename:'[name].js', publicPath:webpath.publicPath },
并且要把之前配置在devServer中的host修改成你自己的本机host,我的是http://192.168.199.124,如果你不知道,可以在cmd中使用ipconfig来查询。
然后,我们npm run server一下,发现打开的页面已经有图片和样式了。
那么我们就学会了如何处理css中的图片问题,下面我们学习一下如何处理html中的图片(也是用插件,各种插件,你可以去github随便找一个你喜欢的可以处理这中问题类型的插件):
这里我们使用html-withimg-loader,然后在config中如下配置:
npm install html-withimg-loader --save /*因为在生产环节中也需要用到,所以使用--save命令*/
{ test: /\.(htm|html)$/i, use:[ 'html-withimg-loader'] }
完事了。。。。。。简单吧。
前边的内容,打包后的图片并没有放到images文件夹下,要放到images文件夹下,其实只需要配置我们的url-loader选项就可以了。前面也说到了,要限制limit的大小,不然图片在小于limit的范围内会进行转码,咱们来小小的修改下代码就可以了:
{ test:/\.(png|jpg|gif)/ , use:[{ loader:'url-loader', options:{ limit:500, outputPath:'images/' } }] }
我们在src/index.html中加入一个图片的引入:
<div id="title"></div> <div id="name"></div> <div id="img"></div> <!-- 通过src引入图片 --> <img id="htmlImg" src="./images/dog.jpg">
然后在src/css/index.css下写上这样的css:
body{ background:red; } #title{ background:orange; color:blue; } #img{ background: url(../images/dog.jpg); width: 500px; height: 500px; } /*设置图片大小*/ #htmlImg{ width: 500px; height: 500px; }
然后我们npm run server一下看看结果吧。这里说明一下,可能细心的小伙伴会问,为什么以前打包用npm run build 而这里用npm run server呢?
通常情况下,我们有两种环境,一种是dev,一种是prod,也就是开发环境和生产环境,一般在开发环境下,我们本地会通过webpack-dev-server通过express起一个node服务器,而不是真正的打包,而我们以前所一起学习的webpack使用方法即包含了开发环境下的需求,又有生产环境下的内容,当我们要把整个项目打包上线的时候,我们会压缩js,压缩图片,整合资源以减少http请求,但是我们在开发环境下的时候,往往需要更多的功能以使代码更容易阅读和debug。再有就是,我们在引入图片的时候,用的是绝对地址,也就是node起服务器后你本地的ip地址,如果不通过npm run server起本地服务器,是无法找到图片的。有兴趣的小伙伴可以试试npm run build然后手动打开dist下的html看看效果。
至此,图片的处理方式就结束了。下一章咱们来看看怎么处理less啊,sass这样的css预编译语言,毕竟现在很少用css来写样式了。