Webpack--loader

140 阅读5分钟

回顾

回顾一下,我们现在已经能使用Webpack对JS文件进行打包了。并且支持JS文件的模块化开发。Webpack会自动帮我们处理好模块之间的依赖关系。但是往往我们不止有js文件,还有css文件等等。之前我们说过,Webpack可以将他们也看作一个模块然后进行打包。**其实Webpack本身并没有这个功能,他唯一能做的就是打包js文件,并且处理好模块之间的关系。**他也不能把里面的ES6转成ES5.那这些功能是怎么实现的呢?都是通过安装loader来实现的。loader的作用就是拓展Webpack的功能。

loader的作用

loader可以把Webpack打包不了的文件(如css文件)转化成Webpack能打包的模块。比如我举个栗子: 我在之前的文件的基础上,又创建了一个css文件 index.css

body{
    background-color:red;
}

现在如果我直接打包main.js,会不会打包我们的index.css呢?很明显是不会的,因为index.css这个文件和我们的main.js文件之间没有任何联系,没有任何依赖。
现在我们让他产生依赖。导入index.css:

 import {decrement} from "./es6Module"
 let css  = require("./index.css")
let a = 11;
let b = 12;
 decrement(a,b);
console.log(css);

使用webpack进行打包,发现报错。 很明显的错误提示:you may an appropriate loader handle this file type.你需要一个合适的loader来处理这个文件。也就是说我们的Webpack打包不了css文件。这时候我们需要使用loader了。

使用loader

使用loader,主要分为两步,一个是下载我们的loader。一个是配置好我们的loader

  • 下载对应的loader。比如打包css文件,我们需要的是css-loader
  • 配置对应的loader.有关于webpack的配置应该都在webpack.config.js中进行,这个也不例外

安装对应的loader

以安装css-loader为例

npm install css-loader --save-dev

css-loader是把我们的css文件打包成我们webpack可以打包的模块。所以它也是一个开发时依赖。

配置相应的loader

之前我们在webpack.config.js中,配置了出口,入口。接下来我们来配置loader的有关东西。应该是在导出对象的module属性中配置。module属性对应的是一个对象,这个对象有一个rules属性对应一个数组,所有的loader配置规则都存放在这里。每种规则对应代码其实又是一个对象,这个对象有两个特别重要的属性:

  • test属性,是一个正则表达式,匹配哪些文件要使用对应的loader进行转换
  • use属性,对应的一个loader组成的数组,表明匹配到对应文件后,使用哪些loader以及使用的顺序
const path = require("path");
module.exports={
    entry:"./src/main.js",
    output:{
        path:path.resolve(__dirname,"dist"),
        filename:"bundle.js"
    },
    module:{
        rules:[
        {
        test:/\.css$/,
        use:["css-loader"]
        }
        ]
    }
}

配置好后,webpack如果在打包过程中碰到.css文件,在对它打包之前他会先使用css-loader对css文件做转换,转换成webpack可以打包的模块,然后你再打包。
配置好,我们再对项目进行打包。发现样式并没有生效。这是为什么呢?
原因是这样的:css-loader只是解析了我们css代码,并没有把样式添加到DOM上去,我们可以打印一下刚刚那个那个css变量。
这居然是一个数组。所以我猜测css-loader它把css文件解析成了数组的形式。但是这个js的形式,浏览器肯定解析不懂。这个时候我们需要另一个loader把我们的js形式的样式,转成浏览器能看懂的样式。这就是我们的style-loader
首先,第一步还是安装npm uninstall style-loader --save-dev 第二步配置,应该是只要修改use属性就可以 use:["style-loader","css-loader"],请注意,webpack调用loader是从右往左的顺序调用的,所以我们也是倒着写的。
再打包,果然就可以了。 很明显,它的网页代码里面多了一个style标签,所以style-loader的作用应该就是解析css-loader解析后的js代码,然后使用创建style标签的形式,存放样式,并把style标签添加到页面。webpack官网也说了

处理less文件

当我们的项目存在less文件的话我们需要添加less-loader

  1. 安装
npm install less-loader less --save-dev

less-loader的作用是将我们的less文件编译成我们css文件。为什么要安装less呢?less-loader将less文件编译为css文件的过程中是要依赖到less.
2. 配置

处理图片文件

我们的项目中可能还会存在一些图片文件,处理图片文件,我们需要使用url-loader。webpack处理图片的时候也会把他当作一个模块。

安装url-loader

cnpm  install url-loader@1.1.2 --save-dev

cnpm是淘宝镜像,相比npm下载速度更快

配置url-loader

{
            test: /\.(png|jpg|gif)$/,//匹配使用url-loader的文件
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 8192//它的配置项,就是对图片大小进行限制,默认值是8kb,超过的就不归url-loader管了。
                }
              }
            ]
          }

效果

可以看到,url-loader把指定的图片文件转成了base-64的字符串,它实际做的事儿就是对图片进行base64编码

大于limit值的图片文件

大于limit值的图片文件,不能使用url-loader了。只能使用file-loader。

安装file-loader

 cnpm  install file-loader@3.0.1 --save-dev

file-loader好像并不用配置,直接打包即可。
重新打包,没有效果。但是dist文件夹中会多出一个图片文件,并且名字很乱。
file-loader将图片文件进行了打包,打包到了目标文件夹./dist中。而之前url-loader是将图片进行了base64编码并没有进行打包到dist文件夹中。那么为什么会没有效果呢?
看这里: 生成的url路径并不存在dist文件夹,导致文件无法找到。
解决方法:在webpack.config.js中配置publicPath,那么所有和路径有关的东西都会加上公共路径了。 其实这个也不是特别重要,因为最后的index.html文件也要放在dist文件夹中,所以公共路径就没有意义了。

生成的图片名字

这是一个随机的32位hash值,目的就是怕重名的情况。但是往往我们需要知道图片的内容,也就是图片名字要有一定的含义,这样我们就需要重新命名图片的名字。
很多情况下,我们不想把图片直接放在dist文件夹下,需要把他统一放在一个子文件夹。这个问题也是通过命名来解决。
在options下,配置name 他是配置在url-loader的配置项下,就有点奇怪。解释下几个组成部分

  • img/ 这个img是随便命名的就是再创建一个子文件夹
  • [name] 获取图片打包前的name,放在这里(让图片的名字有了含义)
  • [hash:6] 获取六位hash值,因为图片的name可能相同
  • [ext] 获取图片原来的拓展名

这就是我们重新命名的图片文件的方式了,重新打包看看效果。

ES6转ES5

当Webpack帮我们打包js文件的时候,其实js文件中,es的语法并没有转化成es5的语法。这导致bundle.js中的代码还含有es6的语法,这样可能不是所有浏览器都能适配,所以我们需要使用babel.loader来转换ES6的语法

安装babel-loader

npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
babel-core 依赖它对我们es6转成es5
babel-preset-es2015 好像和配置有关

配置babel-loader

  1. 匹配js/mjs文件
  2. exclude 去除掉这两个文件的js文件
  3. presets 设置