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 相关文章推荐
extjs form textfield的隐藏方法
Dec 29 Javascript
Extjs学习笔记之一 初识Extjs之MessageBox
Jan 07 Javascript
jQuery中has()方法用法实例
Jan 06 Javascript
angularJS结合canvas画图例子
Feb 09 Javascript
正则表达式,替换所有HTML标签的简单实例
Nov 28 Javascript
Angular.JS实现无限级的联动菜单(使用demo)
Feb 08 Javascript
基于JavaScript实现微信抢红包功能
Jul 20 Javascript
微信小程序实现红包雨功能
Jul 11 Javascript
微信小程序解除10个请求并发限制
Dec 18 Javascript
使用vuex较为优雅的实现一个购物车功能的示例代码
Dec 09 Javascript
JS数据类型判断的几种常用方法
Jul 07 Javascript
使用vant的地域控件追加全部选项
Nov 03 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
PHPShop存在多个安全漏洞
2006/10/09 PHP
PHP学习笔记 (1) 环境配置与代码调试
2011/06/19 PHP
PHP网络操作函数汇总
2015/05/18 PHP
Laravel推荐使用的十个辅助函数
2019/05/10 PHP
Javascript模块化编程(一)模块的写法最佳实践
2013/01/17 Javascript
基于js与flash实现的网站flv视频播放插件代码
2014/10/14 Javascript
javascript实现修改微信分享的标题内容等
2014/12/11 Javascript
javascript定义类和类的实现实例详解
2015/12/01 Javascript
js中实现字符串和数组的相互转化详解
2016/01/24 Javascript
JS数组去掉重复数据只保留一条的实现代码
2016/08/11 Javascript
在javascript中使用com组件的简单实现方法
2016/08/17 Javascript
使用JS实现图片展示瀑布流效果(简单实例)
2016/09/06 Javascript
javascript中的面向对象
2017/03/30 Javascript
ES5 ES6中Array对象去除重复项的方法总结
2017/04/27 Javascript
详解操作虚拟dom模拟react视图渲染
2018/07/25 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
判断“命令按钮”是否被鼠标单击详解
2019/07/31 Javascript
JS获取当前时间戳方法解析
2020/08/29 Javascript
py2exe 编译ico图标的代码
2013/03/08 Python
qpython3 读取安卓lastpass Cookies
2016/06/19 Python
Python中利用LSTM模型进行时间序列预测分析的实现
2019/07/26 Python
python实现大学人员管理系统
2019/10/25 Python
pytorch: Parameter 的数据结构实例
2019/12/31 Python
python生成并处理uuid的实现方式
2020/03/03 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
CSS3改变浏览器滚动条样式
2019/01/04 HTML / CSS
西班牙汉普顿小姐:购买帆布鞋和太阳镜
2016/10/23 全球购物
美国名牌太阳镜折扣网站:Eyedictive
2017/05/15 全球购物
Capitol Lighting的1800lighting.com:住宅和商业照明
2019/04/10 全球购物
会计工作心得体会
2014/01/13 职场文书
小学英语教师先进事迹
2014/05/28 职场文书
2014法院干警廉洁警示教育思想汇报
2014/09/13 职场文书
证婚人婚礼致辞
2015/07/28 职场文书
保护环境建议书作文500字
2015/09/14 职场文书
教师实习自我鉴定总结
2019/08/20 职场文书