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可访问其它域名的cookie的方法
Sep 18 Javascript
javascript while语句和do while语句的区别分析
Dec 08 Javascript
Javascript类库的顶层对象名用户体验分析
Oct 24 Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
Jan 15 Javascript
js点击出现悬浮窗效果不使用JQuery插件
Jan 20 Javascript
让html页面不缓存js的实现方法
Oct 31 Javascript
JSON取值前判断
Dec 23 Javascript
在 Node.js 中使用 async 函数的方法
Nov 17 Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
Aug 10 Javascript
微信提示 在浏览器打开 效果实现过程解析
Sep 10 Javascript
ES6实现图片切换特效代码
Jan 14 Javascript
小程序自定义导航栏兼容适配所有机型(附完整案例)
Apr 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
优化使用mysql存储session的php代码
2008/01/10 PHP
PHP中的命名空间详细介绍
2015/07/02 PHP
PHP实现的简单网络硬盘
2015/07/29 PHP
PHP生成和获取XML格式数据的方法
2016/03/04 PHP
Symfony2创建基于域名的路由相关示例
2016/11/14 PHP
javascript Discuz代码中的msn聊天小功能
2008/05/25 Javascript
javascript的函数、创建对象、封装、属性和方法、继承
2011/03/10 Javascript
基于json的jquery地区联动效果代码
2011/07/06 Javascript
js jquery验证银行卡号信息正则学习
2013/01/21 Javascript
用js实现小球的自由移动代码
2013/04/22 Javascript
使用javascript获取页面名称
2014/12/23 Javascript
js实现遮罩层弹出框的方法
2015/01/15 Javascript
NodeJs基本语法和类型
2015/02/13 NodeJs
jQuery实现仿Google首页拖动效果的方法
2015/05/04 Javascript
如何实现移动端浏览器不显示 pc 端的广告
2015/10/15 Javascript
简单三步实现报表页面集成天气
2016/12/15 Javascript
解决bootstrap下拉菜单点击立即隐藏bug的方法
2017/06/13 Javascript
vue.js-div滚动条隐藏但有滚动效果的实现方法
2018/03/03 Javascript
详解vue-cli项目中怎么使用mock数据
2018/05/29 Javascript
javascript和php使用ajax通信传递JSON的实例
2018/08/21 Javascript
jQuery超简单遮罩层实现方法示例
2018/09/06 jQuery
Vue 实现可视化拖拽页面编辑器
2021/02/01 Vue.js
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
Python import自定义模块方法
2015/02/12 Python
低版本中Python除法运算小技巧
2015/04/05 Python
Python中利用aiohttp制作异步爬虫及简单应用
2018/11/29 Python
Python这样操作能存储100多万行的xlsx文件
2019/04/16 Python
PyCharm 配置远程python解释器和在本地修改服务器代码
2019/07/23 Python
python rsa实现数据加密和解密、签名加密和验签功能
2019/09/18 Python
python正则表达式的懒惰匹配和贪婪匹配说明
2020/07/13 Python
python raise的基本使用
2020/09/10 Python
德国奢侈品网上商城:Mytheresa
2016/08/24 全球购物
荷兰的时尚市场:To Be Dressed
2019/05/06 全球购物
施华洛世奇波兰官网:SWAROVSKI波兰
2019/06/18 全球购物
mysql有关权限的表都有哪几个
2015/04/22 面试题
2015年档案管理工作总结
2015/04/08 职场文书