最近開了一個讀者回饋表單郵箱,無論是對文章的感想或是對部落格的感想,有什麼想回饋的都可以發郵箱跟我說:i_kkkp@163.com

Webpack-自定义 loader/plugin

引言

loader 是导出为一个函数的 node 模块。该函数在 loader 转换资源的时候调用。给定的函数将调用 Loader API,并通过 this 上下文访问。

这边贴一个官网链接loader的用法和例子,以及自定义loader本地开发测试

Webpack Loader的简单使用

当一个 loader 在资源中使用,这个 loader 只能传入一个参数 - 一个包含资源文件内容的字符串。

同步 loader 可以 return 一个代表已转换模块(transformed module)的单一值。

loader 会返回一个或者两个值。第一个值的类型是 JavaScript 代码的字符串或者 buffer。第二个可选值是 SourceMap,它是个 JavaScript 对象。

下面是一个简单的loader的用法,他将匹配所有的js文件,并使用loader.js处理

//webpack.config.js
const path = require('path');
module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: path.resolve('path/to/loader.js'),
            options: {
              /* ... */
            },
          },
        ],
      },
    ],
  },
};

由上面我们可以知道loader的使用方法,但对loader仅停留在使用,那具体的一个loader长什么样呢?

比如说一个简单的loader是这样的:

module.exports = function (content) {
	// content 就是传入的源内容字符串
  return content
}

一个 loader 就是一个node模块,其中暴露了一个函数,并只可以接收一个入参,这个参数是一个包含包含资源文件内容的字符串,而函数的返回值就是处理后的内容。

自定义webpack loader

自定义loader的用法准则

编写 loader 时应该遵循以下准则。它们按重要程度排序,有些仅适用于某些场景,请阅读下面详细的章节以获得更多信息。

  • 保持 简单 。
  • 使用 链式 传递。
  • 模块化 的输出。
  • 确保 无状态 。
  • 使用 loader utilities
  • 记录 loader 的依赖 。
  • 解析 模块依赖关系 。
  • 提取 通用代码 。
  • 避免 绝对路径 。
  • 使用 peer dependencies

步骤1:创建项目目录和文件

首先,在一个webpack项目目录中的文件夹中创建以下文件:

  • src/loader/custom-loader.js:自定义Loader的源文件。
  • src/index.js:JavaScript入口文件,用于测试自定义Loader。

步骤2:编写自定义Loader

custom-loader.js 文件中,编写你的自定义loader代码。这个Loader的作用是将在每个加载的JavaScript文件的顶部添加一个注释。

// src/loader/custom-loader.js
module.exports = function(source) {
    // 在源代码的顶部添加自定义注释
    const updatedSource = `/** Custom Comment added by Custom Loader */\n${source}`;
    return updatedSource;
};

步骤3:配置Webpack

在项目根目录下创建Webpack配置文件 webpack.config.js。在配置文件中,使用刚刚编写的自定义Loader。

// webpack.config.js
const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: ['custom-loader'], // 使用自定义Loader处理.js文件
                exclude: /node_modules/,
            },
        ],
    },
};

功能就简单的进行了一下实现,这里我们主要说一下如何测试调用我们的本地的 loader,方式有两种,一种是通过 Npm link 的方式进行测试,这边贴一个Npm link的链接,大家可以去创建一个软连接进行本地测试,还是挺方便的npm-link。 另外一种就是直接在项目里面进行路径配置:

单loader配置方法

//webpack.config.js
{
  test: /\.js$/
  use: [
    {
      loader: path.resolve('path/to/custom-loader.js'),
      options: {/* ... */}
    }
  ]
}

多loader配置方法

当然也可以通过数组的方式进行配置

//webpack.config.js
resolveLoader: {
  // 这里就是说先去找 node_modules 目录中,如果没有的话再去 loaders 目录查找
  modules: [
    'node_modules',
    path.resolve(__dirname, 'custom-loader')
  ]
}

步骤4:测试自定义Loader

index.js 文件中,编写一些JavaScript代码,例如:

// src/index.js
console.log('Hello, Webpack Loader!');

步骤5:运行Webpack构建

运行以下命令来构建你的项目:

npx webpack --config webpack.config.js

构建完成后,你将在 dist 文件夹中找到生成的 bundle.js 文件。在这个文件里面可以看到在顶部添加了自定义注释的JavaScript代码。


Webpack plugin的简单使用

插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以在 webpack 构建流程中引入自定义的行为。

比如说最简单的一个例子:

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html', // 指定HTML模板文件
            filename: 'index.html', // 生成的HTML文件名
        }),
        // 可以添加更多的插件
    ],
};

在上面这个例子里面使用了HtmlWebpackPlugin插件,根据指定的HTML模板生成一个新的HTML文件,并将打包后的JavaScript文件自动添加到生成的HTML文件中。

一个基本的webpack 插件由以下组成:

  • 一个 JavaScript 命名函数或 JavaScript 类。

  • 在插件函数的 prototype 上定义一个 apply 方法,apply 方法在 webpack 装载这个插件的时候被调用,并且会传入 compiler 对象。。

  • 指定一个绑定到 webpack 自身的事件钩子。

  • 处理 webpack 内部实例的特定数据。

  • 功能完成后调用 webpack 提供的回调。

一个插件结构如下:

class HelloWorldPlugin {
  apply(compiler) {
    compiler.hooks.done.tap(
      'Hello World Plugin',
      (
        stats /* 绑定 done 钩子后,stats 会作为参数传入。 */
      ) => {
        console.log('Hello World!');
      }
    );
  }
}

module.exports = HelloWorldPlugin;

Compiler and Compilation

在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。可以说Webpack plugin的开发就是围绕着这两个对象的 hook 进行操作

compiler 对象可以理解为一个和 webpack 环境整体绑定的一个对象,它包含了所有的环境配置,包括 options,loader 和 plugin,当 webpack 启动时,这个对象会被实例化,并且他是全局唯一的,上面我们说到的 apply 方法传入的参数就是它。

compilation 在每次构建资源的过程中都会被创建出来,一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。它同样也提供了很多的 hook 。

自定义Webpack plugin

步骤1:创建项目目录和文件

首先,还是需要一个webpack项目。我们在这个文件夹中创建以下文件:

  • src/plugins/CustomPlugin.js:自定义插件的源文件。

步骤2:编写自定义插件

CustomPlugin.js 文件中,我们编写了一个插件,并将在Webpack构建结束时输出一条信息。

// src/plugins/CustomPlugin.js
class CustomPlugin {
    apply(compiler) {
        compiler.hooks.done.tap('CustomPlugin', () => {
            console.log('CustomPlugin: Webpack build process is done!');
        });
    }
}

module.exports = CustomPlugin;

步骤3:配置Webpack

在配置文件中,使用上面我们的自定义插件。

// webpack.config.js
const CustomPlugin = require('./src/plugins/CustomPlugin');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist',
    },
    plugins: [
        new CustomPlugin(),
        // 可以添加更多的插件
    ],
};

步骤4:运行Webpack构建

现在进行Webpack构建:

npx webpack --config webpack.config.js
Vue.js 响应式系统的作用与实现 301/302-重定向

評論