8000 feat(nuxt): render all head tags on server with `unhead` by harlan-zw Β· Pull Request #22179 Β· nuxt/nuxt Β· GitHub
[go: up one dir, main page]

Skip to content

feat(nuxt): render all head tags on server with unhead #22179

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

Merged
merged 11 commits into from
Jul 30, 2023

Conversation

harlan-zw
Copy link
Contributor
@harlan-zw harlan-zw commented Jul 17, 2023

πŸ”— Linked issue

resolves #22082
unjs/unhead#116

❓ Type of change

  • πŸ“– Documentation (updates to the documentation, readme or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

Currently, Nuxt users will modify their pages using useHead or nuxt.config appHead This appears to be stable and working well.

The Nuxt core itself though does not rely on this same API, instead opting for building head output using strings and hardcoding output ordering.

By migrating all head output to go through Unhead we get the following:

  • Full type safety
  • Tags can be ordered for for better performance (see Autosort <head> Β danielroe/nuxt-capo#36)
  • Gives end users and module authors more control over where tags end up and which they want to include (for example, pages with no scripts could easily be filtered out via a plugin hook)
export default defineNuxtPlugin({
  name: 'remove-scripts',
  enforce: 'pre',
  setup(nuxtApp) {
   // pretty much the same thing as NO_SCRIPTS logic in renderer.ts
    nuxtApp.ssrContext!.head.hooks.hook('tags:resolve', (ctx) => {
      ctx.tags = ctx.tags.filter(t => {
        if (t.tag === 'script')
          return false
        if (t.tag === 'link' && t.props.rel === 'modulepreload')
          return false
        return true
      })
    })
  }
})

This comes at a likely very small performance cost for SSR. A benchmark would be useful.

Performance Improvement

  • nuxt.config is only rendered server-side now, this should slightly improve the CSR time to interactive metric. This was already the behavior of SPAs.

⚠️ Slightly breaking changes

While these changes should be mostly safe, it will require a delicate eye over the migration to make sure I haven't omitted any previous tags or changed the order. I don't think it's safe to implement app-wide head re-ordering just yet.

  • Overriding the meta using ssrContext.renderMeta won't work anymore, afaik this was internal and shouldn't really be used in any production apps?
  • Using #head-static, shouldn't be used

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@harlan-zw harlan-zw changed the title feat(renderer): improved SSR head management using unhead feat(renderer): improved SSR head API using unhead Jul 17, 2023
@danielroe danielroe changed the title feat(renderer): improved SSR head API using unhead feat(nuxt): improved SSR head API using unhead Jul 18, 2023
@harlan-zw
Copy link
Contributor Author
harlan-zw commented Jul 20, 2023

Related: #21793

Will cause a conflict, should merge the other one first probably.

@danielroe
Copy link
Member

I was thinking this PR would close that one. But maybe I misunderstood?

@danielroe danielroe requested a review from pi0 July 21, 2023 09:53
@danielroe danielroe added this to the 3.7 milestone Jul 30, 2023
Copy link
Member
@danielroe danielroe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lovely.

@danielroe danielroe changed the title feat(nuxt): improved SSR head API using unhead feat(nuxt): render all head tags on server with unhead Jul 30, 2023
@danielroe
Copy link
Member

Just to add that in my testing, this is slightly faster than our existing implementation.

New approach (basic fixture)
Concurrency Level:      10
Time taken for tests:   289.765 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      53800000 bytes
HTML transferred:       51840000 bytes
Requests per second:    34.51 [#/sec] (mean)
Time per request:       289.765 [ms] (mean)
Time per request:       28.976 [ms] (mean, across all concurrent requests)
Transfer rate:          181.32 [Kbytes/sec] received
Old approach (basic fixture)
Concurrency Level:      10
Time taken for tests:   293.881 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      52830000 bytes
HTML transferred:       50870000 bytes
Requests per second:    34.03 [#/sec] (mean)
Time per request:       293.881 [ms] (mean)
Time per request:       29.388 [ms] (mean, across all concurrent requests)
Transfer rate:          175.55 [Kbytes/sec] received
New approach (minimal fixture)
Concurrency Level:      10
Time taken for tests:   4.232 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      7900000 bytes
HTML transferred:       6560000 bytes
Requests per second:    2362.97 [#/sec] (mean)
Time per request:       4.232 [ms] (mean)
Time per request:       0.423 [ms] (mean, across all concurrent requests)
Transfer rate:          1822.99 [Kbytes/sec] received
Old approach (minimal fixture)
Concurrency Level:      10
Time taken for tests:   5.401 seconds
Complete requests:      10000
Failed requests:        0
Total transferred:      7810000 bytes
HTML transferred:       6470000 bytes
Requests per second:    1851.51 [#/sec] (mean)
Time per request:       5.401 [ms] (mean)
Time per request:       0.540 [ms] (mean, across all concurrent requests)
Transfer rate:          1412.13 [Kbytes/sec] received

@danielroe danielroe merged commit 9b09b4d into main Jul 30, 2023
@danielroe danielroe deleted the feat/unhead-ssr-head-rendering branch July 30, 2023 18:46
@github-actions github-actions bot mentioned this pull request Jul 30, 2023
@ijkml
Copy link
Contributor
ijkml commented Jul 30, 2023

Awesome! πŸ™

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't order head tags after Nuxt head tags with tagPriority
3 participants
0