Build for the browser
The @bundles
plugin
For most of your browser needs you can use Enhance’s built-in browser pattern but at times you may have a component that has special imports like css-in-js
that requires the abilities of ESBuild. In these situations you can use plugin-bundles to make your component available to the browser.
Install
npm i @architect/plugin-bundles
Add the plugin and the components you want to bundle to your .arc file
@plugins
architect/plugin-bundles
@bundles
autocomplete '/utils/autocomplete.mjs'
Basic Example
If you have written a bit of JS for your app that has an external dependency, you’ll likely want to bundle your script with its dependency.
Let’s use Algolia’s autocomplete as an example.
import { autocomplete } from '@algolia/autocomplete-js'
addEventListener('DOMContentLoaded', () => {
autocomplete({
container: '#autocomplete',
// ...
})
})
Assuming this file is located at /utils/autocomplete.mjs
, update your .arc
file (adding the @bundles
line if needed) with this entry:
@bundles
autocomplete '/utils/autocomplete.mjs'
The bundled asset will now be available at /_public/bundles/autocomplete.mjs
and can be imported or referenced in a script tag.
<script type="module" src="/_public/bundles/autocomplete.mjs">
Multi-file Source to Single Bundle
If your project grows to a certain size, it can be beneficial to extract Web Component definitions (that is JS classes that extend HTMLElement
) from their source in /app/elements/
into a common place.
For this example, we’ll create an arbitrary directory outside of app/
called components/
and place a couple classes there with an index file:
.
├── .arc
├── app/
└── components/
├── todo-list.mjs
├── todo-item.mjs
└── index.mjs
The index file works as a manifest, exporting all requirements:
export { default as TodoList } from './todo-list.mjs'
export { default as TodoItem } from './todo-item.mjs'
We’ll update our .arc
file, adding @bundles
if it’s not already present:
@bundles
todos '/components/index.mjs'
These classes can now be imported as needed.
import { TodoList, TodoItem } from '/_public/bundles/todos.mjs'
Bundling External Modules
You may want to install an external dependency for use in the browser.
Enhance @bundles
handles this, as well.
Example: wc-toast
wc-toast
provides a nice custom element definition and accompanying API for creating alert messages in an application. We’ll install it as a project dependency:
npm i wc-toast
The wc-toast
project ships with a nice entry point for a bundle. We will bundle and expose wc-toast
’s main index file as “wc-toast” by updating .arc
with:
@bundles
wc-toast './node_modules/wc-toast/src/index.js'
The name “wc-toast” can be anything you’d like, but we prefer to stick as close to the source library’s name as possible.
Now, we’re able to import bundle, or a named export in this case, from the /_public/bundles/
endpoint:
import { toast } from '/_public/bundles/wc-toast.mjs'
TypeScript Web Components
With the @bundles
feature, you can write browser code with TypeScript.
It is automatically converted to browser compatible JavaScript and served to the client.
Example .ts
Definition
Imagine we have a simple Web Component definition that lives in a components/ folder in our project root:
export class TodoItem extends HTMLElement {
public label: string;
public completed: boolean;
checkbox: HTMLInputElement | null;
constructor() {
super();
this.label = this.getAttribute("label") || "";
this.completed = typeof this.getAttribute("completed") === "string";
this.checkbox = this.querySelector("input");
}
public static get observedAttributes(): string[] {
return ["label", "completed"];
}
}
customElements.define("todo-item", TodoItem);
This example doesn’t do a whole lot yet, but it’s a good starting place.
To have our todo-item.ts
transpiled and served to our front end, just give it a name and a path in the project’s .arc
file:
@bundles
todo-item /components/todo-item.ts
Now it can be imported from your custom element or with a script tag:
import TodoItem from '/_public/bundles/todo-item.mjs'
<script type="module" src="/_public/bundles/todo-item.mjs">