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 相关文章推荐
DB.ASP 用Javascript写ASP很灵活很好用很easy
Jul 31 Javascript
document.getElementBy("id")与$("#id")有什么区别
Sep 22 Javascript
js几秒以后倒计时跳转示例
Dec 26 Javascript
js跳转页面方法总结
Jan 29 Javascript
Javascript实现字数统计
Jul 03 Javascript
简单理解JavaScript中的封装与继承特性
Mar 19 Javascript
js实现漫天星星效果
Jan 19 Javascript
详解AngularJS通过ocLazyLoad实现动态(懒)加载模块和依赖
Mar 01 Javascript
网页中的图片查看器viewjs使用方法
Jul 11 Javascript
Angular如何在应用初始化时运行代码详解
Jun 11 Javascript
详解小程序input框失焦事件在提交事件前的处理
May 05 Javascript
Openlayers绘制地图标注
Sep 28 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根据指定位置和长度获得子字符串的方法
2015/03/17 PHP
JavaScript中令你抓狂的魔术变量
2006/11/30 Javascript
Js的MessageBox
2006/12/03 Javascript
推荐一些非常不错的javascript学习资源站点
2007/08/29 Javascript
JS 事件绑定函数代码
2010/04/28 Javascript
js判断浏览器类型的方法
2013/08/07 Javascript
js 获取radio按钮值的实例
2013/08/17 Javascript
javascript操作ul中li的方法
2015/05/14 Javascript
javascript插件开发的一些感想和心得
2016/02/28 Javascript
Angular.js中$apply()和$digest()的深入理解
2016/10/13 Javascript
JavaScript实现各种排序的代码详解
2017/08/28 Javascript
基于原生js运动方式关键点的总结(推荐)
2017/10/01 Javascript
第一个Vue插件从封装到发布
2017/11/22 Javascript
javascript将json格式数组下载为excel表格的方法
2017/12/22 Javascript
浅谈Angular HttpClient简单入门
2018/05/04 Javascript
通过函数作用域和块级作用域看javascript的作用域链
2018/08/05 Javascript
webpack常用构建优化策略小结
2019/11/21 Javascript
python读取浮点数和读取文本文件示例
2014/05/06 Python
Python数据类型学习笔记
2016/01/13 Python
Sanic框架路由用法实例分析
2018/07/16 Python
分享Python切分字符串的一个不错方法
2018/12/14 Python
解决Keras 与 Tensorflow 版本之间的兼容性问题
2020/02/07 Python
python微信公众号开发简单流程实现
2020/03/09 Python
python新手学习使用库
2020/06/11 Python
使用CSS3的::selection改变选中文本颜色的方法
2015/09/29 HTML / CSS
Weekendesk意大利:探索多种引人入胜的周末主题
2016/10/14 全球购物
eDreams葡萄牙:全球最大的在线旅行社之一
2019/04/15 全球购物
LN-CC日本:高端男装和女装的奢侈时尚目的地
2019/09/01 全球购物
史上最全面的Java面试题汇总!
2015/02/03 面试题
班主任对学生的评语
2014/04/26 职场文书
乡镇保密工作责任书
2014/07/28 职场文书
督导岗位职责范本
2015/04/10 职场文书
银行岗位培训心得体会
2016/01/09 职场文书
2019新学期家长会工作计划
2019/08/21 职场文书
Python中的tkinter库简单案例详解
2022/01/22 Python
Mysql如何实现不存在则插入,存在则更新
2022/03/25 MySQL