什么是loader?

loader是webpack中一个非常核心的概念。

webpack用来做什么呢?

在我们之前的实例中,我们主要是用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关的依赖。

但是,在开发中我们不仅仅有基本的js代码处理,我们也需要加载css、图片,也包括一些高级的将ES6转成ES5代码,将TypeScript转成ES5代码,将scss、less转成css,将.jsx、.vue文件转成js文件等等。对于webpack本身的能力来说,对于这些转化是不支持的。那怎么办呢?给webpack扩展对应的loader就可以啦。

loader使用过程:

  • 步骤一:通过npm安装需要使用的loader

  • 步骤二:在webpack.config.js中的module关键字下进行配置

大部分loader我们都可以在webpack的官网中找到,并且学习对应的用法。

css文件处理

将上一篇的文章的代码复制一份。在src目录中创建一个css文件夹。编写一个normal.css文件。给页面设置背景颜色为红色

image-20200610143146299

我们在main.js中使用CommonJS的require()导入css文件产生依赖,从而打包时才会对该css文件一同打包。

image-20200610143853957

接着我们在该根目录下使用npm run build进行webpack打包

image-20200610144026847

报错提示我们可能需要一个合适的loader去处理这种文件类型

这是候我们可以前去webpack中文官网查找文档

image-20200610144335971

点击loaders查看详细介绍

image-20200610144626291

css文件属于样式。点击样式查看

image-20200610144710847

image-20200610144753422

点击css-loader查看安装

image-20200610144920945

控制台npm install --save-dev css-loader安装css-loader

image-20200610145123225

image-20200610145421334

安装完成之后按照官网指示配置webpack-config.js

image-20200610145713474

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const path = require('path')

module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.css$/,
//css-loader只负责将css文件进行加载
//style-loader负责将样式添加到DOM中
//使用loader时,是从右向左使用
use: ['style-loader', 'css-loader']
}
]
}
}

在moudle属性中配置,rules代表使用规则,test使用正则表达式匹配所有后缀为css的文件,use表示使用这些loader来解析css文件。use可以是一个数组也可是一个对象,使用顺序从右向左依次使用,严格遵守使用顺序

我们发现处理css文件的css-loader是要依赖与style-loader的。css-loader只负责将css文件进行加载。style-loader负责将样式添加到DOM中。所有处理css文件时,首先使用css-loader将css文件打包加载,接着使用style-loader将样式添加的到DOM中。使用顺序不能调换,必须严格遵循

所以我们要下载style-loader否则使用webpack打包会报错。使用npm install style-loader --save-dev

image-20200610150854255

image-20200610150953182

接着我们就可以使用npm run build对其进行打包

image-20200610151122797

可以看见页面的背景

已经变红了。而且上篇文章输出的语句也是能正常打印的

image-20200610151140191

less文件处理

如果我们希望在项目中使用less、scss、stylus来写样式,webpack是否可以帮助我们处理呢?

我们这里以less为例,其他也是一样的

首先创建一个special.less文件,依然放在css文件夹中。

image-20200610151616401

同理我们在main.js文件中使用CommonJS的require()导入less文件产生依赖,从而打包时才会对该less文件一同打包。

image-20200610152151975

同理我们去webpack中文官网查找相关文档

image-20200610152342165

安装npm install --save-dev less-loader@4.1.0 lessless-loader和less。指定安装版本。因为使用的是webpack3.6.0使用最新版会出现版本问题。

image-20200610153715010

接着配置webpack配置文件webpack-config.js

image-20200610152959863

我们可以发现less-loader是依赖于css-loaderstyle-loader的。less文件处理时先使用less-loader将less文件转换成css文件,接着通过css-loader处理css文件,最后通过style-loader将样式添加的到DOM中。是按照这个顺序处理less文件的

配置文件后通过npm run build对其进行打包处理

image-20200610153759962

打包成功。点击index.html查看效果。处理成功!

image-20200610153834355

图片文件处理

我们在src目录下创建一个img文件目录,导入一张图片

image-20200610155801055

修改normal.css文件,添加背景图片,从而产生依赖。对图片文件进行打包

image-20200610155915736

我们使用url-loader来处理,先安装url-loader

image-20200610160100441

使用npm install --save-dev url-loader安装url-loader

image-20200610160309989

接着配置webpack-config.js文件

image-20200610161023460

图片文件大小为16940

使用npm run build打包项目

image-20200610161629099

打包成功,查看页面效果

image-20200610161711996

页面效果正常。但是图片变成了base64的格式

当加载的图片,小于limit时,会将图片编译成base64字符串形式

接着我们修改配置文件中的rules中的limit数值大小,改为16939比图片文件小。然后使用npm run build打包

image-20200610162020338

image-20200610162047292

这时候出现报错提示找不到file-loader模块。

这是因为当加载的图片,大于limit时,需要使用file-loader模块进行加载

于是我们下载安装file-loader

image-20200610162214379

使用npm install --save-dev file-loader安装即可。无需配置

image-20200610162341674

接着使用npm run build打包。打包成功。出现图片文件

image-20200610162439905

查看页面效果

image-20200610162555477

发现图片加载失败。这是因为此时它要加载的路径是项目根路径下的图片

image-20200610162929784

把图片复制打项目根路径下,打开页面能正常加载

image-20200610162953248

但是这样操作是十分麻烦的。所有我们可以通过配置output的publicPath

image-20200610163539826

给这些资源路径添加上一个dist/前缀

image-20200610163930937

配置webpack.config.js

image-20200610164034813

删除根目录下的图片。重新打包npm run build

image-20200610164132558

查看页面效果。发现图片路径前加上了配置好的dist/从而引入了dist目录下打包好的图片文件

image-20200610164215171

我们发现webpack自动帮助我们生成一个非常长的名字

这是一个32位hash值,目的是防止名字重复

但是,真实开发中,我们可能对打包的图片名字有一定的要求。比如,将所有的图片放在一个文件夹中,跟上图片原来的名称,同时也要防止重复

所以,我们可以在options中添加上如下选项:

  • img:文件要打包到的文件夹

  • name:获取图片原来的名字,放在该位置

  • hash:8:为了防止图片名称冲突,依然使用hash,但是我们只保留8位

  • pext:使用图片原来的扩展名

image-20200610164514560

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
options: {
//当加载的图片,小于limit时,会将图片编译成base64字符串形式
//当加载的图片,大于limit时,需要使用file-loader模块进行加载
limit: 16939,
name: 'img/[name].[hash:8].[ext]'//为你的文件配置自定义文件名模板
}
}
]
}

重新npm run build打包。图片按规则放在img目录下,名称为原名称.hash8.原后缀名

image-20200610164637046

ES6语法处理

如果你仔细阅读webpack打包的js文件,发现写的ES6语法并没有转成ES5,那么就意味着可能一些对ES6还不支持的浏览器没有办法很好的运行我们的代码。

查看打包好的bundle.js能看到其中使用了ES6特有的const关键字

image-20200610165044382

所以为了能让更多的浏览器兼容我们写的js代码,我们要将其转换成ES5语法。在这里我们就要使用到babel-loader

image-20200610165326382

为了兼容我们3.6.0版的webpack我们指定安装相应版本的babel-loader运行命令npm install --save-dev babel-loader@7 babel-core babel-preset-es2015

image-20200610165704406

接着配置webpack.config.js文件

image-20200610165915260

匹配所有js文件,由于node_modules和bower_components里面都存在js文件。所以要将其排除不进行转换处理

使用命令npm run build打包,并在bundle.js中查找const关键字。发现没有找到。此时已经将js文件中的ES6语法全部转成了ES5

image-20200610170105908

查看页面效果。一切正常

image-20200610170254534