baetheus / deno-spa-example

An example of building a SPA with deno bundle

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Deno SPA Example

Deno has a builtin bundle command as well as typescript libs for dom and esnext. This repo shows a simple example of a deno-only build chain for a simple SPA. Additionally, it uses the lit-html import from esm.sh, some simple AsyncIterator tools from the functional library, and bmake.

Building, cleaning, and serving

There are make recipes for building this app. I use bmake but any posix-compatible make should work fine. This requires Deno 1.19+ to be installed, although I will eventually setup nix for this repo.

Build

bmake

This bundles the webapp to public/bundle.js.

Clean

bmake clean

This removes public/bundle.js.

Serve

bmake serve

This uses deno to serve all files from the public directory over port 4507.

Dev

bmake dev

This cleans, builds, and serves the app.

Files and their explanations

In order to create the simplest example of bundling a SPA and using Deno for dev tooling there are a few things that one must know.

Using a browser specific TypeScript configuration file (browser.json)

Here is a copy of browser.json, which is a very simple TypeScript configuration file.

{
  "compilerOptions": {
    "lib": ["dom", "esnext"],
    "strict": true
  }
}

In order for the types in lit-html to typecheck correctly we need to inform Deno that we are only using the dom and esnext types. By default, dom types conflict with the default deno.window types that Deno automatically loads. The dom lib gives us access to the document as well as various browser types like Node and Element that are used in lit-html. The esnext lib gives us access to language builtins like AsyncIterable and Object.hasOwn. Without these the deno bundle process will fail on type checking.

The Makefile command that bundles this SPA looks like this:

deno bundle --config browser.json src/main.ts > public/bundle.js

Importing the bundle.js in index.html

Rather than rely on cache-busting filenames like bundle-20220303.js I prefer to properly rely on etags and cache control headers, thus I don't find it necessary to mangle filenames. Because of this, building and bundling a SPA become much simpler.

Instead of using the compiler (as is done in Svelte, Angular, Next, etc) to generate or seed an index.html file, I find it much better to just have a static index.html file that imports a staticly named bundle (bundle.js). Along with proper webserver configuration this ensures that index.html can be cached well.

Future work

In the future I will either add to the Makefile to support additional features such as controlling build environment and seeding build-time date into an applicaiton or I will do the same in the context of a nix flake.

About

An example of building a SPA with deno bundle


Languages

Language:JavaScript 89.0%Language:TypeScript 8.5%Language:Makefile 1.7%Language:HTML 0.7%