webpack源码之loader机制详解


Posted in Javascript onApril 06, 2018

loader概念

loader是用来加载处理各种形式的资源,本质上是一个函数, 接受文件作为参数,返回转化后的结构。

loader 用于对模块的源代码进行转换。loader 可以使你在 import 或"加载"模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!

loader和plugin区别

之前一篇文章中介绍了plugin机制,和今天研究的对象loader,他们两者在一起极大的拓展了webpack的功能。它们的区别就是loader是用来对模块的源代码进行转换,而插件目的在于解决 loader 无法实现的其他事。为什么这么多说呢?因为plugin可以在任何阶段调用,能够跨Loader进一步加工Loader的输出,在构建运行期间,触发事件,执行预先注册的回调,使用compilation对象做一些更底层的事情。

loader用法

配置

module: {
  rules: [
   {
    test: /\.css$/,
    use: [
     { loader: 'style-loader' },
     {
      loader: 'css-loader'
     }
    ]
   }
  ]
 }

内联

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

CLI

webpack --module-bind 'css=style-loader!css-loader'

说明 上面三种使用方法作用都是将一组链式的 loader, 按照从右往左的顺序执行,loader 链中的第一个 loader 返回值给下一个 loader。先使用css-loader解析 @import 和 url()路径中指定的css内容,然后用style-loader 会把原来的 CSS 代码插入页面中的一个 style 标签中。

loader实现

//将css插入到head标签内部
module.exports = function (source) {
  let script = (`
   let style = document.createElement("style");
   style.innerText = ${JSON.stringify(source)};
   document.head.appendChild(style);
  `);
  return script;
}
//使用方式1
resolveLoader: {
  modules: [path.resolve('node_modules'), path.resolve(__dirname, 'src', 'loaders')]
},
{
  test: /\.css$/,
  use: ['style-loader']
},
//使用方式2
//将自己写的loaders发布到npm仓库,然后添加到依赖,按照方式1中的配置方式使用即可

说明 上面是一个简单的loader实现,同步的方式执行,相当于实现了style-loader的功能。

loader原理

function iteratePitchingLoaders(options, loaderContext, callback) {
  var currentLoaderObject = loaderContext.loaders[loaderContext.loaderIndex];
  // load loader module
  loadLoader(currentLoaderObject, function(err) {
    var fn = currentLoaderObject.pitch;
    runSyncOrAsync(
      fn,
      loaderContext, [loaderContext.remainingRequest, loaderContext.previousRequest, currentLoaderObject.data = {}],
      function(err) {
        if(err) return callback(err);
        var args = Array.prototype.slice.call(arguments, 1);
        if(args.length > 0) {
          loaderContext.loaderIndex--;
          iterateNormalLoaders(options, loaderContext, args, callback);
        } else {
          iteratePitchingLoaders(options, loaderContext, callback);
        }
      }
    );
  });
}

说明 上面是webpack源码中loader执行关键步骤,递归的方式执行loader,执行机流程似于express中间件机制

参考源码

  1. webpack: "4.4.1"
  2. webpack-cli: "2.0.13"

参考文档
https://webpack.js.org/concepts/loaders/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery中index()的用法分析
Sep 05 Javascript
javascript解决IE6下hover问题的方法
Jul 28 Javascript
Bootstrap~多级导航(级联导航)的实现效果【附代码】
Mar 08 Javascript
js实现随机抽选效果、随机抽选红色球效果
Jan 13 Javascript
利用jQuery实现滑动开关按钮效果(附demo源码下载)
Feb 07 Javascript
jQuery使用eraser.js插件实现擦除、刮刮卡效果的方法【附eraser.js下载】
Apr 28 jQuery
js时间戳与日期格式之间相互转换
Dec 11 Javascript
vue实现导航栏效果(选中状态刷新不消失)
Dec 13 Javascript
vue给input file绑定函数获取当前上传的对象完美实现方法
Dec 15 Javascript
微信小程序-可移动菜单的实现过程详解
Jun 24 Javascript
vue el-tree 默认展开第一个节点的实现代码
May 15 Javascript
vue3.0 的 Composition API 的使用示例
Oct 26 Javascript
vue.js项目nginx部署教程
Apr 05 #Javascript
常用的 JS 排序算法 整理版
Apr 05 #Javascript
通过 JS 判断页面是否有滚动条的实现方法
Apr 05 #Javascript
mint-ui在vue中的使用示例
Apr 05 #Javascript
webpack热模块替换(HMR)/热更新的方法
Apr 05 #Javascript
详解Vue基于 Nuxt.js 实现服务端渲染(SSR)
Apr 05 #Javascript
express默认日志组件morgan的方法
Apr 05 #Javascript
You might like
DC宇宙的第一个英雄,堪称动漫史鼻祖,如今成为美国文化的象征
2020/04/09 欧美动漫
五款常用mysql slow log分析工具的比较分析
2011/05/22 PHP
php解决DOM乱码的方法示例代码
2016/11/20 PHP
PHP生成图片缩略图类示例
2017/01/12 PHP
windows 2008r2+php5.6.28环境搭建详细过程
2019/06/18 PHP
php 使用 __call实现重载功能示例
2019/11/18 PHP
初学js 新节点的创建 删除 的步骤
2011/07/04 Javascript
50款非常棒的 jQuery 插件分享
2012/03/29 Javascript
javascript学习笔记(三)BOM和DOM详解
2014/09/30 Javascript
Node.js连接MongoDB数据库产生的问题
2017/02/08 Javascript
元素全屏的设置与监听实例
2017/11/28 Javascript
js 取消页面可以选中文字的功能方法
2018/01/02 Javascript
基于Vue2x的图片预览插件的示例代码
2018/05/14 Javascript
webpack4简单入门实例
2018/09/06 Javascript
详解vue组件之间的通信
2020/08/30 Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
2020/11/03 Javascript
[03:59]DOTA2英雄梦之声_第07期_水晶室女
2014/06/23 DOTA
[43:58]DOTA2-DPC中国联赛定级赛 LBZS vs SAG BO3第一场 1月8日
2021/03/11 DOTA
Python调用C# Com dll组件实战教程
2017/10/12 Python
Python Scapy随心所欲研究TCP协议栈
2018/11/20 Python
numpy实现神经网络反向传播算法的步骤
2019/12/24 Python
Django多数据库配置及逆向生成model教程
2020/03/28 Python
容易被忽略的Python内置类型
2020/09/03 Python
关于python tushare Tkinter构建的简单股票可视化查询系统(Beta v0.13)
2020/10/19 Python
Python ellipsis 的用法详解
2020/11/20 Python
加拿大领先的牛仔零售商:Bluenotes
2018/01/22 全球购物
马来西亚演唱会订票网站:StubHub马来西亚
2018/10/18 全球购物
免税水晶:Duty Free Crystal
2019/05/13 全球购物
印尼在线旅游门户网站:NusaTrip
2019/11/01 全球购物
JDK安装目录下有哪些内容
2014/08/25 面试题
年终考核实施方案
2014/05/26 职场文书
理发店策划方案
2014/06/05 职场文书
个人安全生产责任书
2014/07/28 职场文书
个人年度总结报告
2015/03/09 职场文书
保研推荐信格式
2015/03/25 职场文书
教育教学工作反思
2016/02/24 职场文书