On This Page
Configuration
This section details all the supported configuration options available with Greenwood, which you can define in a greenwood.config.js file at root of your project.
Below is a greenwood.config.js file reflecting default values:
export default {
activeContent: false,
basePath: "",
devServer: {
extensions: [],
hud: true,
port: 1984,
host: "localhost",
},
isolation: false,
layoutsDirectory: "layouts", // e.g. ./src/layouts
markdown: {
plugins: [],
settings: {},
},
optimization: "default",
pagesDirectory: "pages", // e.g. ./src/pages
plugins: [],
polyfills: {
importAttributes: null, // e.g. ['css', 'json']
importMaps: false,
},
port: 8080,
prerender: false,
staticRouter: false,
workspace: new URL("./src/", import.meta.url),
};
Active Content
To enable support for Greenwood's Content as Data capabilities, set the activeContent
flag to true
.
export default {
activeContent: true,
};
Base Path
There are cases where an application might be deployed and hosted from a "sub" path that acts as the relative "web root". (GitHub Pages is an example of this)
So with a URL of http://www.example.com/app-a/, the basePath would be set as follows:
export default {
basePath: "/app-a",
};
This would then configure Greenwood's routing and <script>
/ <link>
tags to reference this segment automatically:
<script type="module" src="/app-a/some-script.a243dccss.js"></script>
For convenience, the value of basePath will also be made available as a global variable in the <head>
of your pages:
<script data-gwd="base-path">
globalThis.__GWD_BASE_PATH__ = "/app-a";
</script>
User content, like
<a>
and<img>
tags will still require manually prefixing thebasePath
in your application code.
Dev Server
Configuration for Greenwood's development server is available using the devServer
object, including the following options:
- extensions: Provide an array of extensions to watch for changes and reload the live server with. By default, Greenwood will already watch all "standard" web assets (HTML, CSS, JS, etc) it supports by default, as well as any extensions set by resource plugins you are using in your greenwood.config.js.
- hud: The HUD option (head-up display) is some additional HTML added to your site's page when Greenwood wants to help provide information to you in the browser. For example, if your HTML is detected as malformed, which could break the parser. Set this to
false
if you would like to turn it off. - port: Pick a different port when starting the dev server
- proxy: A set of paths to match and re-route to other hosts. Highest specificity should go at the end.
Below is an example configuration:
export default {
devServer: {
extensions: ["txt"],
port: 3000,
proxy: {
"/api": "https://stage.myapp.com",
"/api/foo": "https://foo.otherdomain.net",
},
},
};
Isolation Mode
If running Greenwood as a server in production with the greenwood serve
command, it may be desirable to isolate the server rendering of SSR pages and API routes from the global runtime process. This is a common assumption for many Web Component libraries that may aim to more faithfully honor the browser's native specification on the server.
Examples include:
- Custom Elements Registry - Per the spec, a custom element can only be defined once using
customElements.define
. - DOM Shims - These often assume a globally unique runtime, and so issues can arise when these DOM globals are repeatedly loaded and initialized into the global space
See these discussions for more information
As servers have to support multiple clients (as opposed to a browser tab only serving one client at a time), Greenwood offers an isolation mode that can be used to run SSR pages and API routes in their own context per request.
To configure an entire project for this, simply set the flag in your greenwood.config.js:
export default {
isolation: true, // default value is false
};
Optionally, you can opt-in on a per SSR page / API route basis by exporting an isolation
option:
// src/pages/products.js
export const isolation = true;
Layouts Directory
By default the directory Greenwood will use to look for your layouts is in layouts/. It is relative to your user workspace setting, just like the pages/ directory.
export default {
layoutsDirectory: "layouts", // Greenwood will look for layouts at src/layouts/
};
Markdown
You can install and provide custom unifiedjs presets and plugins to further customize and process your markdown past what Greenwood does by default.
For plugins, after installing their packages, you can provide their names to Greenwood:
export default {
markdown: {
settings: { commonmark: true },
plugins: ["rehype-slug", "rehype-autolink-headings"],
},
};
Optimization
Greenwood provides a number of different ways to send hints to Greenwood as to how JavaScript and CSS tags in your HTML should get loaded by the browser. Greenwood supplements, and builds up on top of existing resource "hints" like preload
and prefetch
.
Option | Description | Use Cases |
---|---|---|
default | Will add a preload link tag for every script or link tag in the head of your HTML, setting the preload attribute for styles and the modulepreload attribute for scripts. This setting will also minify all your JS and CSS files. | General purpose. |
inline | Using this setting, all your script and link tags will get inlined right into your HTML. | For sites with smaller payloads, this could work best as with inlining, you do so at the expense of long-term caching. |
none | With this setting, none of your JS or CSS will be minified at all. | The best choice if you want to handle everything yourself through custom Resource plugins. |
static | Only for script tags, but this setting will remove script tags from your HTML. | If your Web Components only need a single render just to emit some static HTML, or are otherwise not dynamic or needed at runtime, this will help ship unnecessary JavaScript to the client. |
Additional improvements and considerations include adding none override support, SSR + hydration, and side effect free layouts and pages.
Here is an example of setting the inline setting:
export default {
optimization: "inline",
};
Overrides
Additionally, you can apply overrides on a per <link>
or <script>
tag basis by adding a custom data-gwd-opt
attribute to your HTML. The following is supported for JavaScript and CSS.
<!-- Javascript -->
<script type="module" src="/path/to/file1.js" data-gwd-opt="static"></script>
<script type="module" src="/path/to/file2.js" data-gwd-opt="inline"></script>
<!-- CSS -->
<link rel="stylesheet" href="/path/to/file1.css" data-gwd-opt="inline" />
Pages Directory
By default the directory Greenwood will use to look for your local content is pages/. It is relative to your user workspace setting.
export default {
pagesDirectory: "docs", // Greenwood will look for pages at ./src/docs/
};
Plugins
This takes an array of plugins either created already by the Greenwood team, or one you made yourself.
import { greenwoodCssModulesPlugin } from "@greenwood/plugin-css-modules";
export default {
plugins: [greenwoodCssModulesPlugin()],
};
Polyfills
Greenwood provides polyfills for a few Web APIs out of the box.
Import Maps
Only applies to development mode.
If you are developing with Greenwood in a browser that doesn't support import maps, with this flag enabled, Greenwood will add the ES Module Shims polyfill to provide support for import maps.
export default {
polyfills: {
importMaps: true,
},
};
Import Attributes
Import Attributes, which are the underlying mechanism for supporting CSS and JSON module scripts, are not widely supported in all browsers yet. Greenwood can enable this in a browser compatible why by specifying which attributes you want handled. In both cases, Greenwood bundles these as ES Modules and will strip the attributes syntax.
export default {
polyfills: {
importAttributes: ["css", "json"],
},
};
In the case of CSS, Greenwood will inline and export your CSS as a Constructable Stylesheet
So given this usage:
import sheet from "./styles.css" with { type: "css" };
The fallback will become this:
const sheet = new CSSStyleSheet();
sheet.replaceSync(" /* ... */ ");
export default sheet;
For JSON, Greenwood will simply export an object.
So this usage:
// this
import data from "./data.css" with { type: "json" };
Will fallback to this:
export default {
/* ... */
};
Port
Unlike the port option for devServer
configuration, this option allows you to configure the port that your production server will run on when running greenwood serve
.
export default {
port: 8181,
};
Prerender
When set to true
Greenwood will prerender your site using WCC and generate HTML from any Web Components you include in your pages and layouts as part of the final static HTML build output.
export default {
prerender: true,
};
You can combine this with "static" components so that you can just do single pass rendering of your Web Components and get their output as static HTML and CSS at build time without having to ship any runtime JavaScript!
Static Router
⚠️ This feature is experimental. Please follow along with our discussion to learn more.
Setting the staticRouter
option to true
will add a small router runtime in production for static pages to prevent needing full page reloads when navigation between pages that share a layout. For example, the Greenwood website is entirely static, outputting an HTML file per page however, if you navigate from the Docs page to the Getting Started page, you will notice the site does not require a full page load. Instead, the router will just swap out the content of the page much like client-side SPA router would. This technique is similar to how projects like pjax and Turbolinks work, and like what you can see on websites like GitHub.
export default {
staticRouter: true,
};
Workspace
Path to where all your project files will be located, provided a valid URL
. Default is new URL('./src', import.meta.url)
relative to the project's root, where the greenwood.config.js file is located.
For example, to change the workspace to be www/:
export default {
workspace: new URL("./www/", import.meta.url),
};
Please note the trailing
/
here as for ESM, as paths must end in a/
for directories.