Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

通过 Webpack 的 compiler 对象的 Hooks 学会编写 Webpack 插件的编写 #57

Open
huruji opened this issue Jan 5, 2019 · 0 comments

Comments

@huruji
Copy link
Owner

huruji commented Jan 5, 2019

webpack 的 Hooks

Webpack 的 Compiler 对象主要有以下 Hooks:

  • entryOption

webpack 处理完 entry 配置项后触发,这是一个同步串行的 SyncBailHook 钩子,只要监听函数有一个函数的返回值不为undefined,则直接跳过剩下逻辑

无参数

  • afterPlugins

处理完初始化插件后触发,这是一个同步的 SyncHook 钩子,不关心返回值

参数是 compiler 对象

  • afterResolvers

Resolve 安装完成后触发,这是一个同步的 SyncHook 钩子

参数是 compiler 对象

  • environment

environment 准备好后触发,这是一个 SyncHook 钩子

无参数

  • afterEnvironment

environment 安装完成后触发,这是一个 SyncHook 钩子

  • beforeRun

compiler.run 函数之前触发,这是一个异步串行 AsyncSeriesHook 钩子

参数是 compiler

  • run

开始读取 records 之前触发,这是一个异步串行 AsyncSeriesHook 钩子

参数是 compiler

  • watchRun

监听模式下,一个新的编译开始之前触发,这是一个异步串行的 AsyncSeriesHook 钩子

参数是 compiler

  • normalModuleFactory

normalModuleFactory 创建之后触发,这是一个同步 SyncHook 钩子

参数是 normalModuleFactory

  • contextModuleFactory

contextModuleFactory 创建之后触发,

参数是 contextModuleFactory

  • beforeCompile

编译参数创建之后触发,这是一个异步串行 AsyncSeriesHook 钩子

参数是 compilationParams

  • compile

一个新的编译创建之后触发,这是一个同步 SyncHook 钩子

参数是 compilationParams

  • thisCompilation

触发 compilation 之前触发,这个是一个同步 SyncHook 钩子

参数是 compilation

  • compilation

编译创建之后执行,这是一个同步 SyncHook 钩子

参数是 compilation

  • make

这是一个异步并发 AsyncParallelBailHook 钩子

参数是 compilation

  • afterCompile

这是一个异步串行 �AsyncSeriesHook 钩子

参数是 compilation

  • shouldEmit

这是一个 SyncBailHook 钩子

参数是 compilation

  • emit

�生成资源到 output 目录之前�触发,这是一个异步串行 AsyncSeriesHook 钩子

参数是 compilation

  • afterEmit

生成资源到 output �目录之后,这是一个异步串行 AsyncSeriesHook 钩子

参数是 compilation

  • done

编译完成后触发,这是一个异步串行 AsyncSeriesHook 钩子

参数是 stats

  • failed

编译失败触发,这是一个同步 SyncHook 钩子

参数是 error

  • invalid

监听模式下,编译无效时触发,这是一个同步 SyncHook 钩子

参数是 fileName,changeTime

�+ watchClose

监听模式停止,一个同步 SyncHook 钩子

插件编写实例

webpack-clear-console

通过实例学习是最快的,让我们看一个最简单的例子,webpack-clear-console,这个插件是去除输出里的 console 调用,里面插件的写法是 webpack4 之前的写法,不过基本上是一致的,通过源码可以看到插件在 emit 这个钩子上(生成资源到output目录之前)触发,通过 compilation 对象的 assets 对象的 source 方法获取文件内容,然后进行正则匹配。
最后需要将 source 和 size 的变动归回原来的 compilation 对象中,否则这些变动是不会生效的

island-webpack-plugin

island-webpack-plugin 是一个在 bundle 中添加作者信息的插件,这个插件同样是在 emit 这个钩子上触发的,同样是获取 source 后对 source 添加作者信息的字符串。

emit 是一个异步的钩子,可以使用 promise 的 如下,可以使用 promise 对上面的插件进行简单改造,以 island-webpack-plugin 为例,改造如下:

class AuthorPlugin {
    constructor(options) {
        this.options = options;
    }
    apply(compiler) {
        compiler.hooks.emit.tap('author-plugin', (compilation) => {
            const options = this.options
            return new Promise((resolve, reject) => {
                const assets = compilation.assets
                Object.keys(assets).forEach(e => {
                    let source = assets[e].source()
                    let info = []

                    if (options.author) info.push(`@Author: ${options.author}`)
                    if (options.email) info.push(`@Email: ${options.email}`)
                    if (options.homepage) info.push(`@Homepage: ${options.homepage}`)

                    if (info.length) {
                        info.push(`@Date: ${new Date()}`)
                        source = `/*\n  ${info.join('\n\n  ')}\n*/\n${source}`
                    }

                    compilation.assets[e].source = () => source
                    compilation.assets[e].size = () => source.size
                })
                resolve()
            })
        })
    }
}

module.exports = AuthorPlugin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant