studio
studio copied to clipboard
Extensions should be able to load static resources
As far as I can tell, there is no recommended way to bundle a static resource with an extension and reference it at runtime.
I can configure Webpack thusly to enable Asset Modules for things like images.
module.exports = {
webpack: (config) => {
config.module.rules.push({
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: "asset/inline",
});
return config;
},
};
The use of asset/inline here loads the whole image as a Base64-encoded data: URL that gets embedded into the DOM when I write,
import MyImage from "./images/foobar.png";
...
<img src={MyImage} />
But I don't think it's possible to use asset/resource which instead inserts the path of the file, like <img src="./images/foobar.png">, because the base URI to the extension is not exposed at runtime.
Is it maybe possible to have the extension loader prepend something like let __webpack_public_path__ = "..."; to the extension source code before executing it?
I spent an obscene amount of time toying with this and the solution described above does kind of work. See here: https://github.com/foxglove/studio/compare/main...rgov:rzg/extension-path
In my extension's Webpack config.ts I specify the asset/resource rule, and then before I import anything in my main file, I use
declare var __webpack_public_path__: string;
__webpack_public_path__ = (window as any).foobar;
(Why window.foobar? I had to figure out some way to smuggle the path into the scope that overrides __webpack_public_path__. I'm sure there is a more appropriate way to do this. Keep in in mind also that Webpack minifies the variable name so __webpack_public_path__ becomes something like __webpack_require__.p.)
A simpler way to do it, once the extension directory is plumbed through, is to set config.output.publicPath = "@FOXGLOVE_EXTENSION_PATH@" and have the ExtensionRegistryProvider use
const unwrappedExtensionSource = (await extensionLoader.loadExtension(extension.id))
.replace("@FOXGLOVE_EXTENSION_PATH@", `file://${extension.directory}/dist/`);
Except that this doesn't quite play well with the Content-Security-Policy; it seems to work fine when the app is built standalone but when running it in development mode, it doesn't want to load local resources. Perhaps you could implement a URL scheme like x-foxglove-extension://<extension.id>/resource.png instead.
From live discussion:
Problem statement
- monaco is hard to import in webpack (or at least we have no example of this working). here is how we do it in studio.
- importing theora ( https://github.com/brion/ogv.js ) with wasm binary is not working because it appears to expect the wasm blob to be available on a URL.
I created tickets to attempt examples for each of these
- https://github.com/foxglove/create-foxglove-extension/issues/68
- https://github.com/foxglove/create-foxglove-extension/issues/69