Create framework to give first class support to 3rd party browser extensions
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Description
We have had a growing interest in creating features that integrate 3rd party services into GitLab's Frontend. For example:
Each of these services integrate some features into GitLab's UI. The current approach for supporting these is:
- Implement settings to allow user's to opt in to the feature
- Implement the Frontend features or add adapter code to load a browser extension
This approach has some drawbacks
- Code complexity. For some of our core features, we are starting to bake in the third party feature into our preexisting context. These can be a challenge to maintain.
- Coupling of third party extension to GitLab Frontend implementation details. Currently some third party features that extend the GitLab Frontend are coupled to certain implementation details or CSS classes to identify hooks for adding listeners or buttons.
- Performance. Every new bit of code we add increases the amount of code we send to the client and this hurts the overall runtime performance for every user (even if user's have a feature turned off, because we still have to check if they have it or not).
- Scope creep. The vision of the GitLab product is "A single application for the entire DevOps lifecycle". It seems a bit contrary to this scope to natively hook into separate applications for certain features.
Proposal
What if there was a way to make GitLab extensible without maintaining the inidividual extensions ourselves (and pushing them to every user's interface, potentially hurting usability)? Thankfully, this is already a solved pattern from many applications!
Instead of writing and maintaining all the individual extensions (or extension adapters) ourselves, what if we just write and provide a plugin framework that's exposed to the window object which browser extensions can hook into. This is very similar to how Visual Studio Code or other "extensible" applications work.
Okay Paul, but what does that look like?
For instance, with GitPod #228893 (closed), instead of us manually and explicitly placing a GitPod button everywhere (and needing to maintain the look and feel consistency without letting things get too noisy) we would expose something like window.GitLabPlugin.registerEditorButton(...) which a GitPod browser extension could simply call.
Okay Paul, but how does the browser extension know when to call it?
We can use the window messaging API to let extensions know that the page is ready:
window.addEventListener('gitlab.ready', () => {
GitLabPlugin.registerEditorButton({ ... });
});
Okay Paul, but how does the Frontend get values from the BE like "Sourcegraph URL"?
Rather than having separate config sections for each integration, we could have just one config for Frontend environment variables which is pushed to the Frontend (similar to how window.gon is):
window.addEventListener('gitlab.ready', () => {
GitLabPlugin.onBlobViewLoaded(blob => runSourcegraph(blob, GitLabPlugin.env.sourcegraph_url));
});
To summarize this proposal, instead of ad-hocing Frontend third-party extensions as needed and committing ourselves to maintaining each of these, let's create a "Plugin API" and just maintain that and provide third parties with safe and reliable integrations and users with more control of their environment.