Assets

lazy js And js.toml

Bundle manifest-declared JavaScript libraries and hash readable app modules.

By Guillermo Alvarez - Published - Updated

Declare entrypoints

The default manifest is intentionally short:

[entrypoint.stimulus]
module = "@hotwired/stimulus"

Each [entrypoint.<name>] block declares one library bundle. module is the package import that esbuild bundles.

Run the pipeline

Run lazy js from the application module root:

lazy js

The command prepares missing package dependencies, chooses the package manager from active installed mise tools in this order: pnpm, yarn, bun, then node as npm, and runs that install through mise exec. If mise cannot provide one of those tools, it falls back to direct npm install. Then it bundles manifest entrypoints, writes readable content-hashed app/js modules, and writes:

app/public/assets/importmap.json
app/public/assets/lazyshaft/*.js

bundle.minify, shared chunks, source maps, and esbuild transforms apply to manifest-declared library bundles. App-owned files under app/js are not bundled or minified; app/js/app.js is only expanded for GoLazy directives before hashing.

Load by importmap

The layout loads the generated map before app code:

{{importmap "/assets/importmap.json"}}
<script type="module">import "app.js"</script>

The importmap maps stable browser imports to generated assets:

{
  "imports": {
    "@hotwired/stimulus": "/assets/lazyshaft/stimulus-FNW3RRR2.js",
    "app.js": "/assets/lazyshaft/app/app-ZWUSRUPQ.js"
  }
}

Use explicit browser import names

When the browser import name should differ from the bundled module path, set imports:

[entrypoint.monaco]
module = "monaco-editor/esm/vs/editor/editor.api.js"
imports = ["monaco-editor"]

Application code can then import the shorter name:

import * as monaco from "monaco-editor"

Include workers and assets

Some libraries load extra files dynamically. Declare them in the same entrypoint block:

[entrypoint.monaco]
module = "monaco-editor/esm/vs/editor/editor.api.js"
imports = ["monaco-editor"]
workers = [
  "monaco-editor/esm/vs/editor/editor.worker.js",
]
assets = [
  "node_modules/monaco-editor/min/vs/**/*",
]

Workers are bundled as extra JavaScript outputs. Assets are copied into the lazyshaft output directory.

Commit outputs

Commit generated assets and package metadata:

js.toml
package.json
package-lock.json
app/js/**/*.js
app/public/assets/importmap.json
app/public/assets/lazyshaft/*.js

Do not commit node_modules.