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 相关文章推荐
JS 参数传递的实际应用代码分析
Sep 13 Javascript
jquery 页面全选框实践代码
Apr 02 Javascript
使用UglifyJS合并/压缩JavaScript的方法
Mar 07 Javascript
原生js实现shift/ctrl/alt按键的获取
Apr 08 Javascript
JavaScript实现网页对象拖放功能的方法
Apr 15 Javascript
Vue.js报错Failed to resolve filter问题的解决方法
May 25 Javascript
Javascript 实现简单计算器实例代码
Oct 23 Javascript
Vue如何引入远程JS文件
Apr 20 Javascript
jquery submit()不能提交表单的解决方法
Apr 24 jQuery
JavaScript实现移动端轮播效果
Jun 06 Javascript
vue中利用simplemde实现markdown编辑器(增加图片上传功能)
Apr 29 Javascript
vue单元格多列合并的实现
Nov 26 Vue.js
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单例模式详细介绍
2015/07/01 PHP
thinkphp中AJAX返回ajaxReturn()方法分析
2016/12/06 PHP
jquery 插件之仿“卓越亚马逊”首页弹出菜单效果
2008/12/25 Javascript
js 编写规范
2010/03/03 Javascript
IE8 中使用加速器(Activities)
2010/05/14 Javascript
JavaScript下利用fso判断文件是否存在的代码
2010/12/11 Javascript
利用jquery的获取JS文件中的字符串内容
2012/02/14 Javascript
js,jquery滚动/跳转页面到指定位置的实现思路
2014/06/03 Javascript
JavaScript中的console.assert()函数介绍
2014/12/29 Javascript
nodejs根据ip数组在百度地图中进行定位
2017/03/06 NodeJs
iview中Select 选择器多选校验方法
2018/03/15 Javascript
js+canvas实现滑动拼图验证码功能
2018/03/26 Javascript
vue3.0 搭建项目总结(详细步骤)
2019/05/20 Javascript
layui 阻止图片上传的实例(before方法)
2019/09/26 Javascript
[59:35]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#1COL VS Alliance第二局
2016/03/04 DOTA
[00:36]TI7不朽珍藏III——斯温不朽展示
2017/07/15 DOTA
[49:58]完美世界DOTA2联赛PWL S3 Magma vs DLG 第一场 12.18
2020/12/19 DOTA
Python字符串的encode与decode研究心得乱码问题解决方法
2009/03/23 Python
使用70行Python代码实现一个递归下降解析器的教程
2015/04/17 Python
Python切片知识解析
2016/03/06 Python
CentOS7.3编译安装Python3.6.2的方法
2018/01/22 Python
python使用pandas处理大数据节省内存技巧(推荐)
2019/05/05 Python
python飞机大战pygame游戏背景设计详解
2019/12/17 Python
pandas DataFrame 数据选取,修改,切片的实现
2020/04/24 Python
keras得到每层的系数方式
2020/06/15 Python
五分钟学会HTML5的WebSocket协议
2019/11/22 HTML / CSS
预备党员思想汇报范文
2013/12/29 职场文书
遥感技术与仪器求职信
2014/02/22 职场文书
2014年班级工作总结范文
2014/12/23 职场文书
旗帜观后感
2015/06/08 职场文书
关于运动会的广播稿
2015/08/19 职场文书
2015年店长个人工作总结
2015/10/23 职场文书
2016大一新生入学教育心得体会
2016/01/23 职场文书
六年级数学教学反思
2016/02/16 职场文书
Android Flutter实现3D动画效果示例详解
2022/04/07 Java/Android
Redis特殊数据类型bitmap位图
2022/06/01 Redis