如何愉快的开发 Chrome 插件

做为一位前端开发人员,估计是离不开 chrome 浏览器吧,但是你在使用 chrome 时,有遇到一些痛点吗?html

你有想过本身开发一款插件来解决本身使用上的不便吗?其实 chrome 插件已经提供了挺多实用的 API,咱们彻底能够根据本身的需求或兴趣开发本身的插件。前端

chrome 插件没有严格的项目结构的要求,只要求根目录存在一个 manifest.json 相似安卓开发中的 AndroidManifest.xml 这是一个很是重要的功能清单文件,chrome 根据这个文件开放给扩展相应的功能权限。react

<!-- more -->webpack

因此 chrome 扩展的开发彻底能够选择咱们本身熟悉的技术栈开发,好比咱们能够用 React(Vue、Angular) 来开发。下面就是记录我用 React 开发一款好用代理插件 Just Proxy 的过程git

已上架:https://chrome.google.com/web...github

首先须要肯定咱们的插件须要使用 chrome 开发的那些功能,先用户提供哪些界面。web

由于如今要开发的是一款代理插件,咱们向用户提供一下功能:chrome

  • 配置界面(options_page,配置代理服务器设置)
  • 当前 tag 的代理状态(经过右上角的扩展的 Icon 展现,高亮表明当前 tag 使用代理,灰色表明不使用)
  • 代理的切换(点击右上角扩展的 Icon 交互,代理 和 取消代理 之间的状态切换)
  • 代理设置的持久化存储

根据上述的需求,咱们肯定的以下的 manifest.json 的内容。json

{
  "manifest_version": 2,
  "name": "Just proxy",
  "description": "A simple proxy tool",
  "version": "1.0.2",
  "permissions": ["proxy", "storage", "tabs"],
  "browser_action": {
    "default_icon": "emoticon.png"
  },
  "icons": {
    "64": "emoticon.png"
  },
  "options_page": "index.html",
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  }
}

关于 manifest.json 更加详细的内容能够查看 https://developer.chrome.com/...redux

热更新配置

接下来咱们就可使用 Webpack(推荐) 来做为扩展的构建工具,由于 chrome 扩展是须要读取硬盘的文件的,咱们为了提升咱们扩展开发的体验(不要每次修改代码,都须要从新构建扩展,支持热更新),咱们须要借助 write-file-webpack-plugin 来将咱们的内存的编译文件写回硬盘(不严谨)。由于咱们使用 React 构建咱们的扩展程序,因此也要 react-hot-loader 来实现热更新。webpack-dev-server 的配置和咱们开发网页时一致,这里就再也不说明了。

由于 chrome 扩展程序 不是网页,而且它对功能权限有着比网页加严格要求因此咱们须要改造下咱们的 manifest.json 以便支持扩展的热更新

{
  "manifest_version": 2,
  "name": "Just proxy",
  "description": "A simple proxy tool",
  "version": "1.0.2",
  "permissions": ["proxy", "storage", "tabs", "http://127.0.0.1:8000/*"],
  "browser_action": {
    "default_icon": "emoticon.png"
  },
  "icons": {
    "64": "emoticon.png"
  },
  "options_page": "index.html",
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "content_security_policy": "default-src 'self' http://127.0.0.1:8000 http://localhost:8000; script-src 'self' http://127.0.0.1:8000 http://localhost:8000 'unsafe-eval'; connect-src http://127.0.0.1:8000 http://localhost:8000 ws://127.0.0.1:8000 ws://localhost:8000; style-src * 'unsafe-inline' 'self' blob:; img-src 'self' data:;"
}

这里值得关注的点就是 content_security_policy 这一项,这里再也不作详细的说明,想要了解更多的话能够戳下面的连接

https://developer.mozilla.org...

webpack.config.js 的配置须要注意的点,须要注明 publicPath

module.exports = {
  // ...
  output: {
    // ...
    publicPath: "http://127.0.0.1:8000/"
  }
  // ...
};

经过上面的设置咱们就能够拥有一个良好的开发体验了(开发环境和打包环境须要不一样的配置,主要是针对热更新方面)

数据的持久化

项目的状态管理我使用的是 redux,关于状态的持久化咱们能够借助 redux-persist 实现。由于 redux-persist 默认的是使用 localStorage,可是 chrome 扩展中是不支持的,须要本身实现 chrome 插件版本的 storage。 代码以下:

export default class ChromeLocalStorage {
  getItem(key: string) {
    return new Promise(resolve => {
      chrome.storage.local.get(key, item => resolve(item[key]));
    });
  }
  setItem(key: string, value: string) {
    return new Promise(resolve =>
      chrome.storage.local.set({ [key]: value }, resolve)
    );
  }
  removeItem(key: string) {
    return new Promise(resolve => chrome.storage.local.remove(key, resolve));
  }
}

Redux 自动设置代理及多个 store 之间的数据同步

在咱们这个扩展存在两个操做比较麻烦的地方

  1. 如何保证 chrome 的代理设置和 redux store 的代理设置数据一致
  2. 如何保证多个不一样环境(这个扩展中是存在两个环境 options_page 和 background_script)的 store 数据一致

为了处理上面两个问题咱们能够实现一个 redux 中间件来简化上面的操做,实现以下:

const chromeProxyMiddleware = store => {
  // 处理其余环境发过来的 action
  chrome.runtime.onMessage.addListener(request => {
    store.dispatch({ ...request, passed: true });
  });

  return next => action => {
    // 给其余环境发生 action
    if (passingActions.indexOf(action.type) >= 0 && !action.passed) {
      chrome.runtime.sendMessage(action);
    }
    // 设置代理
    chrome.proxy.settings.set(/* proxy config */);
  };
};

export default chromeProxyMiddleware;

项目地址:https://github.com/0jinxing/j...

插件地址:https://chrome.google.com/web...

相关文章
相关标签/搜索