长跑是我个人的一种修行。我在跑步的时候,会有各种各样的想法。其实跑步就是一个锻炼精神强度的过程,不论进入脑海的想法多么恐怖,你还是要继续跑步,你还是要继续做你现在正在做的事情,这是一种意志品质,这种意志品质决定了你人生的意义以及高度。
webpack 虽然是一个模块打包工具,但是这不是它唯一的功能,也不是我们使用它的唯一目的。尽管 webpack 只能理解 JavaScript,但是它可以通过使用 loaders 来扩展功能。官方的文档是这样介绍它的:
Loaders can transform files from a different language (like TypeScript) to JavaScript or inline images as data URLs. Loaders even allow you to do things like import CSS files directly from your JavaScript modules!
添加 loaders
要使用 loaders,需要在 webpack.config.js
文件中声明它们,而要声明它们,你需要添加一个 module.rules
的属性。
css-loader
css-loader
模块会解析导入的 css 文件
$ npm install css-loader
参考下面的配置:
webpack.config.js
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
]
}
}
rules
rules 属性是一个包含了所有 loaders 的数组,这些规则会被应用在每一个能够匹配 test 属性的文件上。实际上,这是一种正则表达式。
use
use 属性声明了对应了这些文件所要使用的具体 loader。
将 loaders 链在一起
通过上面的代码,你就可以在你的 JavaScript 代码中引入 css 文件了。但是这样还不足以让 css 文件产生效果,我们需要一个东西来让浏览器理解这些代码。我们需要的是:style-loader
。
$ npm install style-loader
这样意味着我们需要对 css 文件使用两种不同的 loaders,你可以这样将 loaders 连接起来。
webpack.config.js
module.export = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
我们可以发现,use 属性不仅可以是单纯的字符串,还可以是数组。这样,就把 loaders 给连接起来了。值得注意的的是:在数组中的 loaders 是按照逆序执行的
style.css
body {
background-color: skyblue;
}
index.js
import './style.css'
通过这一系列的配置之后,整个工作的流程是这样的:
- webpack 会尝试解析
style.css
这个文件 - 文件名匹配了正则表达式:
/\.css$/
- 这个文件会被
css-loader
读取 -
css-loader
的结果会传递给style-loader
- 最后,
style-loader
会返回一段 JavaScript 代码
默认情况下,输出的整个打包文件时 ./dist/bundle.js
,现在这个文件将会把所有生成的样式添加到 <style>
标签中去,如果将 bundle.js
连接到 HTML 文件,那么运行之后的 HTML 文件会变成这样:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="../dist/bundle.js"></script>
<!--这里引入了 css 文件中的样式-->
<style type="text/css">body {
background-color: skyblue;
}
</style>
<title>Document</title>
</head>
<body>
</body>
</html>
sass-loader
通过已有的知识,你可以很轻松地让你的项目支持 sass / scss,我们需要的只是 sass-loader。
$ npm install sass-loader
你只需要将它添加到 loaders 的数组里就可以了。
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
}
}
现在你就可以在项目里添加 scss 文件啦,在通过 css-loader 之前,这些文件会从 scss 编译成 css。
给 loaders 一些参数
loaders 是可以接受一些额外的参数的,让我们用 url-loader
来举个例子。
$ npm install url-loader file-loader
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 5000
}
},
]
}
]
}
}
这里需要注意,如果你想要将参数传递给 loaders,不能再直接使用字符串的形式将它传递给 use 这个属性。现在,每个 loader 是一个具有两个属性的对象:分别是 loader 和 options。
url-loader
会将你的图片转换成 base64 格式。如果你的图片非常小,直接将它们放在你的代码中可能更利于性能,因为这可以让浏览器少发几次请求。如果你的图片很大,或许更好的做法是将它们分成多份,这样浏览器可以同步的获取它们。
这就是为什么 url-loader
这个 loader 会有 limit 这个属性。在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL。
Tips: 什么是 DataURL?
DataURL 给了我们一种很巧妙的将图片“嵌入”到 HTML 中的方法。跟传统的用
<img>
标记将服务器上的图片引用到页面中的方式不一样,在 DataURL 协议中,图片被转换成 base64 编码的字符串形式,并存储在 URL 中,冠以mime-type。我们可以使用 DataURL 优化网站加载速度和执行效率。
body {
background-image: url('./big-background.png');
}
.icon {
background-image: url('./icon.png');
}
上面的配置就会变成下面的样子
body {
background-image: url(ca3ebe0891c7823ff1e137d8eb5b4609.png);
}
.icon {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAALElEQVR4AWMYIWAU1FPLoP9AXEFI0QEi8H+YYdQyqIEaXuumRhh1DZdUMwoATlYWfwh9eYkAAAAASUVORK5CYII=);
}
使用 babel 转译(transpile) JavaScript
常见的 loader 还有就是 babel-loader 了。它可以使用 babel 转译 JavaScript 文件,这是一种使用最新版 JavaScript 来写代码的解决方案。它可以用来兼容以往的一些浏览器,也可以使用一些现代浏览器还不支持的语法特性。
$ npm install babel-loader babel-core babel-preset-env
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
};
这里我们使用了 exclude
这个属性,这里也是一个正则表达式,如果文件的路径与之相匹配的话,那么这个文件就不会被转译。
小结
这一次我们学习了 webpack 一个非常有用的特性:loaders。我们介绍了一些可以用到的 loaders,使用它们我们可以让项目支持 scss,不仅如此,还知道了如何用 url-loader 处理图片。另一个非常常用的 loader 就是 babel-loader,它用来对 javascript 进行转译(还知道了转译的目的)。接下来,我们会更加深入 loaders,还会自己动手写 loaders。
网友评论