-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Postprocess inlined styles #41
Comments
Refs #41. This function we be changed to work synchronously and properly bundle the CSS file.
Took a pass at this with my current progress in The problem is that I see three paths forward which are all pretty rough:
Option 1. is probably the best as it makes the most logical sense, is the most performant, and doesn't pollute the user's code with extra boilerplate. Option 2. is awkward but not that bad IMHO, since a component should be simple enough to easily know what styles will be inlined. Option 3. is the most straightforward, but also the least performant since we'll be wasting a lot of time processing each and every CSS file only to actually use a small subset of them. For testing right now I'll go with option 3 since that is the easiest to implement. Simultaneously, I'll explore option 1. and see if it is feasible and if there's appetite to land it on the |
Asked in |
Tried to make option 3 workable and came up with We also run into an edge case where While option 3 is viable, it overcomplicates file resolution, encounters more edge cases in |
Coming back to this a few months later, postprocessing inlined styles is the most immediate issue in
For the first we have For the second, we would need to define some kind of Reflecting on the three possible solutions discussed earlier: The first (update The second (declare inlined styles on
The third approach (process all styles just in case they are inlined) is kind of a pain to implement with After feeling the pain of the third approach from prototyping and taking a another look at the second solution, I'm actually thinking number 2 might be the best path forward. I'll prototype that approach and see how well it works in practice. Global styles should be rare in reusable, isolated components, so most I may need to rename |
I prototyped the suggested modifications to option 2 in ref/inline-style-3 (yes I realize it's confusing that I prototyped each option in a different order than the options were numbered). I think this is actually a viable path forward. It has some interesting design decisions, but mostly seems to work. I added an This lead to a few interesting design decisions: Firstly, Secondly, speaking of strict deps, this has none. Thirdly, this will probably work with Sass, but I think it would require users to manually write Fourthly, I'm still not a fan of shipping my own version of Fifthly, I wrote everything with a new Sixthly, The next step here is to try to clean up this prototype into a complete branch and avoid introducing regressions. I think I'll start by introducing the new |
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Production-quality work (not experimental) is ongoing in |
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. This is to make room for a new `inlineStyle()` implementation which will be properly bundled.
Refs #41. Scope refers to how the CSS file is used. `Global` means that it applies to the entire page, while `Inline` means it is inlined into a particular location in the document and limited to any shadow DOM it might be under. Currently `includeStyle()` is considered global, while the new `inlineStyle()` will be inlined in its specified location.
Refs #41. These need to remain in the HTML so the resource injector knows where to inline each requested style. If they were removed from the HTML and put into the metadata configuration, then there would be no easy way to map each inline style to its position in the HTML.
Refs #41. The resource injector now processes the input HTML to look for any inline style annotations replaces them with a `<style />` tag containing the contents of the file.
Refs #41. The new `inlineStyle()` function looks equivalent to `inlineStyleLegacy()` from the user's perspective, however the key differences are: 1. `inlineStyle()` is synchronous and returns an annotation telling the build pipeline to inline the style here. `inlineStyleLegacy()` asynchronously read the CSS file and returned the actual `<style />` tag. This change makes the function easier to use (no viral `async`) and gives the build system an opportunity to bundle the inlined CSS file which wasn't available before. 2. `inlineStyle()` looks up the given import path in the "inline style map" and uses the result as the path in the output annotation. This map serves to correlate the import path users pass into `inlineStyle()` with the actual on disk location of the CSS file. These may not align as the latter could contain an artifact root, have a different file name, or even be in a different package altogether. The renderer receives this map in its arguments and `inlineStyle()` looks up this map so generated annotations use the real file path of inline styles, while users pass in the import path.
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. This is a multi-stage process which includes: 1. `prerender_component()` accepts inline style `css_library()` targets and compiles them to resolve all their `@import` statements. 2. `prerender_pages_unbundled()` takes the `CssImportMapInfo` provider from the compiled CSS target and passes it into the renderer which maps `inlineStyle()` calls to the correct file path of requsted CSS file. 3. Bundled inline styles are then propagated to the `multi_inject_resources()` target which actually injects the styles into the page at the inline style annotation. This is sufficient to use `@import` with an inlined style inside a declarative shadow root.
Refs #41. These should all work as expected and are fit to be used as public API. I didn't really expect `css_group()` to be public API, but `prerender_resources()` needs it as a direct dependency and is public API itself. It would be impractical to use inline styles with `prerender_resources()` without `css_group()`.
Refs #41. This uses inline styles with a `css_library()` library dependency chain in a declarative shadow root to demonstrate bundled inline styles.
Refs #41. See #41 (comment) for more info on the design of this ruleset. This includes rules for `css_library()` and `css_binaries()` along with supporting providers and rules. The core design here is that `css_library()` targets return a `CssInfo` provider which tracks direct and transitive sources. `css_binaries()` uses them to generate a bundled CSS file for every direct CSS source file of its direct `css_library()` dependencies. These bundled files have resolved all of their imports and inlined them. `css_binaries()` also provides a `CssImportMapInfo` which maps importable CSS file names to their actual file path on disk. This solves two problems: 1. Users shouldn't be writing artifact roots in their code, but the files actually being imported do have artifact roots and may exist in many configurations. 2. `css_binaries()` bundle source files from dependency `css_library()` targets which may exist in different packages. As a result, the generated bundle may not have the same root-relative path as the library file that the user wants to import. `css_group()` provides `filegroup()`-like semantics for merging multiple `css_binary()` targets into a single target with a cohesive `CssImportMapInfo` provider. I did my best to include tests for the major interactions between these rules, hopefully this should provide some reasonable confidence going forward.
Refs #41. This is a multi-stage process which includes: 1. `prerender_component()` accepts inline style `css_library()` targets and compiles them to resolve all their `@import` statements. 2. `prerender_pages_unbundled()` takes the `CssImportMapInfo` provider from the compiled CSS target and passes it into the renderer which maps `inlineStyle()` calls to the correct file path of requsted CSS file. 3. Bundled inline styles are then propagated to the `multi_inject_resources()` target which actually injects the styles into the page at the inline style annotation. This is sufficient to use `@import` with an inlined style inside a declarative shadow root.
Refs #41. These should all work as expected and are fit to be used as public API. I didn't really expect `css_group()` to be public API, but `prerender_resources()` needs it as a direct dependency and is public API itself. It would be impractical to use inline styles with `prerender_resources()` without `css_group()`.
Refs #41. This uses inline styles with a `css_library()` library dependency chain in a declarative shadow root to demonstrate bundled inline styles.
I was able to land an initial implementation and just published it in It's still called One interesting challenge I ran into was that using I think the next step is to rename I'll close this for now since the feature is shipped. I opened #47 to follow up with renaming |
Currently, CSS in declarative shadow DOM works via
inlineStyle()
, which has two critical problems:await
. The virality ofawait
means that any users must alsoawait
and it becomes a much more annoying API to use than one would expect. On top of this, forgetting toawait
does not surface as any kind of compile time or run time error:@import
statements are sent to the browser, where they will fail unless specifically served viaweb_resources()
. This prevents the header and footer components in thesite
example from using declarative shadow DOM.I think we should update this API to be synchronous and leave an HTML annotation rather than reading form the file system at all. The bundling process could extract this annotation, read the file, generate a bundle, and inject it back into the HTML at the correct location. This would avoid the
async
problems and fix@import
.The challenge here is the implementation. Once the annotation is extracted, we need to leave a marker of some kind about where the CSS should be injected back in. Line and column numbers aren't stable since the file gets modified, and we need to be deterministic. I think we could just leave another marker which counts sequentially and then generate a file which maps each location index to the CSS file being inlined. We've have to generate an entry point for each and compile each one, but I think it should be doable.
The text was updated successfully, but these errors were encountered: