In-browser SDKs are a great way to bring your project to the web and simplify the way app developers access your services.
In fact, a number of large companies have built a library around their APIs this way.
Amazon, for example, lets developers build AWS services into their web apps using JavaScript code running in a browser. Facebook, Stripe and Twilio are all doing similar things.
At Microblink, most of our products now work in browsers. We wanted developers to be able to create simple, yet powerful experiences directly on the front-end of their web apps, and we wanted our end users to enjoy those experiences without having to ever leave their tab.
The biggest problem we faced with this goal was: all of our products require intense image processing on the device, something browsers couldn’t handle… until recently.
Tip #1: WebAssembly is the way forward if your code is compute-intensive
Once, all browsers could do is render pages. Today, they let you code, edit videos and play games inside them.
Much of this performance boost came with the widespread adoption of WebAssembly, a new web standard that runs alongside JavaScript to compile low-level code so that browsers can execute it faster. (1)
Because of its compact binary format, WebAssembly is ideal when you need to create native-like experiences on the web. In our case, that’s real-time data extraction with a hefty amount of artificial intelligence under the hood.
As you can see, WebAssembly is fast. The complex logic used to detect, recognize and read credit cards from a user’s video stream runs buttery smooth, despite the low-resolution feed from a laptop camera.
For our end users, this makes signing up or paying for something online as easy as scanning the data in – with the whole experience only a link away.
Apart from improved performance, compiling your code to WebAssembly brings us:
- Increased security: WebAssembly runs in a safe, sandboxed environment and is much more difficult to reverse-engineer than JavaScript because of its bytecode format.
- Accessibility and interoperability: WebAssembly has recently become the official World Wide Web Consortium (W3C) standard (just like HTML and CSS).
- Portability: WebAssembly can run outside of the browser as well, on a variety of operating systems and instruction set architectures.
The source code behind our SDKs is written in C++ but you can compile WebAssembly from Rust, Go, AssemblyScript, and many other languages, too.
Here’s a high-level look at what the process looks like. You’ll notice we’ve chosen Chrome to illustrate our point as it’s the browser of choice for roughly two-thirds of the world’s internet users. (2)
Still, we have to think about the remaining third. And that means developing with cross-browser compatibility in mind.
Tip #2: Deal with browser compatibility issues by progressively enhancing your SDK
Working with new browser APIs or technologies like WebAssembly will often cause some of your features to flop in certain browsers, either because they are blocked by something or not supported at all.
For example, calling WebRTC API to process real-time video in Chrome won’t work on any iPhone running iOS 14.2 or older because Apple’s WebView doesn’t support it.
Suppose you’re building a video conferencing SDK for the web. You now have a problem on your hands because iPhone users that haven’t updated their software in a few months won’t be able to join a meeting in anything but Safari.
We faced the same issue with WebRTC support and some of our users may not have a webcam to begin with. The way we got around this problem is the same way you approach any dead end: by taking a step back and reprioritizing.
Progressive enhancement in practice
In web development, progressive enhancement means you’re delivering essential features to everyone first while the more advanced functionality is available only to users of the most modern browsers.
We know that our core feature isn’t the scanning itself, but rather the data extraction that follows. We need to get an image of the document, but a user can simply upload one from the gallery instead of launching the webcam.
This basic functionality is something all of our users see. After we’ve covered the essentials, we check whether we can access the camera to actually scan the document.
It helps you if you map out your user journey from square one and determine what happens if and when a feature fails to load. Here’s how we’ve designed our flow prior to building the SDK:
Detecting whether a browser supports a feature
Before establishing a basic level of user experience, we need to know what features will and won’t be able to run across browsers.
To do that, you can either implement your own tests or use an existing library such as wasm-feature-detect by Google. We use it to load an appropriate WebAssembly bundle to our users at runtime, from most compatible to most performant. Here’s an example on how to check whether SIMD, one of WebAssembly features, is supported.
<script type="module">
import { simd } from "https://unpkg.com/wasm-feature-detect?module";
simd().then(simdSupported => {
if (simdSupported) {
/* SIMD is supported */
} else {
/* SIMD isn't supported */
}
});
</script>
Run a cross-browser test for each of your features, build workaround logic around the lack of support, and before you know it, you’ll be progressively enhancing your SDK.
Tip #3: Sidestep the dull work with metaprogramming
If you plan on building multiple SDKs (or even web apps) that share similar functionality, you may want to look into metaprogramming.
Metaprogramming is a technique in which a computer program treats other programs as its data. It lets you automate time-consuming and often tedious work by writing programs that themselves write programs.
As an example, our in-browser SDKs have similar architecture but solve entirely different problems. Metaprogramming helps us transform existing and even generate new JavaScript files for each SDK to:
- Generate boilerplate code from a single metarepository
- Add a new feature once and have it work everywhere
- Fix a bug in one place and change the unwanted behavior in all SDKs
- Change license keys in bulk, modify paths to WebAssembly files, etc.
We use two different metaprogramming techniques, depending on the scope of the changes that have to be made: template metaprogramming (TMP) and manipulation of abstract syntax tree (AST).
Template metaprogramming comes in handy when you need to generate multiple JavaScript files from a single, generic file.
Using ASTs to manipulate code is helpful in modifying existing source code files while sticking to their style and code structure.
We’ll take a closer look at how you can implement both of these techniques in a future blog post.
Browsers, the place to be
As browsers continue to evolve, we’re bound to see an increase in SDKs that will power simpler, more personalized experiences across the web.
Hopefully, the findings we’ve outlined above will help you build one of your own — with performance, accessibility and smart engineering in mind.
Enjoy working on amazing in-browser SKDs? Come work with us