Isomorphic (Reflected) Import Attributes Support #1216
Replies: 4 comments
-
One thing that should be taken into account here is that for extending this to non-standard types, like say our own for import styles from './some.css' with { type: 'raw' }; this could / would fail in certain host environments, like a browser. this seems to be corroborated when using Web Test Runner with a browser, as I'll see errors when attempting to use that syntax both in the terminal, and of course when debugging through the browser So perhaps Some links to ongoing discussions around this in the standards space to keep up with
In # 8, the topic of sending these attributes to the server also came up, which would be extremely valuable for our use case. 🥺 Not sure if we can get around this for local dev using es-module-shims and then re-write somehow for Rollup? |
Beta Was this translation helpful? Give feedback.
-
Interestingly in this PR, I noticed that in this PR where I had multiple sheets being used some actually didn't inline bundle? Taking this component for an example // source code
/* eslint-disable max-depth */
import { html, LitElement, TemplateResult } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { getEvents } from '../../services/events/events-service.ts';
import eventsCalendarSheet from './events-calendar.css' with { type: 'css' };
import themeSheet from '../../theme.css' with { type: 'css' };
@customElement('app-events-calendar')
export class EventsCalendarComponent extends LitElement {
static styles = [themeSheet, eventsCalendarSheet];
// ...
} https://deploy-preview-98--practical-fermat-fa2c48.netlify.app/events-calendar.2a50650b.js // output
import {t as e, s as t, x as a} from "./custom-element.89d57e7e.js";
import {n} from "./property.837b91b0.js";
import {o as r} from "./index.ec45f5c4.js";
import {a as s} from "./events-service.23790085.js";
import {s as i} from "./theme.1cbc327b.js";
const o = new CSSStyleSheet;
o.replaceSync(":host .as-events-calendar__header ...");
// ...
)(),
_.styles = [i, o], // i sheet is untouched!
c(_, A)
}
)(); So there is an example where something isn't being lined using |
Beta Was this translation helpful? Give feedback.
-
Was actually able to make some good progress on this in #1259 through a combination of a couple things:
In place of getting import attributes from the bundler, we know for sure which of these assets are bound for the browser, so we can differentiate one set of bundling as needed externalized assets for CSS / JS, where-as for SSR, we can simply shim it for the sake of interop. So I think with this and eventually #1218, I think we should have a decent enough solution here, that we can probably close this out. One random thought that came up was what if we could incorporate Greenwood's inlining optimization using this API? 🤔 import theme from '../styles/theme.css' with { type: 'css', optimization: 'inline' }; |
Beta Was this translation helpful? Give feedback.
-
Just a heads up for #1275 |
Beta Was this translation helpful? Give feedback.
-
Overview
Coming out of #923 (and the PR for it at #1215 ), there were a few lingering items that would be nice to resolve by the 2.0 version if possible, around the experience and expectations as it relates to using Import Attributes in Greenwood.
Use Case
Take for example this standard use case:
When used in a browser, the
type
value does not carry over to the server. The closest thing we can get from the client side is theSec-Fetch-Dest
header which, while it can provide some contextual clues around if the request is coming from a module or not (e.g.empty
), as far as I can tell there is no way currently for us to get any of the attributes used as part of aRequest
, which is a challenge primarily for resource plugins understanding if they should transform responses or not.For example, if I have a CSS file
Browser
In the browser I don't want any processing because for those browser it will get turned into a Constructable Stylesheet (
CSSStylesheet
) automatically.This is nice, because from Greenwood's perspective, we also don't have to worry about distinguishing from normal CSS files either, e.g.
Server / SSR (NodeJS)
On the server, for CSS for example, this needs be instrumented manually since Node will not do this automatically as it does not support CSS modules, e.g.
Although we're not using it now, NodeJS does provide use access to all the attributes via a
context
object when resolving within a custom loader script.Current Behavior
For this reason, the best that Greenwood can do is a couple things
(Un)Bundling / Native Formats
As it stands now, although the Rollup version we're on (
3.x
) seemingly already supports attributes syntax without needing a custom acorn plugin (it already supports assertions), and so for now we basically just do the same thing NodeJS does, which is we explicitly pass anAccept: text/javascript
header to all resource plugins as a hint to this special use case.the only issue we have is just what to do with say a CSS Module
But going forward, should we still inline it? Or say if we allowed Greenwood to be deployed unbundled, ship it as something like an asset like we do with
import.meta.url
+new URL
and just let the browser do all the work:Extension Inference (
?type=
Opt-Out query param)For this reason, the best that Greenwood can do is to infer the
type
value based on the extension which while not ideal, is at least a start. From there, if the URL / request does contain atype
query param, then Greenwood will ignore it and defer it to any plugins instead like the raw plugin, e.g.https://github.com/ProjectEvergreen/greenwood/blob/master/packages/cli/src/plugins/resource/plugin-standard-css.js
And so the new raw plugin would support the "legacy" behavior of getting any arbitrary file contents (e.g. CSS) back as a string
It also begs the question of a query param is the right option or even needed if we infer automatically? Maybe it could be a case-by-case basis per plugin, but not sure how you would do it any other way from the browser, e.g.
Where would the header go?
Outcomes / Goals
Basically, we need to figure out how to get / express import attributes via a browser request, or best way to infer and provide to a resource plugin so we can handle it best across runtimes / platforms
From there we can
4.x
(where custom acorn plugins were deprecated)<script>
tag though?Beta Was this translation helpful? Give feedback.
All reactions