webpack入门系列教程-加载器

简介


  loader用于对模块的源代码进行转换,在import或加载模块时,对文件进行预处理。loader可将文件从不同的语言(如TypeScriptsess、或自定义语言)转换为JavaScript(前提是你得有相应的loader),亦可将内联图像转换为data URL

常用loader


  日常开发中,常用loader如下:

  • css-loader:遍历css文件,处理样式
  • style-loader:将样式插入到<style></style>标签中
  • sass-loader: 便利文件,解析sass格式样式表
  • url-loader: 根据需求将图片自动转成base64编码,减少网络负载
  • file-loade:解决项目中,url资源的引入问题(ttf、woff、eot…等)
  • babel-loader:添加ES6语法支持

loader的使用


模块安装

  首先,安装相应的loader:

1
2
# cd ~/project
# npm install file-loader css-loader style-loader sass-loader url-loader babel-loader --save-dev

  接下来需要安装对应的解释器(loader可以理解成加载相应的模块,而解释器则是对加载后的模块进行翻译,生成最终的可执行代码)

1
# npm install babel-preset-env@next node-sass --save-dev

  babel-preset-env@nextnode-sass分别解释babel-loadersass-loader的加载结果,那么你可能会问:“为什么其它的loader不需要安装解释器?”。原因是babel-loadersass-loader的加载结果,并不是所有浏览器都能直接执行的,因此必须重新将它们翻译成通用的可执行代码。
  这里需要注意的是,在安装node-sass的时候会安装不上,错误原因大概是其必须的二进制文件未下载成功,解决方法在这里贴出来,未能亲测(因为我之前安装成功过,直接把原来的拷贝过来了)。后续有时间,将会亲自测试这里。

1
# npm install node-sass --save-dev --registry=https://registry.npm.taobao.org --disturl=https://npm.taobao.org/dist --sass-binary-site=http://npm.taobao.org/mirrors/node-sass

本篇中暂不涉及到babel-loaderbabel-preset-env@next的使用

编写测试代码

  首先我们补全测试用目录及文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
projerct
├── app
│   ├── index.js
│   └── lib.js
│   └── es6.js
├── build
├── node_modules
│   ├── ...
├── package.json
├── package-lock.json
├── source
│   ├── image
│   ├── style
│   │   ├── css
│   │   │   └── index.css
│   │   └── sass
│   │   ├── index.scss
│   │   └── variables.scss
│   └── template
│   └── index.html
└── webpack.config.js

  其中source/imagesource/style/css/source/style/sass/为新增目录,分别存放图片资源、css资源文件、sass资源文件。同时在source/style/css/目录中增加index.css文件、source/style/sass/目录中增加variables.scssindex.scss文件。同时在app/目录下增加es6.js文件。

  修改我们位于source/template/index.html中的模板文件,分别建立针对css样式与sass样式的两个div容器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<head>
<meta charset="UTF-8">
<title>My template app</title>
</head>
<body>
<div class="css">
<div><h1>css</h1></div>
<div><h1>css</h1></div>
<div><h1>css</h1></div>
</div>
<div class="sass">
<div><h1>sass</h1></div>
<div><h1>sass</h1></div>
<div><h1>sass</h1></div>
</div>
</body>
</html>

  编辑source/style/css/index.css,使拥有 .css 类名的div容器字体呈现红色:

1
2
3
.css {
color: red;
}

  编辑source/style/scss/variables.scss,定义一个颜色变量:

1
$color: blue;

  编辑source/style/scss/index.scss,引入刚刚定义的变量,使拥有 .sass 类名的div容器字体呈现蓝色,并且为body添加一个背景图片:

1
2
3
4
5
6
7
8
9
@import "./variables.scss";

.sass {
color: $color
}

body {
background: url('../../image/1.jpg');
}

  编辑app/es6.js

1
2
3
4
5
export class Test {
constructor(name) {
this.name = name;
}
}

  编辑app/index.js,引入上述资源文件及模块:

1
2
3
4
5
6
7
8
9
10
require('../source/style/css/index.css');
require('../source/style/sass/index.scss');

import {Test} from './es6.js';

let name = new Test("Baichao Jiang")

let element = document.createElement('h2');
element.innerHTML = "My name is " + name.name;
document.body.appendChild(element);

  这里需要注意一点,import的模块名,必须与文件内所导出的类名一致。例如我们app/es6.js中写的是export class Text,那么在import时,后面必须跟的是{Test}才行。
  在最后,编辑webpack.config.js,配置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
29
30
31
32
33
34
35
36
37
38
39
40
41
var path = require('path');
var hwp = require('html-webpack-plugin')

var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
var SOURCE_PATH = path.resolve(ROOT_PATH, 'source');

module.exports = {
mode: 'development',
entry: APP_PATH,
output: {
path: BUILD_PATH,
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.s?css$/,
loaders: ['style-loader', 'css-loader', 'sass-loader'],
include: ROOT_PATH
}, {
test: /\.(jpe?g|png|gif|ico)$/,
loader: 'url-loader?limit=10240'
}, {
test: /\.((ttf|eot|woff2?|svg)(\?v=[0-9]\.[0-9]\.[0-9]))|(ttf|eot|woff2?|svg)$/,
loader: 'url-loader?limit=10000&name=fonts/[hash:8].[name].[ext]'
}]
},
plugins: [
new hwp({
title: 'hello world app',
template:__dirname + '/source/template/index.html'
})
],
devServer: {
historyApiFallback: true,
hot: true,
inline: true,
progress: true,
},
}

运行

  在前面一节中,我们使用了ebpack-dev-server插件,因此直接运行就可以

1
# npm start

  之后在浏览器产看页面即可,最终的页面效果如下:
图片无法显示

遇到的几个错误


非程序错误

  1. 标点符号别写错
  2. 目录、文件名、类名等英文字母别打错

webpack4 加载器关键字用rules

  在某个版本之前,一直是用loaders做关键字的,后来应该是升级为rules了。在这里卡了半天。

loaders里面要的写法

  如果直接写成[css, style,…]会出现如下错误信息:

1
2
3
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.
You need to specify 'style-loader' instead of 'style',
see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed

  解决方法是写成['*-loader',...]*代表所需的加载器模块名。该解决方案来自于https://github.com/tcoopman/

未完待续

谢谢你的支持