Webpack Loader知识分享
写作不易,未经作者允许禁止以任何形式转载!
如果觉得文章不错,欢迎关注、点赞和分享!
认识 Loader
Loader 可以用于对模块的源代码进行转换;
在加载这个模块时,webpack 其实并不知道如何对其进行加载,我们必须定制对应的 loader 来完成这个功能。
loader 配置方式
-
内联方式:
import "css-loader!../css/index.css"
; loader 和文件路径用!分隔 -
配置方式:webpack.config.js
-
配置方式表示的意思是在我们的 webpack.config.js 文件中写明配置信息
- module.rules 中允许我们配置多个 loader(因为我们也会继续使用其他 Loader,来完成其他文件的加载)
- 这种方式可以更好地标识 loader 配置,也方便后期的维护,同时也让你对各个 Loader 有一个全局的概览;
-
module.rules 的配置如下
-
rules 属性对应的值是一个数组:[Rule]
-
数组中存放的是一个个 Rule,Rule 是一个对象,对象中可以设置多个属性
- test 属性:用于多 resource(资源)文件名进行匹配,通常会设置成正则表达式;
- use 属性:对应的值是一个数组[useEntry]
- 执行顺序从后往前,比如解析 css,css-loader 应在 style-loader 后面。
- UseEntry 是一个对象,可以通过对象的属性来设置一些其他属性
- loader:必须有一个 loader 属性,对应的值是一个字符串
- options:可选的属性,值是一个字符串或者对象,值会被传入到 loader 中;
- query:目前已被 options 替代
- 传递字符串(如:use:[‘style-loader’])是 loader 属性的简写(如:use:[{loader:‘style-loader’}])
常见 Loader
CSS loader
-
我们可以将 css 文件也看成是一个模块,我们是通过 import 来加载这个模块的
-
那么需要一个什么样的 loader 呢
-
对于加载 css 文件来说,我们需要一个可以读取 css 文件的 loader
-
最常用的是 css-loader
-
只负责解析 css 文件,不会作用于页面,此外还需要 style-loader 作用于页面
npm i style-loader --save
-
-
css-loader 的安装:
npm install css-loader --save
-
以下为一个 css-loader 的配置文件
const path = require('path'); |
-
less 同理
npm install less-loader less --save
安装这两个插件后 -
依次在 use 数组内写入 style-loader、css-loader、less-loader
浏览器兼容性
-
如果在 css 兼容性和 js 兼容性下共享我们的配置兼容性条件呢
- 就是当我么们设置了一个条件:>1% last 2 version Firefox、Chrome… not dead 都是可选项,多个选项以,分隔为 || 条件;and 为&&关系;可用 not 条件
- 意思为 js、css 兼容市场占有率大于 1%的 Firefox、Chrome 浏览器和最新的两个版本,并且 24 个月内有官方支持和更新的浏览器(dead 过滤条件)
-
在根目录.browserlistrc 文件编写条件
-
通过可实现对市场占有比率的要去,版本要求等进行配置,适配浏览器
-
所用工具:
- 数据来源:browserlist,浏览器市场占有率,精确到每个版本
- 处理插件:autoprefixer、babel、postcss-preset-env 等
认识 PostCSS 工具
-
什么是 PostCSS 工具呢?
- PostCSS 是一个通过 JavaScript 来转换样式的工具
- 这个工具可以帮助我们进行一些 CSS 样式的转换和适配,比如自动添加浏览器前缀、css 样式的充值;
- 但是实现这些功能,我们需要借助于 PostCSS 插件
-
如何使用 PostCSS
- 查找 PostCSS 在构建工具中的扩展,比如 webpack 中的 postcss-loader;
- 选择可以添加你需要的 PostCss 相关插件
手动使用 PostCSS
使用 postcss-cli 操作,需要用到 autoprefixer 插件
npm install postcss postcss-cli --save
npm install autoprefixer --save
npx postcss --use autoprefixer -o '输出路径' '输出路径'
,例如:npx postcss --use autoprefixer -o ./src/css/result.css ./src/css/user.css
Webpack 配置文件使用 PostCSS
- 安装 postcss-loader 和 autoprefixer
npm install postcss-loader autoprefixer --save
- 编写配置文件
- css-loader 处理前先用 postcss-loader 处理
- 在 options 的 postcssOptions 中,配置 plugins,使用 autoprefixer
{ |
postcss-preset-env
-
事实上,在配置 postcss-loader 时,我们配置插件并不需要使用 autoprefixer。
-
我们可以使用另外一个插件:postcss-preset-env
-
postcss-preset-env 也是一个 postcss 的插件;
-
它可以帮助我们将一些现代的 CSS 特性,转成大多数浏览器认识的 CSS,并且会根据目标浏览器或者运行时环 境添加所需的 polyfill;
- 例如八位的十六进制颜色会帮我们转换成 RGBA
-
也包括会自动帮助我们添加 autoprefixer(所以相当于已经内置了 autoprefixer);
-
首先,我们需要安装 postcss-preset-env:
npm install postcss-preset-env --save
-
之后,我们直接修改掉之前的 autoprefixer 即可:
-
-
配置简化
- 在 use 中只写 postcss-loader
- 在项目根目录建立 postcss.config.js,写入配置
webpack.config.js
const path = require('path'); |
postcss.config.js
module.exports = { |
效果
Before
:fullscreen { |
After
:-webkit-full-screen { |
importLoaders
-
正常 css 文件解析遇到@import,不会再从 use 数组最后一个 loader 开始重新解析
-
通过设置 importLoaders 可以实现递归解析
-
填写的数字为在 use 数组中往后的 loader 的数量
-
例如:
const path = require('path'); |
File Loader
希望解析、读取文件,例如图片
- 安装 file-loader
npm install --save file-loader
- 编写配置文件
rule:
- options 解释:
- name:输出名称,[name]名称引用,.字符,[hash:6]哈希信息截取 6 位,[ext]后缀名
- ouputPath:输出的文件夹,也可以在文件名前加 img/
{ |
- 和 file-loader 有同样功能的还有 url-loader
- 不同的是,它不是打包,而是把图片转为 BASE64 编码。
- 可以通过 use 对象的 options 下写入 limit 属性,限制大小,对小图片进行 BASE4 编码,减少请求数。
Asset module type
-
我们当前使用的 webpack 版本是 webpack5:
- 在 webpack5 之前,加载这些资源我们需要使用一些 loader,比如 raw-loader 、url-loader、file-loader;
- 在 webpack5 之后,我们可以直接使用资源模块类型(asset module type),来替代上面的这些 loader;
-
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:
- asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现;
- asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现;
- asset/source 导出资源的源代码。之前通过使用 raw-loader 实现;
- asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源
-
比如加载图片,我们可以使用下面的方式:
// 打包图片 |
- 但是,如何可以自定义文件的输出路径和文件名呢?
- 方式一:修改 output,添加 assetModuleFilename 属性;
- 方式二:在 Rule 中,添加一个 generator 属性,并且设置 filename;
// 方式一 ouput对象 |
加载字体文件
rule 对象:
{ |
自定义 Loader
Loader 是用于对模块的源代码进行转换处理,之前已经使用过很多 Loader,例如 css-loader、style-loader、babel-loader 等
-
Loader 本质是一个导出为函数的 JavaScript 模块
-
Loader runner 库会调用这个函数,然后将上一个 loader 产生的结果或者资源文件传入进去。
-
编写一个自定义 Loader 会接收三个参数
- content:资源文件参数
- map:sourcemap 相关数据
- meta:一些元数据
-
注:传入的路径是和 content 有关系的
- webpack.config.js
{ |
- 如果希望直接去加载 loader 文件夹,可以配置 resoveLoader 属性
module: { |
- 多个 Loader 使用执行顺序
- 从后向前,从右向左
rules: [ |
- 结果
Pitch-Loader 和 enforce
事实上还有另一种 Loader,称之为 PitchLoader
-
其实这也是为什么 loader 的执行顺序是相反的
- run-loader 先优先执行 PitchLoader,在执行 PitchLoader 时进行 loaderIndex++;
- run-loader 之后会执行 NormalLoader,在执行 NormalLoader 时进行 loaderIndex–;
-
那么,怎么改变他们的执行顺序?
- 可以拆分成多个 Rule 对象,通过 enforce 来改变它们的顺序
- enforce 是 rule 对象的一个属性。
-
enforce 一共有四种方式
- 默认所有 loader 都是 normal
- 在行内设置的 loader 都是 inline
- 也可以通过 enforce 设置 pre 和 post
-
在 Pitch 和 Normal 它们的执行顺序分别是
- post、inline、normal、pre
- pre、normal、inline、post
同步的 Loader
-
什么是同步 loader?
- 默认创建的 Loader 就是同步的 Loader
- 这个 Loader 必须通过 return 或者 this.callback 来返回结果,交给下一个 loader 来处理
- 通常在有错误的情况下,会使用 this.callback
-
this.callback 用法如下
- 第一个参数为 ERR 或者 null
- 第二个参数是 string 或者 buffer
- loader.js
module.exports = function (content) { |
异步的 Loader
-
什么是异步的 Loader
- 有时候使用 Loader 进行一些异步的操作
- 我们希望在异步操作完成之后,再返回这个 loader 处理的结果
- 这个时候就要使用异步的 Loader 了
-
loader-runner 已经在执行 loader 时给我们提供了方法,让 loader 变成一个异步的 loader
-
loader.js
module.exports = function (content) { |
传入和获取参数
-
在使用 loader 时传入参数,
-
可以通过 webpack 官方提供的一个解析库 loader-utils
npm i loader-utils
-
webpack.config.js
{ |
- optionLoader.js
const { getOptions } = require('loader-utils'); |
参数校验
-
可以通过 wepack 官方提供的校验库 schema-utils
npm i schema-utils
-
schema.json(校验规则)
{ |
- loader.js
const { getOptions } = require('loader-utils'); |
babel-loader 案例
-
我们知道 babel-loader 可以进行 JS 代码转换
-
接下来尝试定义一个自己的 babel-loader
-
myBabelLoader.js
const babel = require('@babel/core'); |
- babelSchema.json
{ |
- webapck.config.js
module: { |
自定义 md-loader
-
借助 marked 和 highlight 库实现 markdownLoader
npm i marked highlight.js
-
webpack.config.js
- 配置 css 加载和 md 加载规则
rules: [ |
- mdLoader.js
- 使用 marked 和 highlight 处理 content,并返回模块化代码
const marked = require('marked'); |
- main.js
- 同时引入 css 文件
import md from './index.md'; |
- 效果