webpack 核心模块 —— loader & plugins(上)

简介: webpack 核心模块 —— loader & plugins

image.png


前言

本文主要针对 webpack 中的 laoder 和 plugins 进行学习,不涉及如何使用和配置 webpack,因为这些基础在官方文档中已经很明确了,重点在于如何去实现属于自定义的 laoder 和 plugins。那么在开始前,先简单的介绍下什么叫构建工具。

构建工具

在 web 应用程序中,除了 HTML 文件之外,往往还需要用的很多的其他静态资源加以修饰,比如在 HTML 中使用的 图片、css 样式、js文件等等,但是浏览器并不能识别所有的文件资源,并正确的加载。

因此,开发者需要对不同的文件资源进行对应的处理操作,目的是为了能够正确的加载和使用对应的文件资源。比如:

  • 图片除了常用的一些格式能被正常加载和显示之外,一些特殊的格式就无法直接使用;
  • css 样式我们可能会使用 less / scss / css in js 等方式去使用;
  • js 文件中可能使用了比较新的语法,如 ES6 、ES7 以至于更新的特性,需要对应的编译工具去做转换等等。

由于需要针对不同的文件资源做不同的处理,并且还要考这些用于处理文件资源工具的维护问题,因此就诞生了构建工具。

构建工具就是包含了处理大多数以上提及到问题的解决方案,意味着原本我们需要不同的小工具去处理不同的文件内容,但是现在只需要关注构建工具本身如何使用即可。

webpack

webpack 是什么?

webpack 是众多构建工具中的一种,它也是一个用于现代 JavaScript 应用程序的 静态模块打包工具

webpack 处理应用程序时,它会在内部从 一个多个 入口点去构建一个 依赖图,然后将项目中所需的每一个模块组合成一个或多个 bundles,它们均为 静态资源,用于展示你的内容。

其中涉及到的 chunkbundles 的概念,可以根据下图来辅助理解:

  • 根据引入的各种文件资源,形成对应的 依赖图,其中包含了要处理的 代码块 chunk
  • 代码块 chunk 进行对应的处理,也称之为打包,输出之后就得到了需要的 bundles

image.png

五大核心

mode

  • 可选值:development, productionnone
  • 设置 mode 参数,可以启用 webpack 内置在相应环境下的默认优化
  • mode 参数默认值为 production

entry

入口起点(entry point) 指示 webpack 应该使用哪个文件作为入口模块,用来作为构建其内部依赖图,可以拥有多个入口文件。

output

output 负责告诉 webpack 需要在哪里输出它所创建的 bundle,以及怎么去命名这些文件.

  • 默认输出目录: ./dist
  • 默认主要输出文件名: ./dist/main.js
  • 其他生成文件默认放在 ./dist

loader

webpack 只能理解 JavaScriptJSON 文件,开箱的 webapck 没办法识别其他文件类型。loader 就能够把这些文件类型转换成 weback 能识别的资源,并将它们转换为有效 模块,以便于在应用程序中去使用,同时也会被添加到依赖图中。

plugin

loader 用于转换某些类型的模块,而 plugin 则可以用于执行包括 loader 在内的、范围更广的任务。比如:打包优化,资源管理,注入环境变量等。

  • 可以通过 require 引入对应plugin 插件,并在选项配置 plugins 的数组中 实例化调用 new PluginName(opt)
  • 可以自定义 webpack 插件实现具体场景的需求

loader

在 webpack 中 loader 是什么?

loader 本质就是一个函数,这个函数会接收三个参数:

  • content:对应模块的内容
  • map:对应模块的 sourcemap
  • meta:对应模块的元数据

loader 执行顺序

通常 loader 的书写结构决定了对执行顺序的描述:

  • 左右结构 ——> 执行顺序为 从右往左
  • 上下结构 ——> 执行顺序为 从下往上

为了更清晰和直观,下面列出了一个在 webpack 配置中和样式相关的常见配置:

module: {
    rules: [
      {
        test: /\.css$/,
        // 左右结构
        use: ['style-loader', 'css-loader'],
        //   或
        // 上下结构
        use: [
          'style-loader',
          'css-loader'
        ]
      }
    ]
  }
复制代码

无论是 左右结构 还是 上下结构,都可以统一理解为 从后往前 的顺序去执行.

自定义 loader

  • 新建 loader1.jsloader2.js 作为自定义 loader,注意除了向外暴露的函数方法以外,还给这个函数对象上添加了一个 pitch 方法,内容具体如下:

pitch 方法执行顺序和 loader 是相反的,也就是说 pitch从前往后 的顺序去执行.

// loader1.js
module.exports = function(content, map, meta) {
  console.log('loader1 ...');
  return content;
}
module.exports.pitch = function (){
  console.log('loader1 pitch...');
}
// loader2.js
module.exports = function(content, map, meta) {
  console.log('loader2 ...');
  return content;
}
module.exports.pitch = function (){
  console.log('loader2 pitch...');
}
复制代码
  • 并在 webpack.config.js 中进行配置,内容如下:
// webpack.config.js
const { resolve } = require('path');
module.exports = {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          resolve(__dirname, 'loaders/loader1.js'),
          resolve(__dirname, 'loaders/loader2.js'),
        ]
      },
    ]
  }
}
复制代码
  • 为了简化每次引入自定义 loader 时,都要写完整路径,如:resolve(__dirname, 'loaders/xxx.js),因此可以通过配置 resolveLoader 选项统一指定 loader 要查找的路径,具体如下:
// webpack.config.js
const { resolve } = require('path');
module.exports = {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          'loader1',
          'loader2',
        ]
      },
    ]
  },
  resolveLoader: {
    modules: [
      resolve(__dirname, 'loaders'),
      'node_modules'
    ],
  }
}
复制代码
  • 当在编辑器终端输入 webpack 指令进行打包时,控制台输出结果如下:

image.png

loader 的同步和异步

同步 loader

自定义 loader 中书写 loader 的方式就属于同步 loader,当然还有另一种写法,那就是通过调用 this.callback() 方法,可以将上述 自定义 loader 中的写法进行改写,具体如下:

this.callback(error, content, map, meta),其中 error 表示错误内容,当没有错误时,可将其执行为 null. 使用这样的方式,就不需要在显式的进行 return.

// loader1.js
module.exports = function(content, map, meta) {
  console.log('loader1 ...');
  this.callback(null, content, map, meta);
}
module.exports.pitch = function (){
  console.log('loader1 pitch...');
}
// loader2.js
module.exports = function(content, map, meta) {
  console.log('loader1 ...');
  this.callback(null, content, map, meta);
}
module.exports.pitch = function (){
  console.log('loader1 pitch...');
}
复制代码

异步 loader

异步 loader 需要通过 const callBack = this.async(); 方法进行指定,然后通过调用 callBack() 方法表明异步执行完成.

可以将 loader2.js 变为异步 loader,改造内容和运行结果如下:

// loader2.js
module.exports = function(content, map, meta) {
  console.log('loader2 ...');
  const callback = this.async();
  setTimeout(()=>{
    callback(null,content, map, meta);
  },1000);
}
module.exports.pitch = function (){
  console.log('loader2 pitch...');
}
复制代码

image.png

PS: 当执行到 loader2 时,会先等待 1s 左右,然后在执行 loader1 . 同时 compiled successfully 的时间明显比之前更多.


目录
相关文章
|
28天前
|
前端开发 UED
Webpack 中处理 CSS 和图片资源的多 Loader 配置
【10月更文挑战第12天】 处理 CSS 和图片资源是 Webpack 配置中的重要部分。通过合理选择和配置多个 Loader,可以实现对这些资源的精细处理和优化,提升项目的性能和用户体验。在实际应用中,需要不断探索和实践,根据项目的具体情况进行灵活调整和优化,以达到最佳的处理效果。通过对 Webpack 中多 Loader 处理 CSS 和图片资源的深入了解和掌握,你将能够更好地应对各种复杂的资源处理需求,为项目的成功构建和运行提供坚实的基础。
52 1
|
28天前
|
前端开发 JavaScript
Webpack 中多个 Loader 的配置
【10月更文挑战第12天】使用多个 Loader 进行配置是 Webpack 中常见的操作,可以实现对各种资源的精细处理和优化。在配置时,需要根据具体需求合理选择和排列 Loader,并注意它们之间的顺序和交互关系。同时,不断了解和掌握新的 Loader 以及它们的特性,有助于更好地发挥 Webpack 的强大功能,提升项目的开发效率和质量。通过深入理解和熟练运用多个 Loader 的配置方法,你将能够更加灵活地处理各种资源,满足项目的多样化需求。
41 2
|
28天前
|
前端开发 JavaScript
Webpack 常用 Loader 和 Plugin
【10月更文挑战第12天】Webpack 是一个强大的模块打包工具,能够将各种资源模块进行打包和处理。Loader 用于转换模块的源代码,如 `babel-loader` 将 ES6+ 代码转换为 ES5,`css-loader` 处理 CSS 文件等。Plugin 扩展 Webpack 功能,如 `HtmlWebpackPlugin` 自动生成 HTML 文件,`UglifyJsPlugin` 压缩 JavaScript 代码。通过合理配置和使用 Loader 和 Plugin,可以构建高效、优化的项目。
21 2
|
29天前
|
缓存 前端开发 JavaScript
深入了解Webpack:模块打包的革命
【10月更文挑战第11天】深入了解Webpack:模块打包的革命
|
27天前
|
缓存 前端开发 JavaScript
Webpack技术深度解析:模块打包与性能优化
【10月更文挑战第13天】Webpack技术深度解析:模块打包与性能优化
|
2月前
|
设计模式 前端开发 JavaScript
webpack实战之手写一个loader和plugin
该文章详细讲解了如何从零开始编写一个自定义的Webpack Loader和Plugin,包括它们的工作原理、开发步骤以及如何将自定义的Loader和Plugin集成到Webpack配置中。
webpack实战之手写一个loader和plugin
|
2月前
|
前端开发 开发者
在前端开发中,webpack 作为一个强大的模块打包工具,为我们提供了丰富的功能和扩展性
【9月更文挑战第1天】在前端开发中,Webpack 作为强大的模块打包工具,提供了丰富的功能和扩展性。本文重点介绍 DefinePlugin 插件,详细探讨其原理、功能及实际应用。DefinePlugin 可在编译过程中动态定义全局变量,适用于环境变量配置、动态加载资源、接口地址配置等场景,有助于提升代码质量和开发效率。通过具体配置示例和注意事项,帮助开发者更好地利用此插件优化项目。
80 13
|
3月前
|
缓存 JSON JavaScript
Webpack 传递给 Loader 的原始内容是一个 UTF-8 格式编码的字符串
本文详细介绍了Webpack中Loader的概念及其重要性。Webpack仅支持处理JS和JSON文件,而对于CSS、图片等其他类型文件,则需要Loader来转换。文章列举了多种常见Loader,如css-loader、style-loader、babel-loader等,并提供了具体配置示例。此外,还介绍了如何自定义Loader,包括初始化项目、实现基本功能及处理异步操作等内容。通过本文,读者可以全面了解Loader的作用及其实现方法。
31 3
|
3月前
|
缓存 前端开发 JavaScript
Webpack 模块解析:打包原理、构造形式、扣代码补参数和全局导出
Webpack 模块解析:打包原理、构造形式、扣代码补参数和全局导出
128 1
|
3月前
|
前端开发 开发者
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。
在前端开发中,webpack 作为模块打包工具,其 DefinePlugin 插件可在编译时动态定义全局变量,支持环境变量定义、配置参数动态化及条件编译等功能。本文阐述 DefinePlugin 的原理、用法及案例,包括安装配置、具体示例(如动态加载资源、配置接口地址)和注意事项,帮助开发者更好地利用此插件优化项目。
89 0