【Webpack】预处理器 - loader配置介绍

预处理器 (loader) ,的主要功能是赋予了 Webpack 可处理不同资源类型的能力,极大丰富了其可扩展性。

一个Web工程通常会包含HTML、JS、CSS、模板、图片、字体等多种类型的静态资源,并且这些资源之间都存在着某种联系。对于 Webpack 来说,所有这些静态资源都是模块,可以像加载一个JS文件一样去加载它们,如在index.js中加载style.css:

dart 复制代码
//index.js
import './style.css'

这个style.css虽然是被加载在js文件中,但其实是可以被打包并生成在输出资源目录下,对index.js 文件也不会产生质性的影响。这句引用的实际意义是描述了JS 文件与 CSS 文件之间的依赖关系。

在实际开发中,有时某个页面用到了组件,不光要加载JS文件,还要加载样式,而通过Webpack我们可以采用一种更简洁的方式来表达这种依赖关系

dart 复制代码
// 。/u1/calendar/index.js
1mport './style.scss'; //引用组件自身样式

// ./page/home/index.js
import Calendar from './ui/calendar/index.js';
import './styles.css' ;// 引用页面自身样式

可以看到,在calendar的JS中加载了其组件自身的样式,而对于页面来说只要载calendar/index.js 即可(以及页面自身的样式),不需要额引入组件的样式。让Webpack维护模块间的关系可以使工程结构更加直观,代码的可维护性更强。

loader 概述

每个loader本质上都是一个函数。在 Webpack 4之前,函数的输人和输出都必须为字符串; 在Webpack 4之后,loader也同时支持抽象语法树 (AST)的传递,通过这种方法来减少重复的代码解析。用公式表达 loader的本质则为以下形式:

output = loader(input)

举一个例子,当我们使用babel-loader将ES6+的代码转化为ES5时,上面的公式如下:

dart 复制代码
ES5 =babel-loader(ES6+)

loader 可以是链式的。我们可以对一种资源设置多个loader,第一个loader 的输入是文件源码,之后所有 loader 的输入都为上一个loader 的输出。公式如下:

output = loaderA(loaderB(loaderC(input)))

如在工程中编译SCSS时,我们可能需要如下loader:

Style 标签=style-loader(css-loader(sass-loader(SCSS)))

loader 的配置

要注意loader 做的实际上是一个预处理的工作。

loader的引入

假设我们要处理CSS,首先依照 Webpack"一切皆模块"的思想,从一个JS文件加载一个CSS文件。

dart 复制代码
// app.js
import './style.css';

// style.css
body
	text-align; center;
	padding: 100px;
	color: #fff;
	background-color: #09c;
}

此时工程中还没有任何 loader,如果直接打包会看到报错提示

Webpack 无法处理 CSS语法,因此抛出了一个错误,并提示需要使用一个合适loader来处理这种文件。

下面把css-loader加到工程中。loader都是一些第三方npm模块,Webpack身并不包含任何loader,因此使用loader的第一步就是先从npm安装它。在工程目下执行命令:

dart 复制代码
npm install css-loader

接下来我们将 loader引人工程中,具体配置如下:

dart 复制代码
module.exports = {
	// ...
	module: {
		rules: {
			test: /\.csss/,
			use: {'css-loader'},
		}
	}
}

loader相关的配置都在module对象中 ,其中module.rules 代表了模块的处理规则 。每条规则内部可以包含很多配置项,这里我们只使用了最重要的两项一testuse

test
test 可接收一个正则表达式或者一个元素为正则表达式的数组,只有正则配上的模块才会使用这条规则。在本例中是匹配所有以css 结尾的文件。

use

use可接收一个数组,数组包含该规则所使用的 loader。在本例中只配置了一个css-loader,在只有一个loader 时也可以简化为字符串"css-loader"。

此时我们再进行打包,之前的错误应该已经消失了,但是 CSS 的样式仍然没有在页面上生效。这是因为css-loader 的作用仅仅是处理CSS 的各种加载语法 ,如果要使样式起作用还需要 style-loader来把样式插人页面。css-loade与style-loader通常是配合在一起使用的

链式loader

在处理某一类资源时我们都需要使用多个 loader。就比如上面的例子,用css-loader处理CSS的各类加载语法,再使用style-loader 来将样式字符串包装成style标签插入页面。

配置如下:

dart 复制代码
module.exports = {
	// ...
	module: {
		rules: {
			test: /\.csss/,
			use: ['style-loader','css-loader'],
		}
	}
}

我们把style-loader加到了css-loader前面,这是因为在Webpack打包时是按照数组从后往前的顺序将资源交给 loader 处理的,因此要把最后生效的放在前面。

loader options

loader作为预处理器通常会给开发者提供一些配置项,在引入loader 的时候可以通过options将它们传人。

下面是一些场景下loader的相关配置

exclude与 include
excludeinclude是用来排除或包含指定目录下的模块,可接收正则表达式或者字符串(文件绝对路径),以及由它们组成的数组。如下例:

dart 复制代码
rules: {
	test: /\.csss/,
	use: ['style-loader','css-loader'],
	exclude: /node_modules/,
}

上面配置的含义是node_modules 中的模块不会执行这条规则。该配置项通常是必加的,否则可能拖慢体的打包速度。

include的例子如下:

dart 复制代码
rules: {
	test: /\.csss/,
	use: ['style-loader','css-loader'],
	include: /src/,
}

include代表该规则只对正则匹配到的模块生效。

exclude和include 同时存在时,exclude的优先级更高

由于exclude优先级更高,我们可以对include中的子目录进行排除。请看下面的例子:

dart 复制代码
rules: {
	test: /\.csss/,
	use: ['style-loader','css-loader'],
	exclude:/src\/lib/,
	include: /src/,
}

通过include,我们将该规则配置为仅对 src 目录生效,但是仍然可以通过exclude排除其中的src/lib目录。

resource与issuer
resourceissuer可用于更加精确地确定模块规则的作用范围。就比如下面的例子:

dart 复制代码
// index.js
import ./style.css';

在Webpack 中,一般认为被加载模块是 resource ,而加载者是 issuer。如上面的例子中,resource为/path/of/app/style.css,issuer 是/path/of/app/index.js。

如果想要对 issuer 加载者也增加条件限制,则要额外写一些配置。比如,如果我们只让/src/pages目录下的JS可以引用CSS,应该如何设置呢?可以这样:

dart 复制代码
issuer: {
	test: /\.js$/,
	include: /src/pages/,
}

可以看到,我们添加了issuer 配置对象,其形式与之前对resource条件的配置并无太大差异。

enforce

enforce用来指定一个loader的种类,只接收"pre"或"post"两种字符电类型的值。

请看下面的例子:

dart 复制代码
rules:[
	{
		test: /\.js$/,
		enforce: 'pre',
		use:'eslint-loader',
	}
]

可以看到,在配置中添加了一个eslint-loader来对源码进行质量检测,其enforce的值为"pre",代表它将在所有正常 loader之前执行 ,这样可以保证其检测的代码是被其他loader 更改过的。

类似的,如果某一个loader 是需要在所有 loader 之后执行的也可以指定其enforce为"post"

事实上,我们也可以不使用enforce而只要保证loader顺序是正确的即可

配置enforce 主要的目的是使模块规则更加清晰,可读性更强 ,尤其是在实际工程中,置文件可能达到上百行的情况,难以保证各个loader 都按照预想的方式工作,使用enforce可以强制指定 loader的作用顺序

相关推荐
逐·風35 分钟前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫1 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦2 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子2 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山3 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享3 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
清灵xmf5 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨5 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL5 小时前
npm入门教程1:npm简介
前端·npm·node.js
小白白一枚1116 小时前
css实现div被图片撑开
前端·css