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变量作用域使用中常见错误总结
Mar 26 Javascript
js生成动态表格并为每个单元格添加单击事件的方法
Apr 14 Javascript
Js可拖拽放大的层拖动特效实现方法
Feb 25 Javascript
jQuery制作可自定义大小的拼图游戏
Mar 30 Javascript
Yii2使用Bootbox插件实现自定义弹窗
Apr 02 Javascript
js实现简单的左右两边固定广告效果实例
Apr 10 Javascript
JavaScript Split()方法
Dec 18 Javascript
原生js获取元素样式的简单方法
Aug 06 Javascript
Bootstrap风格的zTree右键菜单
Feb 17 Javascript
angularJs自定义过滤器实现手机号信息隐藏的方法
Oct 08 Javascript
实例分析编写vue组件方法
Feb 12 Javascript
Vue实现商品飞入购物车效果(电商项目)
Nov 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
PHP时间戳使用实例代码
2008/06/07 PHP
phpQuery占用内存过多的处理方法
2013/11/13 PHP
JavaScript对象创建及继承原理实例解剖
2013/02/28 Javascript
javascript日期验证之输入日期大于等于当前日期
2015/12/13 Javascript
js实现横向拖拽导航条功能
2017/02/17 Javascript
微信小程序 动画的简单实例
2017/10/12 Javascript
vue19 组建 Vue.extend component、组件模版、动态组件 的实例代码
2019/04/04 Javascript
NodeJs 模仿SIP话机注册的方法
2019/06/21 NodeJs
微信小程序实现购物车代码实例详解
2019/08/29 Javascript
JS浏览器BOM常见操作实例详解
2020/04/27 Javascript
js实现搜索提示框效果
2020/09/05 Javascript
详解vue修改elementUI的分页组件视图没更新问题
2020/11/13 Javascript
Python创建文件和追加文件内容实例
2014/10/21 Python
如何解决django配置settings时遇到Could not import settings 'conf.local'
2014/11/18 Python
Python实现向QQ群成员自动发邮件的方法
2014/11/19 Python
Python编写百度贴吧的简单爬虫
2015/04/02 Python
python开发之thread实现布朗运动的方法
2015/11/11 Python
python中requests库session对象的妙用详解
2017/10/30 Python
django的settings中设置中文支持的实现
2019/04/28 Python
django中使用事务及接入支付宝支付功能
2019/09/15 Python
python except异常处理之后不退出,解决异常继续执行的实现
2020/04/25 Python
Python grequests模块使用场景及代码实例
2020/08/10 Python
简述python Scrapy框架
2020/08/17 Python
意大利拉斐尔时尚购物网:Raffaello Network(支持中文)
2018/11/09 全球购物
个人现实表现材料
2014/02/04 职场文书
《这儿真好》教学反思
2014/02/22 职场文书
小学庆六一活动总结
2014/08/28 职场文书
2014学习优秀共产党员先进事迹思想汇报
2014/09/14 职场文书
2014年后勤管理工作总结
2014/12/01 职场文书
工作经验交流材料
2014/12/30 职场文书
社区六一儿童节活动总结
2015/02/11 职场文书
手机销售员岗位职责
2015/04/11 职场文书
2015年志愿者服务工作总结
2015/04/20 职场文书
2015毕业设计工作总结
2015/07/24 职场文书
sentinel支持的redis高可用集群配置详解
2022/04/01 Redis
MyBatis核心源码深度剖析SQL语句执行过程
2022/05/20 Java/Android