Skip to content
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

Add Resource.Resources (and CSS output in js.Build) #12866

Closed
bep opened this issue Sep 20, 2024 · 2 comments
Closed

Add Resource.Resources (and CSS output in js.Build) #12866

bep opened this issue Sep 20, 2024 · 2 comments
Assignees
Labels
Milestone

Comments

@bep
Copy link
Member

bep commented Sep 20, 2024

While working on #12641 I'm creating a test/demo site "showcasing" all (or most) of the react-aria components. The "Vanilla CSS" starter pack imports CSS into the JS files. Hugo doesn't currently support that, but I know people have aske about it, so we might as well tackle it sooner rather than later.

ESBuild, the library we use for this, builds the CSS and returns them in the outputs slice (where the first item is the entry point JS). But it's up to the user to link it into the HTML.

What I suggest is something ala:

{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }}
{{ range $js.Resources.ByType "css" }}
<link href="{{ .RelPermalink }}" rel="stylesheet">
{{ end }}
<script src="{{ $js.RelPermalink }}"></script>

In the above, ESBuild does not need to know the URL to the CSS, a good thing, since we then are free to do fingerprinting etc. as we please.

Note to self that this may be a good time to clean up the rather ugly way we handle source maps, which is also in the outputs slice from ESBuild. One could imagine we would do:

{{ if hugo.IsDevelopment }}
  {{ range $js.Resources.ByType "map" }}
     {{ .Publish }}
  {{ end }}
{{ end }}

@cmahnke @jmooring does the above make sense?

@bep bep added the Proposal label Sep 20, 2024
@bep bep added this to the v0.135.0 milestone Sep 20, 2024
@bep bep self-assigned this Sep 20, 2024
@bep bep pinned this issue Sep 20, 2024
@bep bep changed the title Add Resource.Resources Add Resource.Resources (and CSS output in js.Build) Sep 20, 2024
@jmooring
Copy link
Member

jmooring commented Sep 20, 2024

First, page resources with extension css or js currently have a ResourceType of text. From the above, it looks like the ResourceType will be explicitly set to css. So there's some room for confusion here, i.e., "Why doesn't this work?"

content/
└── posts/
    └── post-1/
        ├── a.css
        ├── b.css
        └── index.md
{{ range .Resources.ByType "css" }}
  <link rel="stylesheet" href="{{ .RelPermalink }}">
{{ end }}

Do we need ByMediaType.Type, ByMediaType.MainType, and ByMediaType.SubType?

Second, it's unclear to me if the slice of returned resources in your example includes the JS. In other words, are these equivalent?

{{ range $js.Resources.ByType "javascript" }}
  <script src="{{ .RelPermalink }}"></script>
{{ end }}

<script src="{{ $js.RelPermalink }}"></script>

@bep
Copy link
Member Author

bep commented Sep 20, 2024

First, page resources with extension css or js currently have a ResourceType of text

Yea, right. We need to think about adding some more ways to filter these (I guess you could also use where), but I don't think that's the most important part of this.

{{ range $js.Resources.ByType "javascript" }}
  <script src="{{ .RelPermalink }}"></script>
{{ end }}

<script src="{{ $js.RelPermalink }}"></script>

That is a good question, and I thought about this. The output from ESBuild is a slice, but there's a implicit parent child relationship there that needs to be understood/handled, so I think that it makes sense to say that in:

{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }}
  • The $js Resource represents the js/main.js script, which may bundle other modules (either inline or via EMAScript imports (EMAScript imports does not support SRI by design, so we do not have to worry about that).
  • The Resources built that's not included/bundled in $js can be accessed in $js.Resources. This will be CSS, source maps etc.

So, I'm leaning against saying that a Resource may have a list of sub resources (not including itself), but I'm open to arguments against it ...

The alternate take, which would require us to create another func, is to return a Resources slice from js.Build2, but I'm not sure that would make things more clear ... Not sure.

@bep bep closed this as completed Sep 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants