热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

webpack二刷之二、loader资源模块加载器

loader资源模块加载器webpack资源模块加载webpack内部(内部loader)默认只会处理javascript文件,也就是说它会把打包过程中所有遇到的
loader资源模块加载器

webpack 资源模块加载

webpack内部(内部loader)默认只会处理Javascript文件,也就是说它会把打包过程中所有遇到的文件当作Javascript文件去解析。

可以为其他类型的文件添加不同的加载器(loader)。

loader

loader是webpack实现整个前端模块化的核心,借助于loader就可以加载任何类型的资源。

安装loader,然后在配置文件中的module属性下配置rules数组。

rules 是针对其他资源模块的加载规则的配置。

每个规则对象,都需要设置两个属性:

  • test:一个正则表达式,用于匹配打包过程中遇到的文件路径
  • use:用于指定匹配到的文件需要使用的loader
    • 可以配置loader模块名称,也可以配置loader相对路径,原理同require函数
      • use: 'css-loader'使用npm上的loader模块
      • use: './xxx-loader'使用自定义的.js文件的相对路径
    • 如何配置了多个loader(数组),执行顺序是从后向前

一些插件介绍:

  1. css-loader
    1. 将css文件转换称一个js模块,具体实现是:
      1. 将css代码push到一个数组当中
    2. 但是整个过程中,并没有使用到这个数组
    3. 还需要一个style-loader去使用它
  2. style-loader
    1. 将css-loader转换后的结果,通过style标签的形式追加到页面上
  3. html-loader
    1. 使webpack识别.html的模块

webpack 导入资源模块

虽然可以通过loader将任何类型的资源作为入口去打包。

但webpack一般还是将Javascript作为打包入口。

打包入口可以说是项目的运行入口。

webpack建议:

  1. 编写代码过程中,根据代码的需要,动态导入资源
  2. 需要资源的不是应用,而是代码

目前而言,Javascript代码负责完成整个应用的业务功能。Javascript驱动前端应用的业务。

在实现业务的过程中,需要其他类型的资源(例如样式、图片)。

webpack建立Javascript和资源的依赖关系的目的:

  1. 逻辑合理,JS确实需要这些资源文件
  2. 确保上线资源不缺失,都是必要的

webpack 文件资源加载器

大部分loader都类似css-loader,都是将资源模块转换为JS代码的实现方式。

还有一部分(例如 图片 字体)不能通过JS的方式去表示的资源,需要用到文件资源加载器,例如file-loader

webpack默认将输出目录作为网站的根目录,所以资源的路径默认以dist为根目录。

通过配置publicPath,告诉webpack打包的文件在网站中的位置,默认为空''及网站根目录。

例如:publicPath: 'dist/',注意/不能省略。

publicPath即打包后文件中webpack使用的变量__webpack_require__.p

使用图片时,它拼接在图片路径前,即__webpack_require__.p + imgSrc,所以/不能省略。

总结

webpack 在打包时遇到图片等文件,根据配置匹配对应的文件加载器,先将文件拷贝到输出目录,然后将输出的文件的路径,作为返回值返回,从而可以通过import拿到访问这个文件的路径。

webpack URL 加载器

除了file-loader 这种通过拷贝文件的方式去处理文件资源以外,还有一种通过 Data URLs 表示文件的常见方式。

Data URLs

传统的URL一般要求服务器有一个对应的文件,然后通过请求这个地址得到服务器上的这个文件。

Data URLs 是特殊的URL协议,它可以直接表示一个文件的内容,即url中的文本已经包含了文件的内容。

所以使用Data URLs时就不会再发送HTTP请求。

data:[][;base64],

  • data: 协议
  • [][;base64], 媒体类型和编码
  • 文件内容

例如:data:text/html;charset=UTF-8,

html content

表示一个编码为UTF-8,内容为

html content

的html内容。

可以通过浏览器打开这个地址查看效果。

而如果是图片或字体这种无法直接通过文本去表示的二进制类型的文件,可以通过将文件的内容进行base64编码,然后以编码后的字符串去表示文件的内容。

例如:data:image/png;base64,iVBORw0KGg...

表示base64编码的png类型的文件。

通过Data URLs可以表示任意类型的文件。

url-loader

file-loader通过拷贝的方式打包文件,最终返回输出文件的路径。

url-loader将文件转换为Data URLs,最终返回一个完整的 Data URLs类型的url地址,不会输出独立的物理文件。

最佳实践


  • 小文件使用Data URLs,减少请求次数
  • 大文件单独提取存放(传统方式),提高加载速度(Data URLs表示大文件内容过大)

每个loader加载器都有options配置选项。

通过配置url-loaderlimit(字节上限)实现最佳实践。

  • 超出limit的文件单独提取存放(调用file-loader加载器)
  • 小于limit的文件转换为Data URLs嵌入代码

注意:如果url-loader配置了limit,大文件是使用file-loader加载器处理的,所以需要安装它依赖的file-loader

常用加载器分类


  • 编译转换类
    • 把加载到的模块,转换为Javascript代码
    • 例如 css-loader
  • 文件操作类
    • 把加载到的资源模块,拷贝到输出的目录
    • 同时导出文件的访问路径
    • 例如 file-loader
  • 代码检查类
    • 对代码加载的文件中的代码进行校验
    • 目的:统一代码风格,从而提高代码质量
    • 一般不会修改生产环境的代码
    • 例如 eslint-loader

webpack 处理 ES2015

webpack默认就能处理代码当中的 importexport,但这不表示webpack会自动编译ES6的代码。

因为模块打包需要,所以webpack对代码中的importexport作了相应的转换。

webpack并不能转换代码中其他的ES6特性。

如果需要webpack处理代码中其他ES6特性的转换,就需要为JS文件配置一个额外的编译类型的loader,例如常见的babel-loader

babel-loader依赖额外的babel的核心模块@babel/core

另外可以安装一个babel的插件集合(预设)@babel/preset-env

babel只是转换JS代码的一个平台,我们需要基于这个平台,通过不同的插件去转换代码中具体的特性。

所以需要配置babel要使用的插件。

  • webpack只是打包工具,不会处理代码中的ES6的新特性
  • 通过配置加载器实现编译转换代码

webpack 模块加载方式

除了代码中的import可以触发模块的加载,webpack还提供了其他几种方式:

  • 遵循 ES Modules 标准的import声明
  • 遵循 CommonJS 标准的require函数
    • 注:如果require一个 ESM 的模块,需要通过require().default 获取 ESM 模块的默认属性
  • 遵循 AMD 标准的define函数和require函数

建议:除非必要情况,否则不要再项目中混合使用这几种标准。

webpack除了以上3个方式,loader加载的非Javascript也会触发资源加载。(一些独立的加载器,在工作时也会处理所加载到的资源当中导入的模块)

例如

  • css-loader加载的css文件(样式代码中@import指令和url函数)
  • html代码的图片标签的src属性,a标签的href属性
    • 使用html-loader

html-loader默认只会处理html中的src属性,如果要实现其他标签的属性也能触发webpack打包,需要为加载器添加一些相应配置。

代码中所有引用到的资源(有引用资源可能性的地方)都会被webpack找到,然后根据配置交给对应的loader去处理,最后将处理的结果整体打包到输出目录。

webpack就是依据这样的特点,去实现整个项目的模块化。

webpack 核心工作原理

在项目中一般都会散落着各种各样的代码及资源文件(.js .html .css .png .json .scss…)。

webpack会根据配置找到其中的一个文件作为打包入口(entry),一般是一个Javascript文件。

然后它会顺着入口文件的代码,根据代码中出现的importrequire之类的语句,解析推断出这个资源所依赖的模块。

然后分别再解析每个模块对应的依赖。

最后形成了整个项目中,所有用到的文件之间的依赖关系的依赖树。

webpack会递归这个依赖树,找到每个节点对应的资源文件。

最后根据配置文件中的rules属性,找到模块对应的加载器去加载这个模块。

最后会将加载到的结果,放到打包文件bundle.js中,从而实现整个项目的打包。

Loader机制是webpack的核心。
如果没有Loader,webpack就没有办法实现各种资源文件的加载,而只是打包合并JS代码的工具。


webpack Loader的工作原理


开发一个loader

开发一个markdown文件加载器(markdown-loader),实现在代码中直接导入markdown文件。

原理:将md内容转换为html呈现到页面中。

起步


  1. 创建一个loader的js文件,编写内容

  2. 每个loader都需要导出一个函数,这个函数是loader对所加载到的资源的处理过程。

    1. 输入:就是资源所加载到的内容,参数source接收
    2. 输出:return处理后的结果
  3. 在webpack配置文件中配置rules,使用这个loader

// markdown-loader.js
module.exports = source => {console.log(source)return 'hello ~'
}// webpack.config.js
module.exports = source => {module: {rules: [{test: /.md$/,use: './markdown-loader', // 同require一样可以指定相对路径}]}
}

此时执行打包命令,会报错You may need an additional loader to handle the result of these loaders.

“你可能需要一个额外的loader去处理这个自定义加载器的结果”。

webpack加载资源的过程,类似于一个工作管道,可以在这个过程中依次使用多个loader。

Source => loader1 -> loader2 -> loaderx => Result

但是它要求最终这个管道工作过后的结果,必须是一段Javascript代码

而上面的loader返回的是hello ~,它不是Javascript代码,所以才会出现这个错误提示。

解决办法:

  1. 直接返回Javascript代码
    1. 例如 return 'exports default "hello ~"'
  2. 或者找一个合适的loader继续处理markdown-loader处理的结果

使用合适的loader处理

继续完善功能,安装markdown解析模块marked,yarn add marked --dev

该模块可以解析md内容,并返回一个字符串。

markdown-loader仍然返回解析后的html字符串,将结果交给下一个loader处理。

const market = require('market')
module.exports = source => {const html = market(source)return html
}

安装用于加载html的loader(html-loader)。

将这个加载器,配置在markdown-loader的后面执行(代码中位置靠前)。

总结


  • Loader负责资源文件从输入到输出的转换。
  • Loader实际上是一种管道的概念,对于同一个资源可以依次使用多个Loader,将此次loader返回的结果交给下一个loader处理。
    • 例如 上面的 markdown-loader -> html-loader
    • 以及处理样式的 css-loader -> style-loader

推荐阅读
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • PHPMailer邮件类邮件发送功能的使用教学及注意事项
    本文介绍了使用国外开源码PHPMailer邮件类实现邮件发送功能的简单教学,同时提供了一些注意事项。文章涵盖了字符集设置、发送HTML格式邮件、群发邮件以及避免类的重定义等方面的内容。此外,还提供了一些与PHP相关的资源和服务,如传奇手游游戏源码下载、vscode字体调整、数据恢复、Ubuntu实验环境搭建、北京爬虫市场、进阶PHP和SEO人员需注意的内容。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 本文介绍了解决IE678伪类不兼容问题的方法,包括少用CSS3和HTML5独有的属性,使用CSS hacker,使用last-child清除浮动、批量添加标签、去掉list item最后一个的border-right等技巧。同时还介绍了使用after清除浮动时加上IE独有属性zoom:1的处理方法。另外,本文还提到可以使用jQuery代替批量添加标签的功能,以及使用负边距和CSS2选择器element+element去掉list item最后一个的border-right的方法。 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 移动端常用单位——rem的使用方法和注意事项
    本文介绍了移动端常用的单位rem的使用方法和注意事项,包括px、%、em、vw、vh等其他常用单位的比较。同时还介绍了如何通过JS获取视口宽度并动态调整rem的值,以适应不同设备的屏幕大小。此外,还提到了rem目前在移动端的主流地位。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文介绍了一种在PHP中对二维数组根据某个字段进行排序的方法,以年龄字段为例,按照倒序的方式进行排序,并给出了具体的代码实现。 ... [详细]
  • asp.net(vb脚本)如何获取xml的节点值?xmlversion1.0encodingutf-8?rootimageimagemenusmenuurl#frame_paren ... [详细]
  • 前言:原本纠结于Web模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中ev ... [详细]
  • npminstall-Dbabelcorebabelpreset-envbabelplugin-transform-runtimebabelpolyfillbabel-loader ... [详细]
author-avatar
手机用户2602913907
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有