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 相关文章推荐
对javascript的一点点认识总结《javascript高级程序设计》读书笔记
Nov 30 Javascript
getElementByIdx_x js自定义getElementById函数
Jan 24 Javascript
javascript匿名函数实例分析
Nov 18 Javascript
jquery使用slideDown实现模块缓慢拉出效果的方法
Mar 27 Javascript
Javascript实现快速排序(Quicksort)的算法详解
Sep 06 Javascript
jQuery图片左右滚动代码 有左右按钮实例
Jun 20 Javascript
jQuery的Each比JS原生for循环性能慢很多的原因
Jul 05 Javascript
jQuery中Nicescroll滚动条插件的用法
Nov 10 Javascript
实例分析浏览器中“JavaScript解析器”的工作原理
Dec 12 Javascript
Js实现中国公民身份证号码有效性验证实例代码
May 03 Javascript
JS获取日期的方法实例【昨天,今天,明天,前n天,后n天的日期】
Sep 28 Javascript
详解django模板与vue.js冲突问题
Jul 07 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
php文本转图片自动换行的方法
2013/03/13 PHP
php从给定url获取文件扩展名的方法
2015/03/14 PHP
thinkPHP3.2.2框架行为扩展及demo示例
2018/06/19 PHP
JS提交并解析后台返回的XML的代码
2008/11/03 Javascript
node.js中的events.EventEmitter.listenerCount方法使用说明
2014/12/08 Javascript
针对初学者的jQuery入门指南
2015/08/15 Javascript
js控制TR的显示隐藏
2016/03/04 Javascript
js转html实体的方法
2016/09/27 Javascript
JavaScript 深层克隆对象详解及实例
2016/11/03 Javascript
JavaScript实现网页头部进度条刷新
2017/04/16 Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
2018/08/22 Javascript
jQuery实现手风琴效果(蒙版)
2020/01/11 jQuery
Centos Python2 升级到Python3的简单实现
2016/06/21 Python
Python 编码Basic Auth使用方法简单实例
2017/05/25 Python
python读取二进制mnist实例详解
2017/05/31 Python
Python中list查询及所需时间计算操作示例
2018/06/21 Python
Python解析json代码实例解析
2019/11/25 Python
pytorch .detach() .detach_() 和 .data用于切断反向传播的实现
2019/12/27 Python
Matplotlib scatter绘制散点图的方法实现
2020/01/02 Python
Jupyter notebook 启动闪退问题的解决
2020/04/13 Python
Pytorch转tflite方式
2020/05/25 Python
Python基于locals返回作用域字典
2020/10/17 Python
python Autopep8实现按PEP8风格自动排版Python代码
2021/03/02 Python
CSS3制作圆角图片和椭圆形图片
2016/07/08 HTML / CSS
HTML5中视频音频的使用详解
2017/07/07 HTML / CSS
设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
2014/12/30 面试题
银行实习的自我鉴定
2013/12/10 职场文书
人事专员的职责
2014/02/26 职场文书
读书之星事迹材料
2014/05/12 职场文书
公司证明怎么写
2014/09/22 职场文书
师德师风个人整改措施
2014/10/27 职场文书
工程资料员岗位职责
2015/04/13 职场文书
学校通报表扬范文
2015/05/04 职场文书
关于使用Redisson订阅数问题
2022/01/18 Redis
win10搭建配置ftp服务器的方法
2022/08/05 Servers
Tomcat安装使用及部署Web项目的3种方法汇总
2022/08/14 Servers