How we built TinySnap: the anatomy of a browser extension
The story behind the birth of TinySnap.
Background
We understand there's a plethora of screenshot extensions on the Chrome Web Store. However, the core idea of TinySnap is to help creators, developers, and marketers improve their productivity. TinySnap is best suited for people obsessed with getting soulful stuff done efficiently. Our product comes with an in-built post-processing section and cloud synchronization. And in an ideal scenario, our users can snap a screenshot, annotate it, and share it with anyone quickly and easily.
As Leila Hock points out: “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.”
And that's why we built TinySnap.
Obviously, when it comes to building a browser extension, Google Chrome, which takes the #1 market share, is the primary option, and we will start from here.
Google Chrome is ambitious on web extensions, it no longer accepts Manifest V2 extension on building, so we have to start with Manifest V3.
Manifest V3
Compared to Manifest V2, Manifest V3 changed a lot. For us, it means:
Remote script
Remote script is not allowed to execute in Manifest V3, so all the scripts have to be bundled with the extension, even Google Tag Manager/Google Analytics has to be downloaded to local and bundled to the extension.
Background
Background was changed from background pages to service workers, which means all the DOM-related APIs do not work anymore.
Host permissions
host_permissions
was split from permissions
, and now it's a new field.
Shortcuts
Shortcuts must be explicitly defined in commands
, otherwise, the browser will not allow the extension to get temporary activeTab permission.
Technical stack we use
Based on our experience in front-end development, webpack takes a century to wait on both development and bundling. Ridiculously, a small change on a big project takes several seconds to refresh on save, and it takes minutes on bundling, so we desperately need a ⚡lightning-fast tool to replace it.
Vite gave us an awesome development experience, it directly sends the converted ES module code to supported browsers, allowing the browser to load dependencies by itself, and some of the latest ES syntaxes do not need to be converted into the old syntaxes to be compatible with developer's browser, which significantly saves our development time. Vite is very fast and stable and is already our first choice for new projects.
Even though we are experts in React, we chose Vue 3 as the framework, we want to give it a try for knowledge diversity. Vue 3 + Pinia + Typescript make us feel much better compared to Vue 2 + Vuex. In some scenarios, Vue is faster than React in development.
Browser compatibility
Firefox is said to support Manifest V3 by the end of 2022, so we got down to resolve the Manifest V2 compatibility issue after we completed the V3 part. To our surprise, the process went swift. Below is what we encountered that required additional handling:
Manifest
We defined an environment variable so that different browsers can be distinguished when developing or packing, thereby generating different manifest.json files.
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
Background
in Manifest V3 does not support any DOM-related API, so we have to choose OffscreenCanvas
for image rendering. Although Firefox claims to support this API, it cannot be used in the Background page in the actual development process. Maybe we didn't get it right.
Clipboard
Another difference between Firefox and Chrome is the clipboard. Firefox does not support ClipboardItem
, which means that navigator.clipboard.write
cannot be used to copy images to the clipboard. However, Firefox supports browser.clipboard.setImageData
, an API that Chrome has deprecated.
Overall, we didn't meet many difficulties while developing TinySnap, and the development experience was much easier than the traditional web development without having to consider those old browsers.