简单实现一个 Webpack 插件

105 阅读1分钟

实现一个 Webpack 插件把构建信息(如 hash)写进一个文件。

写一个 Webpack 插件就是实现一个类或函数,并在原型上定义 apply 方法。

class 版本

const fs = require('fs')

class BuildInfoPlugin {
  constructor({ filename = 'dist/buildinfo.json' } = {}) {
    this.filename = filename
  }
  apply(compiler) {
    compiler.hooks.done.tap(this.constructor.name, stats => {
      const buildInfo = {
        hash: stats.hash
      }
      return new Promise((resolve, reject) => {
        fs.writeFile(
          this.filename,
          JSON.stringify(buildInfo),
          'utf8',
          error => {
            if (error) {
              reject(error)
              return
            }
            resolve()
          }
        )
      })
    })
  }
}

new BuildInfoPlugin({ filename: 'dist/hash.json' })

function 版本

使用 function 实现一个 class

  • class 只能通过 new 调用
  • class 中的函数不能被枚举
  • class 中的函数不能被 new 调用
  • 在 ES6 中使用 class 语法,代码都是在严格模式下运行
'use strict' // 在 ES6 中使用 class 语法,代码都是在严格模式下运行

function BuildInfoPlugin({ filename = 'dist/buildinfo.json' } = {}) {
  if (!(this instanceof BuildInfoPlugin)) {
    // class 只能通过 new 调用
    throw new TypeError(
      "TypeError: Class constructor BuildInfoPlugin cannot be invoked without 'new'"
    )
  }
  this.filename = filename
}
Object.defineProperty(BuildInfoPlugin.prototype, 'apply', {
  value: function(compiler) {
    if (!(this instanceof BuildInfoPlugin)) {
      // class 中的函数不能被 new 调用
      throw new TypeError('TypeError: apply is not a constructor')
    }
    compiler.hooks.done.tap(this.constructor.name, stats => {
      const buildInfo = {
        hash: stats.hash
      }
      return new Promise((resolve, reject) => {
        fs.writeFile(
          this.filename,
          JSON.stringify(buildInfo),
          'utf8',
          error => {
            if (error) {
              reject(error)
              return
            }
            resolve()
          }
        )
      })
    })
  },
  enumerable: false // class 中的函数不能被枚举
})

hash.json

{"hash":"abee8f136a3edc8d9418"}

前端可以利用 hash 判断用户是否在旧页面,提示用户刷新。

参考

Writing a Plugin

JS怎么使用function实现一个class

How to inject Webpack build hash to application code

webpack-stats-plugin

面试官:前端重新部署如何通知用户刷新网页?