elm-pages
elm-pages copied to clipboard
Pages should work correctly with redirects
If you use a redirect with a 200 status (for example, Netlify redirects), the page should work correctly. That means:
- Fetch the
content.json
file (with the StaticHttp data, etc.) from the correct URL - Links to other pages are correct
There are 3 different cases
- No redirects at all
- Redirect at the same level (i.e.
blog/hello
->post/hello
) - Redirect to a different level (i.e.
news/my-article
->archive/news/my-article
)
elm-pages
currently only works in case 1. In case 2, there is an issue that elm-pages
looks up metadata based on the path name. So if the path name has changed, it won't find it because the path it's looking for because it's looking for post/hello
but it's stored in the code under the path blog/hello
. This can be fixed by storing the path as part of the content.json
. It's case 3 that gets complicated with
Current issue with tags
You need to ensure that the content.json
file with all the StaticHttp data and page-specific data is fetched from the correct URL. We currently hard code looking at current/path/content.json
. But this breaks redirects. The more robust approach is to hard code the path to fetch the content.json
within the pre-rendered HTML. For example, you could encode doing a fetch of archive/news/my-article/content.json
, and pass that value in as a flag when initializing the Elm app. That URL will be accurate where the HTML page was served up with a redirect or not. So even if you view the page from the URL news/my-article
, it will find the content.json
file at the correct URL (no redirects needed to make sure it finds the content.json file).
This seems to be how GatsbyJS solves this problem, based on the preload tags that I see in their pre-rendered HTML. The links use absolute URLs to preload the page-data.json files.
The only way I can think of to robustly fetch content.json
files for a page, even if the page was originally loaded from a 200-redirect HTML page, is to hardcode these absolute URLs. If we used relative URLs, this would only work in case 2, but not in case 3. Is there another way around this using base tags, or is it worth considering finding a new strategy to replace the
Possible alternative to tags
GatsbyJS decided not to use
It seems like this could be a viable solution for elm-pages
as well, because we can apply that path prefix in all the relevant places:
-
ImagePath.toString
andPagePath.toString
(since we control how these are built with the code generation, we can simply add some context to include the path prefix in the generated code for these) - Fetching
content.json
files - Importing entrypoint JS and CSS files
- Do these need to be applied to URLs in the Manifest.json?
- Possibly others
This would take some work to wire this in, but I believe we control all the relevant places where we would need to change these URLs.
One possible downside: you would need to be explicit about the prefix whenever you build the project. However, this may not be a downside because you'll need to get this right in the canonical site URL anyway.
Possible benefits: anchor links don't work as people expect when used with
Looking for Feedback
This alternative to
@icidasset, do you have any opinions on this? I'd be very interested to hear what you think. Happy to discuss on a call some time.
Hey! I haven't used elm-pages in a while now, so my feedback might not that be that useful 😅
I'm not fully understanding the issue here.
If you redirect from blog/hello
to post/hello
, why do you say:
but it's stored in the code under the path blog/hello
Aren't the index.html
and content.json
files living at post/hello/*
then?
Why would you do redirect if that were not the case?
Aren't the index.html and content.json files living at post/hello/* then? Why would you do redirect if that were not the case?
Here's one use case that I'm setting up right now for the elm-radio.com site. I want to have a real URL like /16/elm-graphql
, so the title info is in the canonical URL. But I also want to be able to link to episodes by number, like /16
.
index.html
and content.json
live at /16/elm-graphql/*
. But if I do a redirect, I can't just redirect /16
-> /16/elm-graphql
. I would have to also set up a redirect for content.json. But that's a low-level detail, and also something that could change (could be a different file name or extension in the future). So if I set up the low-level routing rules for redirecting the content.json file, it could break in the future, and users wouldn't be able to easily set that up either.
The way a netlify redirect works, it's not like symlinking a directory, where it will reroute any files in that directory. Instead, it treats /16/elm-graphql
and /16/elm-graphql/content.json
as two separate things. So adding a redirect rule like this:
/16 /16/elm-graphql
Will result in redirecting the HTML file, but not the content.json
file in the same directory. You would need to set that up as a separate redirect rule for that to work. I hope that's more clear, it's a bit of a confusing scenario. Let me know if that's not making sense.
Thanks for the detailed explanation!
I thought the path of content.json
was determined by the path of the html (or the url path). But by reading your explanation, I assume that's not the case? If so, why not? The preload
for content.json
in html is relative to that html file, can't the HTTP request in Elm also be relative then? Also, everything else in the HTML is relative right?