chrome 插件开发中的热更新问题

栏目: 编程语言 · 发布时间: 5年前

内容简介:在编写分析原因:在配置 webpack 的热更新的时候,我们都会在 entry 配置如下配置:

在编写 chrome 插件开发模板 的时候,遇到了 webpack 的 热更新不完全生效 的问题。

  1. 不生效情景:

    当 chrome 插件的 manifest.json 中的 background, content_scripts 被配置为 js 的形式时(如下),这些脚本必须在文件目录中存在(注意:background 的 scripts 和 content_scripts 的 js 两个属性是不能使用远程链接的)。

    {
    	  "background": {
    	    "persistent": false,
    	    "scripts": ["background.js"]
    	  },
    	  "content_scripts": [
    	    {
    	      "matches": ["http://*/*", "https://*/*"],
    	      "js": ["content.js"],
    	      "all_frames": true
    	    }
    	  ],
      }
    复制代码
  2. 生效情景: 当 chrome 插件的 manifest.json 中的 background, popup 被配置为 html (js 在 html 中被以 远程链接 的形式引入) 的形式时(如下),

    {
    	  "browser_action": {
    	    "default_popup": "pages/popup.html"
    	  },
    	  "background": {
    	    "persistent": false,
    	    "page": "pages/background.html"
    	  },
      }
    复制代码
    <!DOCTYPE html>
    	<html>
    	  <head>
    	    <meta charset="utf-8">
    	    <script src="http://127.0.0.1:3000/js/background.js"></script>
    	  </head>
    	</html>
    复制代码
    <!DOCTYPE html>
    	<html>
    	  <head><meta charset="UTF-8"></head>
    	  <body>
    	    <div id="chrome-popup-root"></div>
    	    <script src="http://127.0.0.1:3000/js/popup"></script>
    	  </body>
    	</html>
    复制代码

分析原因:

在配置 webpack 的热更新的时候,我们都会在 entry 配置如下配置: webpack-hot-middleware/client?path=http://127.0.0.1:3000/__webpack_hmr&noInfo=false&reload=true&quiet=false

然后开发过程中,我们会在 network 中发现很多 http://127.0.0.1:3000/__webpack_hmr/xxx 这样的网络请求,这些请求就是用来获取对应脚本的修改部分,并触发其发生热更新,最后局部进行重新渲染。所以这样的 热更新只能支持远程链接配置 的形式。这就是 chrome 插件开发时的热更新不完全生效的原因。

2. 解决开发chrome 插件过程中修改代码后自动重载的问题

上面我们提到 manifest.json 中的 background 的 scripts 和 content_scripts 的 js 两个属性是不能使用远程链接的,所以 webpack 的热更新并不适合 js 脚本配置的 chrome 插件开发。

而开发过 chrome 插件的同学都知道,对于使用本地脚本配置的方式,在修改了脚本后,需要去应用扩展后台手动更新插件,否则插件不会更新。(这里推荐另一个插件,可以重载其他当前正在开发的 chrome 插件: github.com/arikw/chrom…

所以,这里就衍生出了开发 chrome 插件过程中修改代码后能否自动重载的问题。

我们逆向思考:要重载插件,需要获得代码的修改时机;要获得代码的修改时机,需要了解 webpack 在每次修改编译后如何通知到客户端。

于是继续衍生出以下几个问题:

  1. 如何获取 webpack 每次触发修改编译后的钩子
  2. 如何在 webpack 钩子回调中及时通知浏览器代码已更新
  3. 浏览器接受到修改通知后,如何更新重载插件和页面

我们一个一个来解决

1. 如何获取 webpack 每次触发修改编译后的钩子

查阅 webpack 文档我们可以找到如下方法:

const compiler = webpack(webpackConfig)
compiler.hooks.done.tap('name', () => {
	// todo
})
复制代码

2. 如何在 webpack 钩子回调中及时通知浏览器代码已更新

首先请详细看一下这几篇文章和源码:《Server-Sent Events》、 《Webpack 热更新实现原理分析》《EventSource client for Node.js and Browser (polyfill)》

SSE 就是一种由服务端直接将信息推送给客户端的单向通道,相比 websocket 则会更加轻量。

客户端:

if ('EventSource' in window) {
    const source = new EventSource(`http://localhost:3000/sse`)

    source.addEventListener('open', (event) => {
      console.log('Auto Reload Listen: ', event);
    }, false);

    source.addEventListener('compiled', (event) => { // 自定义事件
      console.log('compiled: ', event);
      // todo
    }, false);

    source.addEventListener('error', (event) => {
      console.log('error: ', event);
    }, false);
  }
复制代码

服务端:

const SseStream = require('ssestream');

const compiler = webpack(webpackConfig);

app.use('/sse', webpackChromeExtensionsReloadMiddleware(compiler));

function webpackChromeExtensionsReloadMiddleware(compiler, opts = {}) {
  opts.heartbeat = opts.heartbeat || 5 * 1000;

  const middleware = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');

    const sseStream = new SseStream(req) // 构造 sse 的请求
    sseStream.pipe(res)

    if (compiler.hooks) {
      compiler.hooks.done.tap('webpack-chrome-extensions-reload-middleware', () => {
        sseStream.write({ // 请求数据
          event: 'compiled',
          data: 'compiled'
        })
      })
    }

    res.on('close', () => {
      console.log('close connection')
      sseStream.unpipe(res)
    })

    next();
  };
  return middleware;
}
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

颠覆医疗

颠覆医疗

[美]埃里克·托普 / 张南、魏薇、何雨师 / 译言·东西文库/电子工业出版社 / 2014-1-20 / 55.00

“创造性破坏”是奥地利经济学家约瑟夫·熊彼特最著名的理论,当一个产业在革新之时,都需要大规模地淘汰旧的技术与生产体系,并建立起新的生产体系。电器之于火器、汽车之于马车、个人计算机之于照排系统,都是一次又一次的“创造性破坏”,旧的体系完全不复存在,新的体系随之取代。 “创造性破坏”已经深深地改变了我们的生活,在这个数字时代,我们身边的一切都被“数字化”了。只有一处,也许是由于其本身的根深蒂固,......一起来看看 《颠覆医疗》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具