On This Page
Scripts
The page covers usage of JavaScript in Greenwood using all the standard browser conventions like <script>
tags, ESM, and npm. At build time, Greenwood will use your <script>
tags as entry points to be bundled and processed for a production deployment.
Script Tags
Script tags can be done in any standards compliant way that will work in a browser. So just as in HTML, you can do anything you need, like below:
<!doctype html>
<html lang="en" prefix="og:http://ogp.me/ns#">
<head>
<script>
alert("hello!");
</script>
<script src="../path/to/script.js"></script>
<script src="https://unpkg.com/...."></script>
</head>
<body>
<!-- content goes here -->
</body>
</html>
Modules (ESM)
Greenwood is ECMAScript Modules (ESM) first, as shown with the usage of the type="module"
attribute in the example below:
<!doctype html>
<html lang="en" prefix="og:http://ogp.me/ns#">
<head>
<script type="module" src="../path/to/script.js"></script>
</head>
<body>
<!-- content goes here -->
</body>
</html>
Keep in mind that the specification dictates the following requirements when referencing ESM files:
- It must be a relative specifier (starts with a
./
,../
, or/
) - It must have an extension
// happy panda
import { Foo } from "./foo.js";
// sad panda
import { Foo } from "./foo";
Node Modules
Packages from npm (and compatible registries) can be used by installing them with your favorite package manager. In the browser, Greenwood will automatically build up an import map so that you can use bare specifiers.
Below is an example of using a bare specifier in a JavaScript file:
// after having installed Lit
import { html, LitElement } from "lit";
class SimpleGreeting extends LitElement {
static properties = {
name: { type: String },
};
render() {
return html`<p>Hello, ${this.name ?? "World"}!</p>`;
}
}
customElements.define("simple-greeting", SimpleGreeting);
You can reference node_modules directly from a <script>
tag by starting the path with a "shortcut" alias of /node_modules/, which will signal to Greenwood to use import.meta.resolve
to automatically resolve the full path for you:
<html>
<head>
<!-- after having installed HTMX -->
<!-- npm i htmx.org -->
<script src="/node_modules/htmx.org/dist/htmx.js"></script>
</head>
<body>
<form hx-post="/api/greeting" hx-target="#greeting-output">
<!-- ... -->
</form>
</body>
</html>
Relative paths will also work in this context if you are comfortable resolving the full path to node_modules on your own, e.g.
<script src="../../node_modules/htmx.org/dist/htmx.js"></script>
Prerendering
If you have enabled prerendering and using Greenwood's default renderer (WCC), make sure that any custom elements you want prerendered have a default
export for their class
definition.
export default class Card extends HTMLElement {
connectedCallback() {
if (!this.shadowRoot) {
// ...
}
}
}
customElements.define("x-card", Card);