Chrome插件在webpack项目中也能使用热更新

3 阅读1分钟

一、Vite项目的Chrome插件开发能够热更新

得益于@crxjs/vite-plugin,vite项目很丝滑就能支持在开发插件时享受热更新的便捷

但是还有很多旧项目依然还是使用webpack + vue2技术栈 ,且因为项目老旧重,升级的成本过高。所以还在使用手动刷新标签页的开发模式,非常难受

二、给旧项目加上热更新

接手这个项目,为了让自己开发舒服一点,一定要把热更新加上!

让AI分析了一下@crxjs/vite-plugin干的事,原来是MV3 的 CSP 允许

script-src 'self' http://localhost:*

因此扩展页面可以从本地 dev server 加载脚本,那如果我起一个开发服务器,再把路径给到CSP,是不是就实现了

三、写一个插件实现热更新

如果MV3本身就支持这个东西,那我们要做的事就很简单了

  1. 修改一下项目的 manifest.json
  2. 开一个开发服务器
1. 第一步

写一个插件,完成 manifest.json的修改

class ExtHmrManifestPlugin {
  constructor (options = {}) {
    this.port = options.port || 3200
  }

  apply (compiler) {
    compiler.hooks.afterEmit.tapAsync('ExtHmrManifestPlugin', (compilation, callback) => {
      const outputPath = compiler.options.output.path
      const manifestPath = path.join(outputPath, 'manifest.json')

      fs.readFile(manifestPath, 'utf-8', (err, data) => {
        if (err) {
          callback()
          return
        }

        try {
          const manifest = JSON.parse(data)

          manifest.content_security_policy = {
            extension_pages: [
              `script-src 'self' http://localhost:${this.port}`,
              `object-src 'self'`
            ].join('; ')
          }

          fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2), (writeErr) => {
            if (!writeErr) {
              console.log(
                '\x1b[36m%s\x1b[0m',
                `[ext-hmr] ✓ manifest.json CSP 已注入 (localhost:${this.port})`
              )
            }
            callback()
          })
        } catch (parseErr) {
          callback() 
        }
      })
    })
  }
}
2. 第二步

开一个本地的服务

function createServer (config, options = {}) {
  const port = options.port || 3200
  config.publicPath = `http://localhost:${port}/`
  config.devServer = Object.assign(config.devServer || {}, {
    port: port,
    hot: true,
    writeToDisk: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
      'Access-Control-Allow-Headers': '*'
    },
    disableHostCheck: true
  })

  if (!config.configureWebpack.plugins) {
    config.configureWebpack.plugins = []
  }
  config.configureWebpack.plugins.push(
    new ExtHmrManifestPlugin({ port: port }),
  )

  console.log(
    CYAN_FMT,
    `[ext-hmr] ✓ HMR 模式已启用 → http://localhost:${port}/`
  )

  return true
}

当你启动服务器后,如果在console中看到了HMR,那么恭喜你,可以愉快地开发了

image.png

四、封装成插件,方便使用

因为调试途中还遇到了一些小问题,所以把完整的封装了一个插件,如果有需要的小伙伴可以试下 ext-hmr-webpack-plugin