Assets
Widgets may use different external assets such as images (or even audio and video), WebAssembly files, custom resources, and so on. This section shows how to use some of the most common types of assets in a widget.
How assets are handled in WebWriter
When a widget is loaded into WebWriter (by installing a package), WebWriter bundles the package using esbuild
and imports the resulting bundle. This means that a widget may include any type of asset that esbuild
allows. Bundling is used again when the author saves the explorable, as all widgets are combined into a single, minimal bundle and the bundle source is embedded into the explorable.
JS
JS is the default asset type. It can be the entry point of your widget with "exports": {... "./widgets/my-widget": "./widgets/my-widget.js"}
configured in package.json
. Any files imported in your entry point are also bundled (this applies recursively) according to normal bundler behavior.
my-widget.js
import MySubComponent from "./mysubcomponent"
More details can be found in the esbuild documentation on JS.
TypeScript
TypeScript (TS) is a strongly typed language building on JS. In WebWriter, TypeScript has first-class support: A TypeScript file can also be an entry point with "exports": {... "./widgets/my-widget": "./widgets/my-widget.ts"}
, configured in package.json
. The same rules as for JS generally apply. Additionally, if your package includes a tsconfig.json
, it is used when bundling.
my-widget.ts
import MySubComponent from "./mysubcomponent"
More details can be found in the esbuild documentation on TypeScript.
JSX/TSX
JSX is a syntax for JS to create React elements with an XML-like syntax. Some component libraries, most prominently React, use this syntax.
More details can be found in the esbuild documentation on JSX.
JSON
JSON can be imported directly, as well. When a JSON file is imported, it is converted into a JS object at build time. This also applies to .jsonld
files.
my-widget.js
import config from "./config.json"
This means that you can also import the package’s package.json
if you want to reuse metadata you stored there for the widget.
More details can be found in the esbuild documentation on JSON.
CSS
The recommended way to include styles in a widget is to use a CSS-in-JS approach such as lit’s support for styles.
Alternatively, CSS files can be imported from JS/TS. This will generate a CSS bundle that WebWriter will import along with the widget. Note that the CSS will still not affect your component’s shadow DOM, so this is typically not what you want.
import "./mystyle.css"
More details can be found in the esbuild documentation on CSS.
Text
Any text file with the .txt
extension can be imported as a string.
import string from './myfile.txt'
console.log(string)
More details can be found in the esbuild documentation on text.
Media: Images, Icons, (Audio, Video)
Media assets can be imported in your JS/TS code. These assets are converted into a Base64-encoded data URI that can be used directly in any place a URI would be used.
The following file extensions are loaded as data URIs:
- Image:
.apng
,.jpg
,.jpeg
,.jfif
,.pjpeg
,.pjp
,.png
,.svg
,.webp
,.bmp
,.ico
,.cur
,.tif
,.tiff
- Audio:
.wav
,.wave
,.mp3
,.aac
,.aacp
,.oga
,.flac
,.weba
- Video:
.mp4
,.webm
,.avif
,.gif
,.mov
,.avi
,.ogv
,.mkv
,.opus
,.mpeg
- Font:
.woff
,.woff2
,.ttf
,.otf
- Document:
.pdf
Note that binary file types are loaded in Base64 encoding, while text formats such as SVG as loaded directly as text in the Data URI.
import myicon from "./myicon.svg"
@customElement("my-widget")
class MyWidget extends LitElement {
render() {
return html`<img src=${myicon}></img>` // if using Shoelace.js, <sl-icon src=${myicon}></sl-icon> also works
}
}
As shown in the example, this approach is most useful for using multiple small assets such as a set of icons for the widget.
Larger media assets such as most video and audio files are not intended to be part of a widget’s source. Since these assets would be bundled into every explorable that includes the widget, they would massively increase the widget’s size, and slow down both authoring and usage of the explorable.
WebAssembly
WebAssembly is not supported yet.
Other assets
Other types of assets are not directly supported. However, some other types of assets can be supported by adding a build step to your widget’s development. To achieve this, you need to convert/compile the unsupported asset type into one of the supported asset types.