gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
75.38k stars 7.49k forks source link

`hugo -w` detects template changes but doesn't rebuild usages of the template #12296

Closed KianNH closed 5 months ago

KianNH commented 7 months ago

What version of Hugo are you using (hugo version)?

$ hugo version
hugo v0.124.1-db083b05f16c945fec04f745f0ca8640560cf1ec+extended darwin/arm64 BuildDate=2024-03-20T11:40:10Z VendorInfo=brew

Does this issue reproduce with the latest release?

Yes.

What is the issue?

hugo -w will detect that a template has changed, but doesn't rebuild the pages that use it (leading to them still showing the old content).

To reproduce, the quickstart can be used. Add a page and a shortcode, i.e /content/hello.md and /layouts/shortcodes/hello.html.

/layouts/shortcodes/hello.html

Hello!

/content/hello.md

Testing: {{<hello>}}

Running hugo -w, there will be <p>Testing: Hello!</p> in /public/hello/index.html. Changing Hello! to Bye! in /layouts/shortcodes/hello.html will give you the following output from Hugo:

Change detected, rebuilding site (#1).
2024-03-22 13:17:12.022 +0000
Template changed /shortcodes/hello.html
Total in 46 ms

If we check /public/hello/index.html, it still says <p>Testing: Hello!</p>.

This is not an issue with hugo server, but our use-case is having Vite watch the /public/ directory and transform/serve the files for us so we rely on just hugo.

It can be worked around by just restarting the Hugo process if anything in /layouts/ changes, but I was wondering if it's a bug or expected behaviour.

jmooring commented 7 months ago

This works with v0.122.0 and earlier.

bep commented 7 months ago

Yea, I guess the hugo -w is ... undertested. I have never used that feature myself.

jmooring commented 7 months ago

Conceptually, since hugo server now renders to disk by default, are hugo server and hugo -w functionally equivalent?

KianNH commented 7 months ago

That's a good point! I did test hugo server as a replacement for hugo -w.

In the reproduction example, if I change /layouts/shortcodes/hello.html then /public/hello/index.html won't be rebuilt until I have accessed http://localhost:1313/hello/.

https://github.com/gohugoio/hugo/blob/27414d43a07026fe94f0e3c5ca3e69a4b1c8f2e4/hugolib/hugo_sites.go#L440-L444

That behaviour makes sense, but we use Vite which serves the files (and does some rewriting/transforms) so we don't access the files via the server that Hugo runs meaning when we make a change, files wouldn't be rebuilt. It's basically hugo -w and vite running concurrently, where vite watches the /public/ directory.

We can workaround the 'only rebuild opened pages' behaviour by using --disableFastRender to but the partial rebuilds introduced in 0.123.0 (which are awesome, great work!) made our development loop much quicker where only rebuilding the changed files was sub-100ms versus a full rebuild which is closer to 8-10 seconds.

bep commented 7 months ago

@KianNH try

hugo server --disableFastRender
KianNH commented 7 months ago

@KianNH try

hugo server --disableFastRender

That does work, but means that we miss out on the partial rebuild logic which is a big benefit for us since it makes the local development experience a lot nicer.

However, out of curiosity, I made a Vite middleware that fires off a mirrored request to Hugo's server. With this, we only really use Hugo's server in order to let Hugo know which pages we visited via Vite so that the recently visited logic works.

It's definitely a niche use-case, but this lets us continue using Vite whilst leveraging Hugo's partial rebuilds and fixes the issue with layouts not rebuilding that we have with hugo -w.

bep commented 7 months ago

That does work, but means that we miss out on the partial rebuild logic which is a big benefit for us since it makes the local development experience a lot nicer.

I'm not sure I follow. You still get "partial rebuilds", your just not getting "partial re-renderings".

The basic flow of a template change in Hugo is (in fast render mode):

  1. Determine what depends on that template and mark that for re-render.
  2. Then render the last n(5?) pages viewed in browser.

The second step gets really useful when you change a template used by "all" pages.

I don't remember how -w behaved re "fast renders" (as I said, never used it), but there's certainly no browser events to look at.

Well, this is a bug that needs fixing.

KianNH commented 7 months ago

That does work, but means that we miss out on the partial rebuild logic which is a big benefit for us since it makes the local development experience a lot nicer.

I'm not sure I follow. You still get "partial rebuilds", you're just not getting "partial re-renderings".

My confusion was from only testing --disableFastRender with templates, that's my bad!

I saw a full rebuild when changing templates but didn't test if changing content behaved differently, which does work as you describe.

If it's helpful, this is the difference in logs between hugo -w and hugo server --disableFastRender when editing a shortcode:

With hugo -w:

INFO  build:  step process substep resolve page output change set changes 1 checked 16634 matches 0 duration 15.431417ms
INFO  build:  step process substep gc dynacache duration 8.393708ms
INFO  build:  step process substep rebuild templates duration 7.913375ms
INFO  build:  step process duration 33.053792ms
INFO  build:  step assemble duration 83ns
INFO  build:  step render substep pages site en outputFormat html duration 1.949208ms
INFO  build:  step render substep pages site en outputFormat json duration 2.205667ms
INFO  build:  step render substep pages site en outputFormat rss duration 2.094792ms
INFO  build:  step render pages 0 content 0 duration 10.05775ms
INFO  build:  step postProcess duration 1.667µs
INFO  build:  duration 43.162583ms

With hugo server --disableFastRender:

INFO  build:  step process substep resolve page output change set changes 1 checked 8522 matches 6234 duration 23.630625ms
INFO  build:  step process substep gc dynacache duration 6.188125ms
INFO  build:  step process substep rebuild templates duration 9.721375ms
INFO  build:  step process duration 41.147292ms
INFO  build:  step assemble duration 208ns
INFO  build:  step render substep pages site en outputFormat html duration 6.303632333s
INFO  build:  step render substep pages site en outputFormat json duration 3.954458ms
INFO  build:  step render substep pages site en outputFormat rss duration 35.178125ms
INFO  build:  step render pages 3350 content 3346 duration 6.3485485s
INFO  build:  step postProcess duration 1.375µs
INFO  build:  duration 6.389746459s
KianNH commented 5 months ago

This fixed our issue perfectly - thanks @bep and @jmooring!

github-actions[bot] commented 5 months ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.