Getting Started
This guide is intended for devs interested in making a SW proxy, not all information here is relevant to making a server-only proxy. We will teach you how to do it in a type-safe and effective matter. All historic methods will be documented, and alternatives, but the best will be recommended.
Why use a SW
Section titled “Why use a SW”As opposed to a server-only proxy:
- It takes the load off the server, so proxy sites that use your proxy can scale well. Remember, rewriters are heavy, and proxies before SW proxies used to handle requests synchronously; even if you handle them asynchronously, it will build up load in terms of memory, since it has to copy the AST trees and nodes in memory.
- It’s a native way to handle Requests and Responses, making it simple to fetch the request under a transport.
- You can get offline support if your SW proxy supports cache emulation.
- It’s easy to route and switch between other SW proxies.
As opposed to a sandboxed iframe proxy:
Glossary
Section titled “Glossary”- Regression-proofing - This refers to setting up effective tests to ensure that after tweaking modules in your SW proxy it is less likely to break on the next revision. You can do this by following our tips to make your proxy more safe, and implementing integration tests with the help of the testing doc.
Recommendations
Section titled “Recommendations”Package Manager
Section titled “Package Manager”PNPM is recommended. This will save space on your developer environment, and also help with caching on CI later, when you get to the Testing and CI document.
Annotation
Section titled “Annotation”It’s recommended that you annotate your public-facing APIs, typically for initializing your SW Proxy and controlling it from the client, with JSDoc.
Typescript is recommended, but provide your config example with JSDoc importing and typing your exposed config types in your package.
Type Building
Section titled “Type Building”Rslib is recommended, especially if you stick to the Rstack with using Rspack.
Build system
Section titled “Build system”Rspack is recommended, which is a modern, backwards-compatible, alternative to Webpack.
What you should know before starting out
Section titled “What you should know before starting out”Proxy Specs
Section titled “Proxy Specs”- BareMux - It’s very important to learn the BareMux APIs and how transports work, since this is how you will be fetching under the proxy.
Browser Features
Section titled “Browser Features”- Service Workers - You should also know that Service Workers are commonly referred to as “SWs”.
- Object data type
- ES6 Proxies
- DOM APIs
- Storage APIs
- Location APIs
- History APIs
Optional
Section titled “Optional”- Valibot - This is recommended for type-validating the message RPC of Client <-> SW.
- Workbox - Workbox will likely have no use in your SW proxy, but you should still learn it since proxy site devs, mostly webOS and PWA-powered offline proxy sites, will likely route your SW proxy with it.
Extras
Section titled “Extras”When you get to writing interceptors you will realize that there are many APIs you have to intercept. Assuming you have enough JS knowledge you should be able to learn from the web specs and explainer documents.
It’s best that you learn of APIs through explainers, and then delve deeper in web standards if you want to understand browser behavior. You would likely need web standards when you have to study how related browser features affect the web feature you are trying to implement, especially when you are trying to write emulation for a web feature; this is where you would usually need to read the intricate details of how APIs and browser features work.
Common explainer sources
Section titled “Common explainer sources”- MDN - This will be your primary source. These will contain guides, descriptions (guides, interfaces, properties), and browser compatibilty tables.
- web.dev - These articles, written by Google Devs, explain APIs in terms that make sense for the average web developer.
- Chrome Web Platform - These documents explain APIs, which only ship in Chromium at a time. These usually aren’t explained in the other sources. You should focus on APIs shipped on all majors browsers, before you delve into most of these, since they tend to be niche.
- Can I use - This site provides the most in depth compatibility. It shows table columns for more browsers, and shows when an API was adopted and removed after being deprecated. This may also be useful if there is not an MDN article written for it yet, but that is a rare occurance.
Building Controller APIs
Section titled “Building Controller APIs”It’s recommended that you build and publish types for these Controller APIs, and document those type declaration files with JSDoc.
Controller APIs should abstract the prefixed message-based APIs for your Service Worker, and handle the message RPC for you. This will make it easier for the proxy site developers to implement your Service Worker. You may also provide classes, which manage iframes, and abstract away navigation with URL encoding and history state proxification. They may also provide more complex behavior through event or method-based APIs on the class to create persistent userscripts to inject, register middleware, or reimplement browser features with emulation.
Building a configuration system for your proxy
Section titled “Building a configuration system for your proxy”The config should live on your SW and be dynamically configurable.
You can do this by:
- Making types for the config.
- Providing the config types in the builds and packages, preferrably documented with JSDoc.
- Initializing IndexedDB and creating object stores for the config. You may use idb to make this easier with a modern Promise-based API and schemas.
- Handling message RPC, so that on your client, being the proxy site, you can push new configs, which will then be persisted into the SW’s IndexedDB stores. Remember this is extra important, because SWs are suicidal. It is now your SW’s job to pass down the config into the injects into every new client of a proxified site, and expose the config as a global, so that your sandboxers can understand your current config at the time of the navigation.
- Providing an example config to make it easier for proxy site developers.