目录
一、什么是Loader
前面章节已经展示了如何使用webpack打包js文件,那么怎么使用webpack打包其他类型的文件呢?(比如图片、css样式文件、json文件等等)
答案是使用loader,webpack最出色的功能之一就是,除了能引入js文件之外,还可以通过loader引入任何其他类型的文件。
因此,loader是一个打包方案,能对特定类型的文件用相应的方案进行打包。
二、打包图片
webpack的loader机制支持打包图片,打包图片主要用到的两个loader是file-loader和url-loader。
2.1、file-loader
我们先来看file-loader。
首先,先安装file-loader:
然后,清空webpack-demo目录下的src文件夹,并随便放入一张图片:
在src文件夹中再加入一个index.js文件:
index.js:
import Icon from './dog.jpg';
console.log(Icon);
var element = document.getElementById('webContent');
var icon = new Image();
icon.src = Icon;
element.appendChild(icon);
然后,为了让file-loader能够起作用,还需配置wepback.config.js文件:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [
'file-loader' // 使用的loader
]
}
]
}
}
最后,进行打包操作:
打包后生成了一个新的以哈希值命名的图片文件,可以在dist文件夹中找到:
我们可以使用浏览器打开dist.html:
图片已经被成功打包,并在项目中显示出效果了!
另外,还可以对file-loader进行更多配置:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'file-loader', // 使用的loader
options: {
name: '[name].[ext]' // 打包出的图片文件仍保持原有命名
}
}]
}
]
}
}
进行打包操作:
可以看到生成的图片文件文件名与原始文件一致。
2.2、url-loader
还可以使用url-loader来打包图片,它与file-loader的不同之处在于url-loader将图片打包成base64的形式加载到main.js文件中。
首先,让我们来安装url-loader:
然后,重新配置webpack.config.js:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
}
]
}
}
进行打包操作:
可以明显发现,这次打包没有生成新图片文件,这是因为dog.jpg这个图片文件大小只有8kb,所以url-loader以base64的形式对该图片文件进行打包。
我们打开main.js文件:
可以发现,图片真的以base64位的形式被打包,并被加载到main.js文件中。
可以用浏览器打开dist.html文件:
效果和之前一致!
2.3、file-loader和url-loader的比较
file-loader实际上只将图片进行了文件目录的转移,而ulr-loader却可以将图片文件以base64位的形式进行处理,因此:
- 当图片很小时 —— 适合用url-loader,因为图片将以base64位的形式加载到main.js,因此浏览器将只请求一个main.js文件,而不用多发起一次对图片的http请求。
- 当图片比较大时 —— 适合用file-loader,因为能让main.js更快地加载出来。
三、打包CSS文件
3.1、style-loader和css-loader
为了让webpack能够打包css文件,需要安装style-loader和css-loader,并对webpack.config.js进行配置。
先来安装style-loader和css-loader:
再对webpack.config.js进行配置:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
}
现在就可以来测试一下webpack能不能打包css文件了,首先在src文件夹下创建一个dog.css文件:
dog.css:
.dog {
width: 300px;
height: 300px;
}
修改index.js:
index.js:
import Icon from './dog.jpg';
import './dog.css';
var element = document.getElementById('webContent');
var icon = new Image();
icon.src = Icon;
icon.classList.add('dog');
element.appendChild(icon);
进行打包:
用浏览器打开dist.html,可以发现css样式文件已经起作用:
3.2、sass-loader
webpack不仅可以打包css文件,还可以打包sass文件,不过需要sass-loader。
首先安装sass-loader:
再配置webpack.config.js:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
}
现在可以测试webpack能不能打包sass文件,首先修改dog.css文件名为dog.scss,然后再修改dog.scss内容:
dog.scss:
body {
.dog {
width: 300px;
height: 300px;
}
}
进行打包:
再用浏览器打开dist.html,可以发现效果与之前一样:
3.3、postcss-loader
许多css样式的书写需要添加厂商前缀,我们可以使用postcss-loader来完成添加厂商前缀的操作,但现在我们先来看不添加厂商前缀的示例。
修改dog.scss文件:
dog.scss:
body {
.dog {
width: 300px;
height: 300px;
transform: translate(100px, 100px);
}
}
进行打包,然后用浏览器打开dist.html:
果然有偏移效果,在浏览器中查看样式:
可以发现,transform之前并没有添加前缀,接下来我们使用postcss-loader来让transform之前添加厂商前缀。
首先,安装postcss-loader:
因为还需要autoprefixer插件的配合,所以安装autoprefixer:
然后在webpack-demo根目录创建一个postcss.config.js,并为其添加内容:
postcss.config.js:
module.exports = {
plugins: [
require('autoprefixer')
]
}
再配置webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
'postcss-loader'
]
}
]
}
}
进行打包:
用浏览器打开dist.html,可以发现transform已经添加了厂商前缀:
3.4、处理sass文件中引入另外sass文件的情况
在webpack打包sass文件的过程中,它内部调用的loader的顺序是postcss-loader、sass-loader、css-loader和style-loader,也就是webpack.config.js文件中从use数组中从下往上调用:
现在,在src根目录创建一个dog2.scss文件:
dog2.scss:
body {
.dog {
transform: translate(100px, 100px);
}
}
再修改dog.scss文件:
dog.scss:
@import './dog2.scss';
body {
.dog {
width: 300px;
height: 300px;
}
}
因为dog2.scss作为引入的方式加载到dog.scss,所以webpack会直接调用css-loader,而不会在调用css-loader之前先调用postcss-loader和sass-loader,为了解决这个问题,可以对css-loader进行配置:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}
]
}
}
现在可以进行打包了:
3.5、CSS模块化
webpack支持CSS模块化,具体是什么意思呢?
在src根目录下,创建一个createImg.js:
createImg.js:
import Icon from './dog.jpg';
function createImg() {
var element = document.getElementById('webContent');
var icon = new Image();
icon.src = Icon;
icon.classList.add('dog');
element.appendChild(icon);
}
export default createImg;
修改src目录下的index.js:
index.js:
import Icon from './dog.jpg';
import './dog.scss';
import createImg from './createImg.js';
createImg();
var element = document.getElementById('webContent');
var icon = new Image();
icon.src = Icon;
icon.classList.add('dog');
element.appendChild(icon);
进行打包:
然后用浏览器打开dist.html:
可以发现,新创建的图片和之前的图片有相同的样式,也就是dog.scss样式文件中指定的效果。
现在我们想让只有其中的一张图片具有dog.scss文件中的样式,这也就是CSS模块化的意思,只将某个CSS文件作用于页面中的某些部分。
可以这样来做,首先修改webpack.config.js文件以开启CSS模块化:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
}
]
}
}
再修改index.js文件:
index.js:
import Icon from './dog.jpg';
import style from './dog.scss';
import createImg from './createImg.js';
createImg();
var element = document.getElementById('webContent');
var icon = new Image();
icon.src = Icon;
icon.classList.add(style.dog);
element.appendChild(icon);
进行打包,然后用浏览器打开dist.html文件:
可以发现,dog.scss文件样式只作用于其中的一张图片。
四、打包字体、图标
如何使用webpack来打包字体和图标呢?
我们可以去阿里巴巴矢量图标库下载图标来测试一下。
这里我随便下载了一个图标:
在webpack-demo的src文件夹下新建一个fonts文件夹,将iconfont.eot、iconfont.svg、iconfont.ttf、iconfont.woff、iconfont.woff2这几个文件拷贝进去。
然后在src文件夹下新建一个iconfont.scss,将iconfont.css里的全部内容复制到iconfont.scss里,并作路径修改:
iconfont.scss:
修改index.js:
index.js:
import './iconfont.scss';
var webContent = document.getElementById('webContent');
webContent.innerHTML = '<i class="iconfont iconWIFI"></i>';
最后,还要修改webpack.config.js:
webpack.config.js:
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif$)/, // 文件后缀名匹配通配符
use: [{
loader: 'url-loader', // 使用的loader
options: {
limit: 10240 // 当图片小于10kb时,使用base64的方式进行打包
}
}]
},
{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf)$/,
use: [
'file-loader'
]
}
]
}
}
现在可以进行打包了:
使用浏览器打开dist.html:
图标显示出来了!