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 相关文章推荐
Prototype Function对象 学习
Jul 12 Javascript
JQuery live函数
Dec 24 Javascript
原生JS和JQuery动态添加、删除表格行的方法
May 28 Javascript
BootStrap下jQuery自动完成的样式调整
May 30 Javascript
谈谈JavaScript中的几种借用方法
Aug 09 Javascript
javascript ASCII和Hex互转的实现方法
Dec 27 Javascript
JS实现运动缓冲效果的封装函数示例
Feb 18 Javascript
Vue filter格式化时间戳时间成标准日期格式的方法
Sep 16 Javascript
vue-property-decorator用法详解
Dec 12 Javascript
vue实现导航菜单和编辑文本的示例代码
Jul 04 Javascript
详谈vue中router-link和传统a链接的区别
Jul 22 Javascript
在vs code 中如何创建一个自己的 Vue 模板代码
Nov 10 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
thinkphp3.x中cookie方法的用法分析
2016/05/19 PHP
PHP+MariaDB数据库操作基本技巧备忘总结
2018/05/21 PHP
JS中引用百度地图并将百度地图的logo和信息去掉
2013/09/29 Javascript
javascript中处理时间戳为日期格式的方法
2014/01/02 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
javascript实现淡蓝色的鼠标拖动选择框实例
2015/05/09 Javascript
js中setTimeout()与clearTimeout()用法实例浅析
2015/05/12 Javascript
jquery可定制的在线UEditor编辑器
2015/11/17 Javascript
Ionic快速安装教程
2016/06/03 Javascript
Vue.js每天必学之组件与组件间的通信
2016/09/08 Javascript
Radio 单选JS动态添加的选项onchange事件无效的解决方法
2016/12/12 Javascript
教你一步步用jQyery实现轮播器
2016/12/18 Javascript
ES6新特性之模块Module用法详解
2017/04/01 Javascript
ReactNative之键盘Keyboard的弹出与消失示例
2017/07/11 Javascript
微信小程序实现自定义modal弹窗封装的方法
2018/06/15 Javascript
webpack3里使用uglifyjs压缩js时打包报错的解决
2018/12/13 Javascript
react-router4按需加载(踩坑填坑)
2019/01/06 Javascript
JS实现可用滑块滑动的缓动图代码
2019/09/01 Javascript
详解用js代码触发dom事件的实现方案
2020/06/10 Javascript
JavaScript实现刮刮乐效果
2020/11/01 Javascript
[03:09]显微镜下的DOTA2第一期——带你走进华丽的DOTA2世界
2014/06/20 DOTA
Python中的filter()函数的用法
2015/04/27 Python
python函数中return后的语句一定不会执行吗?
2017/07/06 Python
python实现抖音视频批量下载
2018/06/20 Python
对numpy.append()里的axis的用法详解
2018/06/28 Python
python机器学习之KNN分类算法
2018/08/29 Python
对Python3中bytes和HexStr之间的转换详解
2018/12/04 Python
Python3.7+tkinter实现查询界面功能
2019/12/24 Python
Python的历史与优缺点整理
2020/05/26 Python
澳大利亚儿童鞋在线:The Trybe
2019/07/16 全球购物
Mountain Hardwear官网:攀岩服装和户外装备
2019/09/26 全球购物
2014年元旦促销活动方案
2014/02/22 职场文书
我的大学四年规划书范文2014
2014/09/26 职场文书
酒店收银员岗位职责
2015/04/07 职场文书
被委托人身份证明
2015/08/07 职场文书
SpringCloud Alibaba 基本开发框架搭建过程
2021/06/13 Java/Android