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 相关文章推荐
经典的解除许多网站无法复制文字的绝招
Dec 31 Javascript
JQuery获取浏览器窗口内容部分高度的代码
Feb 24 Javascript
json的使用小结
Jun 08 Javascript
理解AngularJs篇:30分钟快速掌握AngularJs
Dec 23 Javascript
详解JS中的立即执行函数
Feb 24 Javascript
vue.js树形组件之删除双击增加分支实例代码
Feb 28 Javascript
JS实现的Unicode编码转换操作示例
Apr 28 Javascript
es7学习教程之fetch解决异步嵌套问题的方法示例
Jul 21 Javascript
vue中appear的用法
Aug 17 Javascript
js验证身份证号码记录的方法
Apr 26 Javascript
如何在微信小程序中存setStorage
Dec 13 Javascript
Vue.js中Line第三方登录api的实现代码
Jun 29 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读取MySQL数据代码
2008/06/05 PHP
PHP获取网站域名和地址的代码
2008/08/17 PHP
php 中文字符入库或显示乱码问题的解决方法
2010/04/12 PHP
PHP小技巧之JS和CSS优化工具Minify的使用方法
2014/05/19 PHP
fckeditor上传文件按日期存放及重命名方法
2015/05/22 PHP
总结PHP中初始化空数组的最佳方法
2019/02/13 PHP
IE7提供XMLHttpRequest对象为兼容
2007/03/08 Javascript
jQuery的实现原理的模拟代码 -5 Ajax
2010/08/07 Javascript
JS 实现点击a标签的时候让其背景更换
2013/10/15 Javascript
js特殊字符过滤的示例代码
2014/03/05 Javascript
jquery获取复选框被选中的值
2014/03/22 Javascript
实现无刷新联动例子汇总
2015/05/20 Javascript
Javascript数组中push方法用法分析
2016/10/31 Javascript
jQuery实现简单弹窗遮罩效果
2017/02/27 Javascript
详解vue-resource promise兼容性问题
2017/06/20 Javascript
用最少的JS代码写出贪吃蛇游戏
2018/01/12 Javascript
详解vue-cli官方脚手架配置
2018/07/20 Javascript
解决vue2.0 element-ui中el-upload的before-upload方法返回false时submit()不生效问题
2018/08/24 Javascript
NodeJS 文件夹拷贝以及删除功能
2019/09/03 NodeJs
python中getaddrinfo()基本用法实例分析
2015/06/28 Python
Python的Django框架中forms表单类的使用方法详解
2016/06/21 Python
python出现"IndentationError: unexpected indent"错误解决办法
2017/10/15 Python
python创建文件备份的脚本
2018/09/11 Python
对python中字典keys,values,items的使用详解
2019/02/03 Python
Python使用selenium + headless chrome获取网页内容的方法示例
2019/10/16 Python
浅析Python+OpenCV使用摄像头追踪人脸面部血液变化实现脉搏评估
2019/10/17 Python
Python 实现数组相减示例
2019/12/27 Python
python中的itertools的使用详解
2020/01/13 Python
python通过函数名调用函数的几种场景
2020/09/23 Python
优秀毕业生自我鉴定
2014/01/19 职场文书
《最佳路径》教学反思
2014/04/13 职场文书
个人自荐书怎么写
2015/03/26 职场文书
旷工辞退通知书
2015/04/17 职场文书
小学二年级语文教学反思
2016/03/03 职场文书
nginx前后端同域名配置的方法实现
2021/03/31 Servers
MySQL8.0的WITH查询详情
2021/08/30 MySQL