Build in public 记录: 我们是如何开发 TinySnap 的

我们是如何开发 TinySnap 这个浏览器截图扩展的。

Build in public 记录: 我们是如何开发 TinySnap 的

背景

其实 Chrome Web Store 中已经存在非常多的屏幕截图扩展了,但制作 TinySnap 的核心理念还是希望可以帮助繁忙的创业者、开发者以及营销人员提高生产力,尤其是那些有着完美主义情怀的人。我们想要用户在最短的时间内完成 “截图-美化-发布” 的过程。

输出之后的截图如下:

TinySnap 示例

正如 Leila Hock 所说:“It’s not hard work–work is work, and yes, some work requires more brain power, but most of us smart people like that and want more of it, so let’s stop calling it hard. Let’s call it productive. Effective. Valuable. Anything that speaks to nature over quantity, because that’s what we need more of.” 这不是艰苦的工作——工作就是工作,是的,有些工作需要更多的脑力,但我们大多数聪明人都喜欢这样,并且想要更多,所以让我们停止说它很难。 让我们称之为生产力。 有效的。 有价值的。 任何与自然对话超过数量的东西,因为这是我们需要更多的东西。

这就是我们开发构造 TinySnap 的原因。

当我们想要开始做浏览器拓展时,占有率最高的浏览器是 Google Chrome ,我们自然是要从这里开始。

Google Chrome 在 web extension 上表现得一直很激进,在开始 build 时,Chrome web store 已经不再接受 Manifest V2 extension ,Manifest V3 就是我们唯一的选择。

Manifest V3

Manifest V3 与之前的 V2 对比,有了不少的变化,对应到我们的 web extension 来说有下面这些改动:

  • Manifest V3 禁止执行任何的 remote script ,意味着所有的 script 必须在本地打包,即便是 gtm/ga 也需要下载到本地,然后打包进 extension
  • Background 从之前的 page 变成了 service worker ,意味着所有的与 DOM 相关的 API 都无法使用
  • host_permissions 从 permissions 拆分成单独的 field
  • Shortcuts must be explicitly defined in commands, otherwise the browser will not allow extension to get temporary activeTab permision

开发工具和框架

在过去的前端开发体验中,webpack 无论是开发还是打包所需要等待的时间都非常长。大型项目修改一小段代码,保存后都要等几秒才更新,打包则需要几分钟,甚至十几分钟。因此我们需要一个⚡快的工具来应对后续的开发。

Vite 开发的体验非常好,直接将转换后的 ES module 代码给支持的现代浏览器,让浏览器自己去加载依赖,并且一些最新的 ES 语法并不需要转换成旧的语法来兼容开发者的浏览器,这些都大大的节省了开发时间。Vite 非常快速且稳定,已经是我们新项目的首选。

框架上我们选择了 Vue 3 ,虽然我们已经有了非常丰富的 React 开发经验,但是我们还是想来尝试一下。Vue 3 + Pinia 配合 Typescript 相比于几年前 Vue 2 + Vuex 体验上几乎有了质的变化。某些场景上 Vue 的开发速度也比 React 要快不少。

浏览器兼容

Firefox 可能需要到今年年底才开始支持 V3 ,所以我们在完成 V3 之后,开始解决 V2 的兼容问题,出乎我们意料的是,这个过程异常的顺利。以下是我们遇到的需要额外处理的情况:

Manifest

我们定义了一个环境变量,这样在开发或者打包的时候可以区分不同的浏览器,从而生成不同的 manifest.json 文件。

if (process.env.FIREFOX) {
    delete manifest.action
    delete manifest.host_permissions

    manifest = {
        ...manifest,
        manifest_version: 2,
        permissions: [
            ...,
            '<all_urls>'
        ],
        background: {
            scripts: ['./dist/background/index.mjs'],
        },
        browser_action: {
            default_icon: {
                "32": "./assets/icon-512.png"
            },
            default_popup: "./dist/popup/index.html",
        }
    }
}

Canvas

Manifest V3 中 Background 不支持任何与 Dom 相关的 API ,因此在图片渲染上只能选择 OffscreenCanvas ,虽然 Firefox 号称支持这一 API ,但是在实际开发过程中,却无法在 Background page 中使用,也许是我们使用的姿势不对。

Clipboard

最后一个 Firefox 与 Chrome 浏览器不一致的地方就是 clipboard ,Firefox 不支持 ClipboardItem ,也就意味着不能使用 navigator.clipboard.write 将图片复制到 clipboard. 但是 Firefox 支持 browser.clipboard.setImageData 这个 Chrome 已经废弃的 API 。


总的来说,在开发 TinySnap web extension 没有遇到浏览器上太多的差异,并且在不考虑老旧浏览器的情况下,开发体验也比传统网页开发要轻松得多。在 Manifest V3 到 V2 的迁移过程中,我们也没有遇到太多的麻烦情况。