走近webpack(3)--图片的处理

时间:2022-09-06 01:02:14

  上一章,咱们学了如何用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来写样式了。