Skip to content

Commit

Permalink
fix: improve injectScriptsAt condition handling (#1857)
Browse files Browse the repository at this point in the history
Co-authored-by: Romuald Brillout <git@brillout.com>
  • Loading branch information
phonzammi and brillout authored Sep 7, 2024
1 parent b39160a commit 8c85511
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions vike/node/runtime/html/injectAssets/getHtmlTags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,15 @@ function getHtmlTags(
// ==========
// JavaScript
// ==========
// - The pageContext JSON should be fully sent before Vike's client runtime starts executing.
// - By default, we place the entry <script> towards the end of the HTML for better performance.
// - Performance-wise, it's more interesting to start showing the page (parse HTML and load CSS) before starting loading scripts.
// - But with HTML streaming, in order to support [Progressive Rendering](https://vike.dev/streaming#progressive-rendering), the entry <script> should be injected earlier instead.
// - The entry <script> shouldn't be `<script defer>` upon HTML streaming, otherwise progressive hydration while SSR streaming won't work.
// - `<script id="vike_pageContext" type="application/json">` (the `pageContext` JSON) should be fully sent before Vike's client runtime starts executing.
// - Otherwise, race condition "SyntaxError: Unterminated string in JSON": https://github.com/vikejs/vike/issues/567
// - <script id="vike_pageContext" type="application/json"> must appear before the entry <script> (which loads Vike's client runtime).
// - <script id="vike_pageContext" type="application/json"> can't be async nor defer.
// - The entry <script> can't be defer, otherwise progressive hydration while SSR streaming won't work.
// - The entry <script> should be towards the end of the HTML as performance-wise it's more interesting to parse <div id="page-view"> before running the entry <script> which initiates the hydration.
// - But with HTML streaming, in order to support [Progressive Rendering](https://vike.dev/streaming#progressive-rendering), the entry <script> should be injected early instead.
// - `<script id="vike_pageContext" type="application/json">` must appear before the entry <script> (which loads Vike's client runtime).
// - `<script id="vike_pageContext" type="application/json">` can't be async nor defer.
const positionJavaScriptDefault = 'HTML_END'
const positionJavaScriptEntry = (() => {
if (injectScriptsAt !== null) {
if (pageContext._pageContextPromise) {
Expand All @@ -143,19 +145,22 @@ function getHtmlTags(
{ onlyOnce: true }
)
}
if (injectScriptsAt === 'STREAM' && !isStream) {
return positionJavaScriptDefault
}
return injectScriptsAt
}
if (pageContext._pageContextPromise) {
// - If there is a pageContext._pageContextPromise then <script id="vike_pageContext" type="application/json"> needs to await for it.
// - pageContext._pageContextPromise is typically resolved only after the page's components are rendered and the stream ended.
// - https://vike.dev/streaming#initial-data-after-stream-end
return 'HTML_END'
return positionJavaScriptDefault
}
if (streamFromReactStreamingPackage && !streamFromReactStreamingPackage.hasStreamEnded()) {
// If there is a stream then, in order to support progressive hydration, inject the JavaScript during the stream after React(/Vue/Solid/...) resolved the first suspense boundary.
return 'STREAM'
}
return 'HTML_END'
return positionJavaScriptDefault
})()
if (pageContext._pageContextPromise && streamFromReactStreamingPackage) {
// - Should we show this warning for Solid as well? Solid seems to also support progressive rendering.
Expand Down

0 comments on commit 8c85511

Please sign in to comment.