Skip to content

Commit

Permalink
content/issue 103 v0.30.0 release blog post (#118)
Browse files Browse the repository at this point in the history
  • Loading branch information
thescientist13 authored Nov 2, 2024
1 parent 0f6fdca commit 3b0ec3e
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 1 deletion.
Binary file added src/assets/blog/acorn.webp
Binary file not shown.
Binary file added src/assets/blog/greenwood-init-refresh.webp
Binary file not shown.
184 changes: 184 additions & 0 deletions src/pages/blog/release/v0-30-0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
---
title: Release - v0.30.0
abstract: Import Attributes are here in Greenwood! Learn more about them and other key highlights from this release.
published: 2024-11-02
coverImage: /assets/blog/acorn.webp
layout: blog
---

# Greenwood v0.30.0

**Published: Nov 2nd, 2024**

## What's New

<!-- <img src="/assets/blog/acorn.webp" style="display:inline-block; float: left; min-width: 100px; max-width: 10%; margin: 30px auto 10px; padding-right: 20px;" alt="Serverless function cloud"/> -->

In support of this latest release the Greenwood team would like to share some highlights with you, and top of the list for us is Import Attributes. Import Attributes are a powerful new web standard for loading non JavaScript files like CSS and JSON just by extending the standard ESM syntax. They work great with Web Components, or standalone. In addition, we want to showcase the HTML Web Components pattern, as well as introduce a new plugin to support CSS Modules ™️.

> Please refer to the [release notes](https://github.com/ProjectEvergreen/greenwood/releases/tag/v0.30.0) for a complete changelog and overview of breaking changes.
## Import Attributes

Although not implemented in [all browsers](https://github.com/web-platform-tests/interop/issues/733) (yet), **Import Attributes** are a [Stage 4 TC39 proposal](https://github.com/tc39/proposal-import-attributes) for extending ESM syntax to support additional module formats. [**CSS**](https://github.com/web-platform-tests/interop/issues/703) and [**JSON**](https://github.com/web-platform-tests/interop/issues/705) modules are already on the standards track, with [HTML Modules](https://github.com/WICG/webcomponents/blob/gh-pages/proposals/html-modules-explainer.md) possible in the future. For Greenwood, we have made support for CSS and JSON possible out of the box, with a [polyfill config flag](/docs/reference/configuration/#polyfills) for providing fallback behavior in the interim.

<!-- eslint-disable no-unused-vars -->

```js
// JSON is exported as an object
import data from "./data.json" with { type: "json" };

// CSS is exported as a Constructable StyleSheet
import sheet from "./styles" with { type: "css" };
```

<!-- eslint-enable no-unused-vars -->

For CSS, this works especially well with Shadow DOM based custom elements, as you can now author component styles in vanilla CSS files, and "adopt" them right into your Shadow roots. This same adoption technique can also be used to include any global "light DOM" styles, as you can adopt those too! So now you can finally share a global CSS theme file across both Light and Shadow DOM. Web standards ftw!

```js
import themeSheet from "../theme.css" with { type: "css" };
import componentSheet from "./header.css" with { type: "css" };

const template = document.createElement("template");

template.innerHTML = `
<header><!-- content goes here --></header>
`;

export default class Header extends HTMLElement {
connectedCallback() {
if (!this.shadowRoot) {
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}

this.shadowRoot.adoptedStyleSheets = [themeSheet, componentSheet];
}
}

customElements.define("x-header", Header);
```

> In the case of CSS Module Scripts, Greenwood will handle linking any CSS files used in an Import Attribute and also used in a `<link>` tag in your HTML (like our _theme.css_ in the example above), ensuring a single source of truth for those contents across both your HTML and your JS.
## HTML Web Components

As detailed in this excellent [blog post](https://blog.jim-nielsen.com/2023/html-web-components/), HTML Web Components are a strategy for leaning more into a less JavaScript dependent flavor of custom elements. Instead of (or in addition to) setting attributes, which would require JavaScript to do anything meaningful with from a content perspective, this options favors nesting the content as HTML. In this way, the custom element can be a nice styling wrapper or progressively enhanced experience on top. This also provides the benefit of playing nicely with CSS, which is global by default, as styling is not restricted by the encapsulation of the Shadow DOM. (think of it as a Light DOM [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_templates_and_slots), if you will.)

So instead of setting attributes:

```html
<picture-frame url="/path/to/image.png" title="My Image"></picture-frame>
```

You would want to "pass" HTML as children instead:

```html
<picture-frame>
<h3>My Image<h3>
<img src="/path/to/image.png" alt="My Image">
</picture-frame>
```

With a custom element definition like so:

```js
// CSS can be referenced from HTML, utility libraries, etc
export default class PictureFrame extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<div class="picture-frame">
${this.innerHTML}
</div>
`;
}
}

customElements.define("picture-frame", PictureFrame);
```

> This pattern works great when combined with Greenwood's [**prerendering**](/docs/reference/configuration/#prerender) and [static optimization](/docs/reference/configuration/#optimization) settings for a no-runtime, JS based, SSG build pipeline. Or combine with our CSS Modules ™️ plugin. What's our CSS Modules plugin, you ask? Keep reading. 👇
## CSS Modules

We are excited to share a [new plugin](/docs/plugins/css-modules/) we made to support [**CSS Modules ™️**](https://github.com/css-modules/css-modules). **_NOT_** to be confused with CSS Module _scripts_, which we covered at the start of this post, this plugin aims to be a modest implementation of [the specification](https://github.com/css-modules/icss). 🙂

With this plugin, create a standard CSS file that ends in _.module.css_:

```css
/* header.module.css */
.container {
display: flex;
justify-content: space-between;
}

.navBarMenu {
border: 1px solid #020202;
}

.navBarMenuItem {
& a {
text-decoration: none;
color: #020202;
}
}

@media screen and (min-width: 768px) {
.container {
padding: 10px 20px;
}
}
```

And reference that in your Light DOM based custom element:

```js
// header.js
import styles from "./header.module.css";

export default class Header extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<header class="${styles.container}">
<ul class="${styles.navBarMenu}">
<li class="${styles.navBarMenuItem}">
<a href="/about/" title="Documentation">About</a>
</li>
<li class="${styles.navBarMenuItem}">
<a href="/contact/" title="Guides">Contact</a>
</li>
</ul>
</header>
`;
}
}

customElements.define("x-header", Header);
```

From there, Greenwood will scope your CSS class names by prefixing them with the filename and a hash, and will then inline that content into a `<style>` tag in your HTML. It will also strip out the reference to the _module.css_ file from your calling file.

> This plugin works great when combined with Greenwood's [**prerendering**](/docs/reference/configuration/#prerender) and [static optimization](/docs/reference/configuration/#optimization) settings for JS based static HTML generation featuring scoped styles with no JS overhead.
## Honorable Mentions

The above highlights are by no means the only features delivered in this release, and so let's take a moment to check out some of the other capabilities and enhancements included in this release.

### Init Refresh

We gave the initial scaffolding output when running our `@greenwood/init` command a refresh. It now comes with some useful starter code and links to the website for common documentation resources. Try it out today using `npx @greenwood/init@latest my-app`!

![Greenwood Init Refresh](/assets/blog/greenwood-init-refresh.webp)

### Lit SSR Enhancements

In this release, we upgraded our Lit SSR plugin to support Lit v3 and addressed some bugs with our existing implementation. Checkout out the [plugin docs](/docs/plugins/lit-ssr/) for more info and check out our [demo repo](https://github.com/thescientist13/greenwood-lit-ssr) to see it all in action.

### Content as Data

We took on a pretty significant overhaul of the feature set related to leveraging the content of your Greenwood project programmatically as data, for creating things like navigation menus, content lists, and more. As of this release, we have deprecated our "menu" feature and replaced it with a more useful and general purpose "Collections" feature (that acts the same in principal), introduced a data client, and made enhancements to page data and frontmatter. Check out the [full docs](/docs/content-as-data/) to learn all about what's new.

---

As always, we're excited to see where the community can take Greenwood and are always available to chat on [GitHub](https://github.com/ProjectEvergreen/greenwood) or [Discord](https://discord.gg/pFbynPar). See you for the next release! ✌️
2 changes: 1 addition & 1 deletion src/pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ imports:
- ../styles/home.css
---

<app-latest-post link="/blog/release/v0-29-0/" title="We just released v0.29.0"></app-latest-post>
<app-latest-post link="/blog/release/v0-30-0/" title="We just released v0.30.0"></app-latest-post>

<app-hero-banner></app-hero-banner>

Expand Down

0 comments on commit 3b0ec3e

Please sign in to comment.