文章目录

  • 1. Loader 分类与执行顺序
    • 1.1 Loader 分类
    • 1.2 Loader 执行顺序
    • 1.3 使用Loader方式
      • 1.3.1 内联 Loader
  • 2. 开发 Loader 步骤
    • 2.1 开发环境
    • 2.2 最简单的 Loader
    • 2.3 Loader 分类
      • 2.3.1 同步 Loader
      • 2.3.2 异步 loader
      • 2.3.3 Raw Loader
      • 2.3.4 Pitching Loader
    • 2.4 loader API
  • 3. 自定义Loader
    • 3.1 clean-log-loader
    • 3.2 banner-loader
    • 3.3 babel-loader
    • 3.4 file-loader
  • 4. 小结

webpack作为前端项目的打包工具,具有很好的学习价值。下面来学习下其中的 Loader

Loader可以帮助webpack将不同类型的文件转换为webpack可识别的模块

webpackLoader使用:https://www.webpackjs.com/loaders/

webpackLoader API的介绍:https://www.webpackjs.com/api/loaders/

Webpack中,默认的配置文件为:webpack.config.js。在学习Loader之前,要先了解下webpack.config.jsvue.config.js的区别:

  • webpack.config.jswebpack的配置文件,所有使用webpack作为打包工具的项目都可以使用,vue项目可以使用,react项目也可以使用

  • vue.config.jsvue项目的配置文件,专用于vue项目。通过vue.config.js中常用功能的配置,简化配置工作,当然如果需要更专业的配置工作,两者在vue项目中是可以并存的

  • vue-cli3创建项目时并不会自动创建vue.config.js,因为这个是可选项,所以一般都是修改webpack时才会自己创建一个vue.config.js

  • 因为vue-cli3内部高度集成了webpack,一般来说使用者不需要再为webpack做什么配置,所以没有暴露webpack的配置文件,但开发中依然可以创建vue.config.js去修改默认的webpack

  • Vue项目中 vue.config.js 文件就等同于 webpackwebpack.config.js

vue 中配置文件说明:https://cli.vuejs.org/zh/config/

1. Loader 分类与执行顺序

1.1 Loader 分类

  • pre: 前置 loader
  • normal: 普通 loader
  • inline: 内联 loader
  • post: 后置 loader

1.2 Loader 执行顺序

  • 4 类 loader 的执行优级为:pre > normal > inline > post
  • 相同优先级的 loader 执行顺序为:从右到左,从下到上
// 此时loader执行顺序:loader3 - loader2 - loader1
module: {rules: [{test: /\.js$/,loader: "loader1",},{test: /\.js$/,loader: "loader2",},{test: /\.js$/,loader: "loader3",},],
},
// 此时loader执行顺序:loader1 - loader2 - loader3
module: {rules: [{enforce: "pre",test: /\.js$/,loader: "loader1",},{// 没有enforce就是normaltest: /\.js$/,loader: "loader2",},{enforce: "post",test: /\.js$/,loader: "loader3",},],
},

1.3 使用Loader方式

  • 配置方式:在 webpack.config.js 文件中指定 loader。(prenormalpost
  • 内联方式:在每个 import 语句中显式指定 loader。(inline loader

1.3.1 内联 Loader

用法:import Styles from 'style-loader!css-loader?modules!./styles.css';

含义:

  • 使用 css-loaderstyle-loader 处理 styles.css 文件
  • 通过 ! 将资源中的 loader 分开

inline loader 可以通过添加不同前缀,跳过其他类型 loader

  • ! 跳过 normal loader

import Styles from '!style-loader!css-loader?modules!./styles.css';

  • -! 跳过 prenormal loader

import Styles from '-!style-loader!css-loader?modules!./styles.css';

  • !! 跳过 prenormalpost loader

import Styles from '!!style-loader!css-loader?modules!./styles.css';

2. 开发 Loader 步骤

2.1 开发环境

新建一个文件在,并在里面新建一个webpack.config.js文件,同时新建srcpublic文件夹,具体目录结构如下:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {entry: './src/main.js',output: {path: path.resolve(__dirname, './dist'),filename: 'js/[name].js',clean: true,},module: {rules: [{test: /\.js$/,loader: './loaders/test-loader/test-loader.js',},],},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, 'public/index.html'),}),],mode: 'development',
}

然后打开终端,来到项目根目录,分别运行以下指令:

  • 初始化package.json,此时会生成一个基础的 package.json 文件
npm init -y
  • 下载依赖
npm i webpack webpack-cli -D

  • 安装html-webpack-plugin插件

    该插件生成一个HTML文件,使用自己提供的模板

  • 编写main.js文件

// 很简单的一句打印
console.log('hello main')
  • 启用 Webpack
开发模式:npx webpack ./src/main.js --mode=development
生产模式:npx webpack ./src/main.js --mode=production

npx webpack: 是用来运行本地安装 Webpack 包的。./src/main.js: 指定 Webpackmain.js 文件开始打包,不但会打包 main.js,还会将其依赖也一起打包进来。--mode=xxx:指定模式(环境)

npx是执行Node软件包的工具,它从npm5.2版本开始,就与npm捆绑在一起

npx作用:

  • 默认情况下,首先检查路径中是否存在要执行的包(即在项目中)
  • 如果存在,它将执行
  • 若不存在,意味着尚未安装该软件包,npx将安装其最新版本,然后执行它

执行完上面操作后,会在项目根目录下生成一个dist文件夹,把其中的index.html文件在浏览器打开

2.2 最简单的 Loader

loaders文件夹下新建test-loader/test-loader.js文件

// loaders/test-loader/test-loader.js
module.exports = function (content, map, meta) {console.log('hello test loader ... ')// 将源文件中的main替换成webpackreturn content.replace('main', 'webpack')
}

它接受要处理的源码作为参数,输出转换后的 js 代码。Loader 接受的参数

  • content:源文件的内容
  • mapSourceMap 数据
  • meta数据:可以是任何内容

webpack.config.js文件中,使用该Loader

module: {rules: [{test: /\.js$/,loader: './loaders/test-loader/test-loader.js',},],
},

执行打包命令,并查询运行结果:

2.3 Loader 分类

2.3.1 同步 Loader

module.exports = function (content, map, meta) {return content;
};

this.callback 方法则更灵活,因为它允许传递多个参数,而不仅仅是 content

module.exports = function (content, map, meta) {/*第一个参数:err 代表是否有错误第二个参数:content 处理后的内容第三个参数:source-map 继续传递source-map第四个参数:meta 给下一个loader传递参数*/this.callback(null, content, map, meta);// 同步loader中不能进行异步操作return; // 当调用 callback() 函数时,总是返回 undefined
};

2.3.2 异步 loader

module.exports = function (content, map, meta) {// 异步操作const callback = this.async();// 进行异步操作setTimeout(() => {callback(null, result, map, meta);}, 1000);
};

由于同步计算过于耗时,在 Node.js 这样的单线程环境下进行此操作并不是好的方案,建议尽可能地使loader 异步化。但如果计算量很小,同步 loader 也是可以的。

2.3.3 Raw Loader

默认情况下,资源文件会被转化为 UTF-8 字符串,然后传给 loader。通过设置 rawtrueloader 可以接收原始的 Buffer

module.exports = function (content) {// content是一个Buffer数据return content;
};
module.exports.raw = true; // 开启 Raw Loader

2.3.4 Pitching Loader

module.exports = function (content) {return content;
};
module.exports.pitch = function (remainingRequest, precedingRequest, data) {console.log("do somethings");
};

webpack 会先从左到右执行 loader 链中的每个 loader 上的 pitch 方法(如果有),然后再从右到左执行 loader 链中的每个 loader 上的普通 loader 方法

在这个过程中如果任何 pitch 有返回值,则 loader 链被阻断。webpack 会跳过后面所有的的 pitch 和 loader,直接进入上一个 loader

2.4 loader API

方法名 含义 用法
this.async 异步回调 loader。返回 this.callback const callback = this.async()
this.callback 可以同步或者异步调用的并返回多个结果的函数 this.callback(err, content, sourceMap?, meta?)
this.getOptions(schema) 获取 loader 的 options this.getOptions(schema)
this.emitFile 产生一个文件 this.emitFile(name, content, sourceMap)
this.utils.contextify 返回一个相对路径 this.utils.contextify(context, request)
this.utils.absolutify 返回一个绝对路径 this.utils.absolutify(context, request)

3. 自定义Loader

3.1 clean-log-loader

需求:清理 js 代码中的console.log

  • loaders文件夹下新建clean-log-loader/clean-log-loader.js文件
// loaders/clean-log-loader/clean-log-loader.js
module.exports = function cleanLogLoader(content) {// 将console.log替换为空return content.replace(/console\.log\(.*\);?/g, "");
};
  • webpack.config.js文件中,使用该Loader
module: {rules: [{test: /\.js$/,loader: './loaders/clean-log-loader/clean-log-loader.js',},],
},

3.2 banner-loader

需求:给 js 代码添加文本注释

  • loaders文件夹下新建banner-loader/banner-loader.jsschema.json文件
const schema = require("./schema.json");module.exports = function (content) {// schema对options的验证规则// schema符合JSON Schema的规则const options = this.getOptions(schema);const prefix = `/** Author: ${options.author}*/`;return prefix + content;
};
  • loaders/banner-loader/schema.json文件可以对在配置loader时的参数进行校验
{"type": "object","properties": {"author": {"type": "string"}},"additionalProperties": false
}
  • webpack.config.js配置文件
{test: /\.js$/,loader: "./loaders/banner-loader/banner-loader.js",// 传入的参数options: {author: "scorpios",},
},

3.3 babel-loader

需求:编译 js 代码,将 ES6+语法编译成 ES5语法。(虽然这个功能已经有现场的loader,但可以自己模拟,加深理解)

  • 下载依赖
npm i @babel/core @babel/preset-env -D
  • loaders文件夹下新建babel-loader/babel-loader.jsschema.json文件
const babel = require("@babel/core");
const schema = require("./schema.json");// https://www.babeljs.cn/docs/babel-coremodule.exports = function (content) {// 异步loaderconst callback = this.async();const options = this.getOptions(schema);// 使用babel对代码进行编译babel.transform(content, options, function (err, result) {if (err) callback(err);else callback(null, result.code);});
};
  • loaders/banner-loader/schema.json
{"type": "object","properties": {"presets": {"type": "array"}},"additionalProperties": true
}
  • webpack.config.js配置文件
{test: /\.js$/,loader: "./loaders/babel-loader/babel-loader.js",options: {presets: ["@babel/preset-env"],},
}

3.4 file-loader

需求:将文件原封不动输出出去

  • 下载包
npm i loader-utils -D
  • loaders文件夹下新建file-loader/file-loader.js文件
const loaderUtils = require("loader-utils");module.exports = function (content) {// 1. 根据文件内容生成带hash值文件名let interpolatedName = loaderUtils.interpolateName(this, "[hash].[ext][query]", {content,});interpolatedName = `images/${interpolatedName}`// console.log(interpolatedName);// 2. 将文件输出出去this.emitFile(interpolatedName, content);// 3. 返回:module.exports = "文件路径(文件名)"return `module.exports = "${interpolatedName}"`;
};// 需要处理图片、字体等文件。它们都是buffer数据
// 需要使用raw loader才能处理
module.exports.raw = true;
  • webpack.config.js配置文件
{test: /\.(png|jpe?g|gif)$/,loader: "./loaders/file-loader/file-loader.js",type: "javascript/auto", // 解决图片重复打包问题
},

4. 小结

Loader就是一个函数, 当webpack解析资源时,会调用相应的Loader去处理, Loader接受到文件内容作为参数,返回内容出去。

  • content: 文件内容
  • mapSourceMap
  • meta: 别的Loader传递的数据

Webpack之Loader原理及自定义Loader相关推荐

  1. vue-cli Webpack之Loader原理及自定义Loader

    文章目录 1. Loader 分类与执行顺序 1.1 Loader 分类 1.2 Loader 执行顺序 1.3 使用Loader方式 1.3.1 内联 Loader 2. 开发 Loader 步骤 ...

  2. webpack loader解析及自定义loader

    自定义实现webpack loader加载模块,解析指定的类型文件 loader loader是一个导出为函数的node模块,可通过this访问上下文. 特点: loader单一职责,只负责解决单一的 ...

  3. webpack自定义loader

    创建自己的Loader 创建自己的Loader Loader是用于对模块的源代码进行转换(处理),css-loader.style-loader.babel-loader等. 如何自定义自己的Load ...

  4. Webpack自定义Loader和Plugin方法

    手写Loader Loader 本质上是导出函数的 JavaScript 模块,而该模块导出的函数被称为 Normal Loader,在开发 Loader时,我们可以在导出的函数上添加一个 pitch ...

  5. webpack:自定义loader

    以下是一个自定义loader replace-loader,实现一个类似模板引擎变量替换的简单功能 文件目录 . ├── dist │ └── index.js # 打包结果 ├── loaders ...

  6. 24.重学webpack——loader的原理及常用loader的实现(高频面试题)

    [重学webpack系列--webpack5.0] 1-15节主要讲webpack的使用,当然,建议结合<webpack学完这些就够了>一起学习. 从本节开始,专攻webpack原理,只有 ...

  7. 深度解读Webpack中的loader原理

    一.前言 webpack 是一个现代 JavaScript 应用的静态模块打包器.那么 webpack 是怎样实现不同种类资源模块加载的呢? 没错就是通过 loader.loader 用于对模块的源代 ...

  8. webpack源码分析之三:loader

    前言 在webpack特性里面,它可以支持将非javaScript文件打包,但前面写到webpack的模块化打包只能应用于含有特定规范的JavaScript文件.本次介绍的loader则是用来解决这类 ...

  9. Unity puerts 自定义Loader和调试和ab包的注意点

    输出ab包 他会把你创建的ab包都打包 也就是在这里的创建的都打包 string assetBundleDirectory = Path.Combine(Application.streamingAs ...

最新文章

  1. 与孩子一起学编程 python_【和孩子一起学编程】 python笔记--第五天
  2. python语言入门电子版-python从入门到精通pdf
  3. 中国九章量子计算机诞生!比最快的超算快一百万亿倍
  4. 微信小程序图片轮转播放
  5. python和sql_Python和SQL 2017的强大功能
  6. 穷人变富的过程中,最大的阻碍是什么?
  7. 存储过程和存储函数和触发器示例
  8. MongoDB 的设计模式策略
  9. java并发编程实战读书笔记4--生产者消费者模式和队列
  10. L2TP-***通用原理取证及在华为防火墙上的实施
  11. NTC热敏电阻温度计算方法,Steinhart-Hart方程和B值法
  12. 基于产生式系统的野人渡河问题求解
  13. 目标客户画像_4 种类型 + 10 大步骤,详解用户画像
  14. 女研究生做“思维导图”与男友吵架!网友:吵架届的“内卷之王”....
  15. C#开发工控上位机编程 csdn_中吉午餐自动售货机加热自动午餐盒智能便利店【盒饭售货机】_智能云仓储库存wms管理分配货_电子标签价签拣货系统_工控erp上位机软件开发设计...
  16. 格林尼治时间转换为本地时间
  17. 前端Jquery使用pagination.js插件进行分页
  18. 为什么网上都说 AirPods 3 音质不如AirPods Pro?
  19. 随便拍几张照片赚了3K,近期的风口视频项目
  20. 支持向量机检测DGA

热门文章

  1. java孙膑和庞涓问题_庞涓VS孙膑——一个很难的数学问题(智力140以下勿进)
  2. 在Mac上使用招商银行网银
  3. 2022-04-16老张修路360笔试-prim构建最小生成树
  4. Excel VBA 利用FileSystemObject处理文件
  5. 计算机科学与技术中模电,模拟电子技术基础
  6. 使用Python获取春节档电影影评,制作可视化词云图
  7. 【2016 泉市教科】保险箱
  8. 云和恩墨大讲堂 x 长江鲲鹏 x openGauss Meetup(武汉站)圆满落幕
  9. 【练习篇】SQLZOO(中文版)习题答案_SELECT from world
  10. Linear Algebra