9种loader
1. babel-loader
-
作用
- 对代码进行预处理,常用于将 es6 语法 转换为 es5 语法,向下兼容老旧浏览器
-
安装
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript-
@babel/core- 核心底层依赖包
-
@babel/preset-env- 提供了 ES6 转 ES5 的语法规则和垫片
- 包含了 babel-preset-latest 的功能,并对其进行增强
-
@babel/preset-react- 提供了处理 react jsx 模板文件的功能
-
@babel/preset-typescript- 提供了处理 typescript 文件的功能,就不需要额外的更慢的
ts-loader,要求 babel 版本在 7+,会直接移除 TS 转为 JS,编译速度飞快 - 这种方法不需要安装 typescript 包,但需要根目录下新建
tsconfig.json文件配置 - 由于没安装 typescript 包,所以这种方法没有类型检查功能,可选如下方案补充
- 额外安装并配置脚本
"type-check": "tsc --watch",手动检查 - 使用 ESLint,用@typescript-eslint 配置 ESLint 来自动检查
- 使用 Vscode 带有的自动检查
- 额外安装并配置脚本
- 提供了处理 typescript 文件的功能,就不需要额外的更慢的
-
-
在 json 中配置
module: { rules: [ { test: /\.(m?js|jsx|ts|tsx)$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { cacheDirectory: true, presets: [ ["@babel/preset-env", { modules: false }], "@babel/preset-react", "@babel/preset-typescript", ], }, }, }, ]; }- test 表示只对
.js结尾的文件应用 - exclude 排除对 node_modules 目录下的应用
- use 可以同时指定 要使用的 loader 和 配置项 options
- 也可以直接用
loader: "babel-loader"替代,这样配置项就要写到单独的根目录.babelrc文件中:{ "presets": [ "@babel/preset-env", "@babel/preset-typescript" ] }
- 也可以直接用
- 配置项
- cacheDirectory 可以启用缓存机制,防止对未改变过的模块二次编译
- 这里
@babel/preset-env默认会将 ES6 转为 CommonJS,导致 tree-shaking 失效,所以需要配置modules: false禁用这个模块依赖解析
- test 表示只对
-
在 chain 中配置
config.module .rule("babel") .test(/\.(m?js|jsx|ts|tsx)$/) .exclude.add(/node_modules/) .end() .use("babel-loader") .loader("babel-loader") .options({ presets: [ "@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript", ], });
2. css-loader
-
css-loader
- 作用:
- 解析 js 内使用的
import './style.css'、@import './style.css',就像 js 解析 import 和 require 一样
- 解析 js 内使用的
- 作用:
-
style-loader【不建议使用】
- 作用: 把上面解析好的 css 直接插入到 DOM 中,即在 header 处用
<style></style>嵌入式引入 - 如果想保留独立的 css 文件,就不要用这个 loader,而是换成 mini-css-extract-plugin 去处理,就能生成 link 插入到 DOM 中
- 作用: 把上面解析好的 css 直接插入到 DOM 中,即在 header 处用
-
安装
npm i style-loader css-loader -D -
在 json 中配置
module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"] }, ], }, -
在 chain 中配置
config.module .rule("css") .test(/\.css$/) .use("style-loader") .loader("style-loader") .end() .use("css-loader") .loader("css-loader") .end();
CSS modules 支持
-
可以通过 options 开启 CSS modules 支持,实现作用域隔离
{ loader: "css-loader", options: { modules: true, localIdentName: "[name]__[local]__[hash:base64:5]" } }-
这里 localIdentName 的作用,就是指定生成的 class 的名字,由文件名、类名、5 位哈希拼成,比如如下用法
//style.css .title { color: purple; } //app.js import styles from "./style.css"; document.write(`<h1 class="${styles.title}">Hey</h1>`)- 会生成如下 class 名字
.style_title_1CFy6
- 会生成如下 class 名字
-
3. postcss-loader
-
作用
- 使用 PostCSS 对 css 做处理和优化
-
安装
npm i postcss-loader postcss -D- postcss 最新版本需要 webpack v5,如果是 v4,需要指定 postcss 版本为@4
- 需要在根目录下新建配置文件
postcss.config.js,添加各种工具的配置,比如autoprefixer、stylelint、postcss-cssnext等
-
在 json 中配置
module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"] }, ], }, -
在 chain 中配置
config.module .rule("css") .test(/\.css$/) .use("style-loader") .loader("style-loader") .end() .use("css-loader") .loader("css-loader") .end() .use("postcss-loader") .loader("postcss-loader") .end();
4. less-loader
-
作用
- 将 less 编译为 css,需要安装 less 包
-
安装
npm i less less-loader -D -
在 json 中配置
module: { rules: [ { test: /\.less/, use: ["style-loader", "css-loader", "less-loader"] }, ], }, -
在 chain 中配置
config.module .rule("css") .test(/\.css$/) .use("style-loader") .loader("style-loader") .end() .use("css-loader") .loader("css-loader") .end() .use("less-loader") .loader("less-loader") .end();
。5 sass-loader
-
作用
- 将 Sass/SCSS 编译为 css,需要安装 sass 包
-
安装
npm i sass sass-loader -D -
在 json 中配置
module: { rules: [ { test: /\.s[ac]ss/, use: ["style-loader", "css-loader", "sass-loader"] }, ], }, -
在 chain 中配置
config.module .rule("css") .test(/\.css$/) .use("style-loader") .loader("style-loader") .end() .use("css-loader") .loader("css-loader") .end() .use("sass-loader") .loader("sass-loader") .end();
5.file-loader
-
作用
- 解析代码中的 url 引入,并将 url 资源(比如图片)拷贝到相应的打包路径
- 同时在代码内修改为这个路径,使之指向正确的文件
- 还能生成版本 hash 值到文件名,从而获得更好的缓存
-
注意
- 一般来说,只建议对字体文件使用这个 loader
- webpack 5 内置了另一种解决方案,可以做替换
{ test: /(\.(eot|ttf|woff|woff2|otf)|font)$/, type: 'asset/resource' } - 而对于图片等资源,有更好的 url-loader 可以使用,且 url-loader 本身就封装了 file-loader 的功能
-
安装
npm i file-loader -D -
在 json 中配置
module: { rules: [ { test: /(\.(eot|ttf|woff|woff2|otf)|font)$/, use: [ { loader: "file-loader", options: { outputPath: "fonts/" } } ] }, ], }, -
在 chain 中配置
config.module .rule("font") .test(/(\.(eot|ttf|woff|woff2|otf)|font)$/) .use("file-loader") .loader("file-loader") .options({ outputPath: "fonts/", }) .end();
6. url-loader
-
作用
- 参考 file-loader,只是多出下面的特性
- 可以按照 limit 参数来划分
- 小于 limit 的文件,会转为 DataURL base64 内容 inline 内嵌到代码中,避免请求 http 数过多
- 大于 limit 的文件,会调用 file-loader 进行处理
-
注意
- 不能对字体文件使用这个 loader,因为字体文件转成 base64 后浏览器无法识别
- webpack 5 内置了小图片的 inline 方案,但不建议做替换
{ test: /\.svg$/, type: 'asset/inline' }
-
安装
npm i url-loader -D -
在 json 中配置
module: { rules: [ { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, use: [ { loader: "url-loader", options: { limit: 10240, name: utils.assetsPath("img/[name].[hash:8].[ext]") } } ] }, ], }, -
在 chain 中配置
config.module .rule("url") .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/) .use("url-loader") .loader("url-loader") .options({ limit: 10000, name: utils.assetsPath("img/[name].[hash:8].[ext]"), }) .end();
7.html-loader
-
作用
- 支持导入 html 类型的文件,并生成为字符串
import html_string from "./xxx.html"; document.write(html_string);
- 支持导入 html 类型的文件,并生成为字符串
-
安装
npm i html-loader -D -
在 json 中配置
module: { rules: [ { test: /\.html$/, use: ["html-loader"] }, ], }, -
在 chain 中配置
config.module .rule("html") .test(/\.html$/) .use("html-loader") .loader("html-loader") .end();
8.js-conditional-compile-loader
-
作用
- 支持条件编译
-
安装
npm i js-conditional-compile-loader -D -
在 json 中配置
module: { rules: [ { test: /\.(m?js|jsx|ts|tsx)$/, use: [{ loader: "js-conditional-compile-loader", options: { isMainland: globalConfig.isMainland, isOversea: !globalConfig.isMainland } }] }, ], },- 可以用 isMainland 和 isOversea 作为布尔标志,去决定哪些内容应该被加入到生产编译
-
在 chain 中配置
config.module .rule("conditional") .test(/\.tsx$/) .use("js-conditional-compile-loader") .loader("js-conditional-compile-loader") .options({ isMainland: globalConfig.isMainland, isOversea: !globalConfig.isMainland, }) .end(); -
使用案例
/* IFTRUE_isMainland const logo = logoMainLand FITRUE_isMainland */ /* IFTRUE_isOversea const logo = overseaLogo FITRUE_isOversea */- 如果 isMainland 为 true,那上面那一条会在生产环境被加入
- 如果 isOversea 为 true,那下面那一条会在生产环境被加入
- 为了防止开发环境没有 logo 变量的定义,需要加入如下代码
/* IFDEBUG */ const logo = globalConfig.isMainland ? logoMainLand : logoOversea; /* FIDEBUG */- 只有在开发环境才会原样使用这个代码,否则就移除
9.自定义 loader
实现一个 loader,在每个 js 文件最开始加上 开启严格模式 的一行代码
-
创建一个新目录
touch force-strict-loader && cd force-strict-loader -
初始化
npm init -y -
安装依赖,用来获取外面传入的 options
npm i loader-utils -D -
创建 index.js 文件,并填入如下内容
let loaderUtils = require("loader-utils"); module.exports = function (content) { if (this.cacheable) { this.cacheable(); } const options = loaderUtils.getOptions(this) || {}; console.log("options", options); var useStrictPrefix = "'use strict';\n\n"; return useStrictPrefix + content; };- cacheable 可以启用缓存,输入没变化时无需重复转换
-
在工程中安装这个 loader
npm i <path-to-loader>/force-strict-loader -D- 会在 node_modules 目录内创建一个软链接
-
使用
rules: [ { test: /\.js$/, use: "force-strict-loader", }, ];