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 相关文章推荐
jQuery dialog 异步调用ashx,webservice数据的代码
Aug 03 Javascript
javascript返回顶部效果(自写代码)
Jan 06 Javascript
jQuery+.net实现浏览更多内容(改编php版本)
Mar 28 Javascript
json对象转为字符串,当做参数传递时加密解密的实现方法
Jun 29 Javascript
js实现常用排序算法
Aug 09 Javascript
表单input项使用label同时引用Bootstrap库导致input点击效果区增大问题
Oct 11 Javascript
Bootstrap CSS组件之面包屑导航(breadcrumb)
Dec 17 Javascript
jquery插件ContextMenu设置右键菜单
Mar 13 Javascript
jQuery实现简单漂亮的Nav导航菜单效果
Mar 29 jQuery
ReactNative页面跳转Navigator实现的示例代码
Aug 02 Javascript
js定义类的方法示例【ES5与ES6】
Jul 30 Javascript
详谈Vue.js框架下main.js,App.vue,page/index.vue之间的区别
Aug 12 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
COM in PHP (winows only)
2006/10/09 PHP
字母顺序颠倒而单词顺序不变的php代码
2010/08/08 PHP
php中socket通信机制实例详解
2015/01/03 PHP
实现php删除链表中重复的结点
2018/09/27 PHP
PHP中如何使用Redis接管文件存储Session详解
2018/11/28 PHP
Jquery阻止事件冒泡 event.stopPropagation
2011/12/11 Javascript
js的hasownproperty使用示例
2014/03/02 Javascript
js 采用delete实现继承示例代码
2014/05/20 Javascript
AngularJS入门教程(零):引导程序
2014/12/06 Javascript
详细解读AngularJS中的表单验证编程
2015/06/19 Javascript
jQuery实现点击小图片淡入淡出显示大图片特效
2015/09/09 Javascript
深入分析jQuery的ready函数是如何工作的(工作原理)
2015/12/17 Javascript
Angular2 (RC5) 路由与导航详解
2016/09/21 Javascript
js实现水平滚动菜单导航
2017/07/21 Javascript
详解http访问解析流程原理
2017/10/18 Javascript
AngularJS使用ui-route实现多层嵌套路由的示例
2018/01/10 Javascript
详解vue2.0 不同屏幕适配及px与rem转换问题
2018/02/23 Javascript
JavaScript使用享元模式实现文件上传优化操作示例
2018/08/07 Javascript
对angularJs中ng-style动态改变样式的实例讲解
2018/09/30 Javascript
js中call()和apply()改变指针问题的讲解
2019/01/17 Javascript
Vue实现数据请求拦截
2019/10/23 Javascript
JS实现小米轮播图
2020/09/21 Javascript
[05:49]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS 选手采访
2021/03/11 DOTA
在GitHub Pages上使用Pelican搭建博客的教程
2015/04/25 Python
用Python实现一个简单的能够上传下载的HTTP服务器
2015/05/05 Python
python实现比较文件内容异同
2018/06/22 Python
Python OpenCV实现视频分帧
2019/06/01 Python
PyCharm2019 安装和配置教程详解附激活码
2020/07/31 Python
CSS3 分类菜单效果
2019/05/27 HTML / CSS
WoolOvers澳洲官方网站:英国针织服装公司
2018/05/13 全球购物
为什么需要版本控制?
2013/08/08 面试题
担保书格式
2015/01/20 职场文书
员工工作表扬信
2015/05/05 职场文书
创业计划书之酒吧
2019/12/02 职场文书
MySQL 覆盖索引的优点
2021/05/19 MySQL
Golang 链表的学习和使用
2022/04/19 Golang