webpack学习方法(教你开发一款属于你自己的)

大家好,我是喜欢写 hello world 的前端西瓜哥这次我们开发一个自己的 webpack 插件,接下来我们就来聊聊关于webpack学习方法?以下内容大家不妨参考一二希望能帮到您!

webpack学习方法(教你开发一款属于你自己的)

webpack学习方法

大家好,我是喜欢写 hello world 的前端西瓜哥。这次我们开发一个自己的 webpack 插件。

插件使用的 webpack 版本为 4.46.0。

webpack 插件有什么用?

webpack plugins 是 webpack 非常重要的一环,用于增强 webpack 的功能。

插件会在 webpack 构建时的生命周期钩子上做一些处理。比如,最常用的 HtmlWebpackplugin 是在打包文件构建好之后,该插件会额外生成一个 HTML,并将将打包文件通过引用的方式加入到 HTML 文件里。

下面正式开始开发一款名为 HelloWorldPlugin 的插件,作用是打包时额外生成一个 hello.js 文件。

plugin 的结构

首先插件需要有一个 apply 方法。webpack 构建时,会执行这个 apply 方法,并将 webpack 的 compiler 对象传入进去。

通过这个对象,我们可以访问 webpack 的生命周期钩子,改动一些构造过程中产生的对象,影响最终构建结果。

理论上插件是个有 apply 方法的对象即可,但最好还是写成类的形式。

我们看下 webpack 常见的配置写法:

const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { // ... new HtmlWebpackPlugin({ template: 'index.html', }), // ... }

可以看到,类的写法可以更方便地传入配置项,以及被复用(这里的 new HtmlWebpackPlugin 其实可以被使用多次,构造多个 HTML)。

我们的 HelloWorldPlugin 类的基本框架为:

class HelloWorldPlugin { options; constructor(options) { this.options = options; } apply(compiler) { console.log('hello'); } } module.exports = HelloWorldPlugin;

然后将该插件加入到 webpack 配置中:

const HelloWorldPlugin = require('./HelloWorldPlugin'); module.exports = { entry: './src/index.js', output: { filename: 'app.js', }, plugins: [ // 插件在这里 new HelloWorldPlugin(), ], }

此时如果执行 webpack 构建,你会在控制台中看到 hello 被打印出来。

此外构造函数也会将传入的配置对象保存起来,当然这里我还没传任何东西。

使用 webpack 的生命周期钩子

下面我们让 HelloWorldPlugin 去通过钩子去额外生成一个文件。

先看 plugin 代码实现:

const { RawSource } = require('webpack-sources'); const pluginName = 'hello-world-Plugin'; class HelloWorldPlugin { options; constructor(options) { this.options = options; } apply(compiler) { // 生成一个文件 compiler.hooks.emit.tap(pluginName, (compilation) => { compilation.assets['hello.js'] = new RawSource('console.log(\'Hello world!\')'); }) } } module.exports = HelloWorldPlugin;

apply 方法中,通过 compiler.hooks 可以拿到所有的钩子。

我们要用到是 emit hook。emit hook 的触发时机是 webpack 打包好资源,准备将资源生成到构建目录之前,此时正是我们往里面塞一个文件的好时机。

我们需要执行这个 emit hook 的 tap 方法来注册事件响应函数,这里需要传入当前插件名和一个回调函数。传入插件名,我也不清楚是要干嘛,大概是做一个标记,方便 debug。回调函数则会拿到一个 compilation 对象,这个对象下的 assets 其实就是即将生成的文件。我们可以直接修改这个对象,补上一个 hello.js 文件。

这里需要用到 webpack 官方提供的 webpack-sources 库,这个库专门用来生成符合 assets 格式的对象。

const { RawSource } = require('webpack-sources'); compilation.assets['hello.js'] = new RawSource('console.log(\'Hello world!\')');

如果你使用 webpack5,该库其实已经内置到 webpack 中,通过 require('webpack').sources 即可获取到。

使用 webpack 构建后,你会发现 dist 目录下,除了有一个 app.js 文件,还有一个内容为 console.log('Hello world!') 的 hello.js 文件。

使用插件配置

这里我们没有用到插件传入的配置,我们对 HelloWorldPlugin 做个加强,用到配置。

插件改为:

const { RawSource } = require('webpack-sources'); const pluginName = 'hello-world-plugin' class HelloWorldPlugin { options; constructor(options) { this.options = options; } apply(compiler) { const { filename, content} = this.options; compiler.hooks.emit.tap(pluginName, (compilation) => { compilation.assets[filename] = new RawSource(content); }) } } module.exports = HelloWorldPlugin;

配置改为:

plugins: [ new HelloWorldPlugin({ filename: 'a.js', content: 'b', }), ]

于是你额外拿到了一个内容为 b 的 a.js 文件。

结尾

总结一下,开发一个 Plugin 的几个要点:

  1. 确定 webpack 版本,使用对应的 API。否则插件可能用了更高版本的 webpack 语法且没有兼容而无法工作,比如 webpack4 中, CopyWebpackPlugin 的版本不能高于 6。
  2. 插件需要通过类的方式保存好传入的配置项,并提供一个 apply 方法。
  3. 插件本质是利用 webpack 构建时的各种生命周期钩子,在其中对数据做一些改动,最终导致构建的资源发生变化。
  4. webpack 官方文档写得很垃圾

我是啥都写写的前端西瓜哥,欢迎关注我。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页