# 打包静态资源

# 什么是loader?

概念

loader是一种打包规则,它告诉了 Webpack 在遇到非.js文件时,应该如何处理这些文件

loader有如下几种固定的运用规则:

  • 使用test正则来匹配相应的文件
  • 使用use来添加文件对应的loader
  • 对于多个loader而言,从 右到左 依次调用

# 使用loader打包图片

安装依赖

打包图片需要用到file-loader或者url-loader,需使用npm install进行安装

# 一点小改动

在打包图片之前,让我们把index.html移动到上一节打包后的dist目录下,index.html中相应的.js引入也需要修改一下,像下面这样

<script src="./main.js"></script>
1

# 添加打包图片规则

对于打包图片,我们需要在webpack.config.js中进行相应的配置,它可以像下面这样

// path为Node的核心模块
const path = require('path');

module.exports = {
  // 其它配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: 'file-loader'
        }
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 改写index.js

import avatar from './avatar.jpg'

var root = document.getElementById('root');
var img = document.createElement('img');
img.src = avatar
root.appendChild(img)
1
2
3
4
5
6

# 打包后的项目目录

|-- dist
|   |-- bd7a45571e4b5ccb8e7c33b7ce27070a.jpg
|   |-- main.js
|   |-- index.html
|-- index.js
|-- avatar.jpg
|-- package.json
|-- webpack.config.js
1
2
3
4
5
6
7
8

# 打包结果

打包结果

# 运用占位符

在以上打包图片的过程中,我们发现打包生成的图片好像名字是一串乱码,如果我们要原样输出原图片的名字的话,又该如何进行配置呢?这个问题,可以使用 占位符 进行解决。

占位符说明

文件占位符它有一些固定的规则,像下面这样:

  • [name]代表原本文件的名字
  • [ext]代表原本文件的后缀
  • [hash]代表一个md5的唯一编码

根据占位符的规则再次改写webpack.config.js文件,

// path为Node的核心模块
const path = require('path');

module.exports = {
  // 其它配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]'
          }
        }
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

根据上面占位符的运用,打包生成的图片,它的名字如下

|-- dist
|   |-- avatar_bd7a45571e4b5ccb8e7c33b7ce27070a.jpg
1
2

# 使用loader打包CSS

打包说明

样式文件分为几种情况,每一种都需要不同的loader来处理:

  1. 普通.css文件,使用style-loadercss-loader来处理
  2. .less文件,使用less-loader来处理
  3. .sass或者.scss文件,需要使用sass-loader来处理
  4. .styl文件,需要使用stylus-loader来处理

# 打包css文件

安装依赖

首先安装style-loadercss-loader

改写webpack配置文件:

// path为Node的核心模块
const path = require('path');

module.exports = {
  // 其它配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]'
          }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

根目录下创建index.css

.avatar{
  width: 150px;
  height: 150px;
}
1
2
3
4

改写index.js文件

import avatar from './avatar.jpg';
import './index.css';

var root = document.getElementById('root');
var img = new Image();
img.src = avatar;
img.classList.add('avatar');
root.appendChild(img);
1
2
3
4
5
6
7
8

打包结果

css打包结果

# 打包Sass文件

安装依赖

需要安装sass-loadernode-sass

改写webpack.config.js文件

// path为Node的核心模块
const path = require('path');

module.exports = {
  // 其它配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]'
          }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(sass|scss)$/,
        use: ['style-loader','css-loader','sass-loader']
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

根目录下添加index-sass.sass文件

body{
  .avatar-sass{
    width: 150px;
    height: 150px;
  }
}
1
2
3
4
5
6

改写index.js

import avatar from './avatar.jpg';
import './index.css';
import './index-sass.sass';

var img = new Image();
img.src = avatar;
img.classList.add('avatar-sass');

var root = document.getElementById('root');
root.appendChild(img);
1
2
3
4
5
6
7
8
9
10

根据上面的配置和代码改写后,再次打包,打包的结果会是下面这个样子

打包结果

# 自动添加CSS厂商前缀

当我们在css文件中写一些需要处理兼容性的样式的时候,需要我们分别对于不同的浏览器书添加不同的厂商前缀,使用postcss-loader可以帮我们在webpack打包的时候自动添加这些厂商前缀。

安装依赖

自动添加厂商前缀需要npm install安装postcss-loaderautoprefixer

npm install postcss-loader autoprefixer -D
1

修改index-sass.sass

.avatar-sass {
  width: 150px;
  height: 150px;
  transform: translate(50px,50px);
}
1
2
3
4
5

在修改sass文件代码后,我们需要对webpack.config.js























 





// path为Node的核心模块
const path = require('path');

module.exports = {
  // 其它配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]'
          }
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(sass|scss)$/,
        use: ['style-loader','css-loader','sass-loader','postcss-loader']
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

根目录下添加postcss.config.js,并添加代码

module.exports = {
  plugins: [require('autoprefixer')]
}
1
2
3

根据上面的配置,我们再次打包运行,在浏览器中运行index.html,它的结果如下图所示

打包运行结果

# 模块化打包CSS文件

概念

CSS的模块化打包的理解是:除非我主动引用你的样式,否则你打包的样式不能影响到我。

根目录下添加createAvatar.js文件,并填写下面这段代码

import avatar from './avatar.jpg';
export default function CreateAvatar() {
  var img = new Image();
  img.src = avatar;
  img.classList.add('avatar-sass');

  var root = document.getElementById('root');
  root.appendChild(img);
}
1
2
3
4
5
6
7
8
9

改写index.js,引入createAvatar.js并调用


 



 








import avatar from './avatar.jpg';
import createAvatar from './createAvatar';
import './index.css';
import './index-sass.sass';

createAvatar();

var img = new Image();
img.src = avatar;
img.classList.add('avatar-sass');

var root = document.getElementById('root');
root.appendChild(img);
1
2
3
4
5
6
7
8
9
10
11
12
13

打包运行

打包运行

我们可以看到,在createAvatar.js中,我们写的img标签的样式,它受index-sass.sass样式文件的影响,如果要消除这种影响,需要我们开启对css样式文件的模块化打包。

进一步改写webpack.config.js






















 







// path为Node的核心模块
const path = require('path');

module.exports = {
  // 其它配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name]_[hash].[ext]'
          }
        }
      },
      {
        test: /\.(sass|scss)$/,
        use: ['style-loader', {
          loader: 'css-loader',
          options: {
            modules: true
          }
        }, 'sass-loader', 'postcss-loader']
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

开启css模块化打包后,我们需要在index.js中做一点小小的改动,像下面这样子




 





 




import avatar from './avatar.jpg';
import createAvatar from './createAvatar';
import './index.css';
import style from  './index-sass.sass';

createAvatar();

var img = new Image();
img.src = avatar;
img.classList.add(style['avatar-sass']);

var root = document.getElementById('root');
root.appendChild(img);
1
2
3
4
5
6
7
8
9
10
11
12
13

打包运行后,我们发现使用createAvatar.js创建出来的img没有受到样式文件的影响,证明我们的css模块化配置已经生效,下图是css模块化打包的结果:

打包结果