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

Experimental: Fast refresh feature in development #872

Merged
merged 25 commits into from
Apr 12, 2024

Conversation

jaredcwhite
Copy link
Member

This is an early WIP look (higher-quality refactored & tested code forthcoming!) at the fast refresh feature for faster reloading in development. I'll write up more detailed notes and some ideas for future TODOs, but in a nutshell:

  • In Fast Refresh mode, the logic will first look for the resource matching the file path of a changed file (which could be a page at a URL or it could be a data file)
  • If it doesn't find that, it then attempts to look for generated pages which came from resources initially (for paginated / prototype pages) and finds the original resource
  • Once found (if possible), either that resource is rebuilt directly (aka re-read, transformed, and written to disk) or any downstream generated pages are rebuilt.

But that's not where the real magic happens. What we ideally want is if you change Resource A, resources B, C, D, E, and F are also rebuilt along with Resource A because there's some sort of dependency there.

  • If you change the name of a person in _data/authors.yml, all of their blog posts should update.
  • If you change the title of a document, a sidebar with a list of those documents should update whichever pages include that sidebar.
  • If you update a description, page 4 in an archive somewhere should update with that new description.
  • etc.

Doing that is pretty challenging if you have to trace all those dependencies by hand (either under the hood automatically or with specific directives users must maintain). Thankfully…Signals to the rescue!

By placing resource data into Signals and transformation steps inside of Effects, we can observe which resources/generated pages Effects might get executed again when the data in certain Signals change—thereby assembling a dependency graph in real-time of which pages should be rebuilt. That way instead of only acting on a simple piece of source data and leaving that data stale on other parts of the site, or performing a full rebuild which can take a while (as was the case to date), we can instead only rebuild 5 pages or 10 pages or even 50 pages…but not 200! (Plus we also get to skip a lot of other slow code reloading paths and so forth.)

For the most part, this will require no changes to existing site repos. It'll "just work". But we do have a new mechanism in particular for handling site data which can prove quite interesting. Instead of reaching for site.data, reach for site.signals. All of the keys will be shortcuts for setting/getting signal values—aka site.signals.authors == site.signals.authors_signal.value and site.signals.authors.value = ... == site.signals.authors_signal.value = ... This means you can save and access site data through various plugins/templates and changes made to data files will propagate accordingly. This is enabled by some enhancements to Signalize::Struct which you can read more about here.

All of this serves to enable fast refresh paths in many cases shaving off several seconds on complex sites. And even on simple sites, sometimes I can make a change to a file and it's rebuilt so quickly that by the time I switch from my editor back over to the site it's already been refreshed. Booyeah!

More details coming…

@jaredcwhite jaredcwhite added this to the 2.0 milestone Mar 24, 2024
Copy link

render bot commented Mar 24, 2024

Copy link

render bot commented Mar 24, 2024

@jaredcwhite
Copy link
Member Author

Layouts, partials, and Ruby components are all fast-refreshing now. The list of cases where Fast Refresh can't happen is shrinking rapidly! 😲

@KonnorRogers
Copy link
Member

Layouts, partials, and Ruby components are all fast-refreshing now. The list of cases where Fast Refresh can't happen is shrinking rapidly! 😲

🎉 so excited! So cool!

@jaredcwhite
Copy link
Member Author

I spend some time today on gnarly code to see how I might handle taxonomy changes in fast refresh (aka your resource was in Category A but you change it to Category B), but after a lot of tearing my hair out I decided this is an abortable offense. So moving pages across categories/tags/etc. will trigger a full refresh…not the end of the world because I assume this happens very rarely (you might add taxonomy to a page right when you first author it, but likely not much if ever after that).

Perhaps down the road when I refactor Prototype/Paginated pages, there can be a new fast-refreshable path.

@jaredcwhite
Copy link
Member Author

I'm going to go ahead and merge this into main because it's already getting to be a bit of a monster. I'll file a series of follow-up issues for possible improvements, as well as adding documentation.

@jaredcwhite jaredcwhite merged commit 6e0751a into main Apr 12, 2024
3 checks passed
@jaredcwhite jaredcwhite deleted the fast-refresh-feature branch April 12, 2024 03:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants