make sure children is first in loader tree to fix head css bug on client navigation (#65279)

### What?

make sure children is first in loader tree to fix head css bug on client
navigation

### Why?

### How?

Fixes PACK-3028

---------

Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
This commit is contained in:
Tobias Koppers 2024-05-08 08:35:25 +02:00 committed by GitHub
parent 0edf4f951e
commit 84602cdf66
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 89 additions and 1 deletions

1
Cargo.lock generated
View file

@ -3061,6 +3061,7 @@ dependencies = [
"fxhash",
"getrandom",
"iana-time-zone",
"indexmap 1.9.3",
"lightningcss-napi",
"napi",
"napi-build",

View file

@ -69,6 +69,7 @@ anyhow = "1.0.66"
backtrace = "0.3"
fxhash = "0.2.1"
dhat = { workspace = true, optional = true }
indexmap = { workspace = true }
napi = { version = "2", default-features = false, features = [
"napi3",
"serde-json",

View file

@ -1,6 +1,7 @@
use std::{collections::HashMap, path::MAIN_SEPARATOR, sync::Arc};
use anyhow::{anyhow, Result};
use indexmap::IndexMap;
use napi::{
bindgen_prelude::External,
threadsafe_function::{ErrorStrategy, ThreadsafeFunction, ThreadsafeFunctionCallMode},
@ -42,7 +43,7 @@ async fn project_fs(project_dir: String, watching: bool) -> Result<Vc<Box<dyn Fi
#[serde(rename_all = "camelCase")]
struct LoaderTreeForJs {
segment: String,
parallel_routes: HashMap<String, ReadRef<LoaderTreeForJs>>,
parallel_routes: IndexMap<String, ReadRef<LoaderTreeForJs>>,
#[turbo_tasks(trace_ignore)]
components: ComponentsForJs,
#[turbo_tasks(trace_ignore)]

View file

@ -1018,6 +1018,14 @@ async fn directory_tree_to_loader_tree(
);
}
if tree.parallel_routes.len() > 1
&& tree.parallel_routes.keys().next().map(|s| s.as_str()) != Some("children")
{
// children must go first for next.js to work correctly
tree.parallel_routes
.move_index(tree.parallel_routes.len() - 1, 0);
}
Ok(Vc::cell(Some(tree.cell())))
}

View file

@ -0,0 +1,3 @@
export default function Page() {
return <main></main>
}

View file

@ -0,0 +1,3 @@
export default function Default() {
return null
}

View file

@ -0,0 +1,3 @@
#global {
background: rgb(0, 255, 0);
}

View file

@ -0,0 +1,16 @@
export default function Root({
children,
modal,
}: {
children: React.ReactNode
modal: React.ReactNode
}) {
return (
<html>
<body>
{children}
{modal}
</body>
</html>
)
}

View file

@ -0,0 +1,15 @@
'use client'
import './global.css'
import styles from './styles.module.css'
export default function Page() {
return (
<main>
<p id="global">Hello World</p>
<p id="module" className={styles.module}>
Hello World
</p>
</main>
)
}

View file

@ -0,0 +1,9 @@
import Link from 'next/link'
export default function Page() {
return (
<main>
<Link href="/">Link</Link>
</main>
)
}

View file

@ -0,0 +1,3 @@
.module {
background: rgb(0, 255, 0);
}

View file

@ -0,0 +1,19 @@
import { nextTestSetup } from 'e2e-utils'
describe('css-client-side-nav-parallel-routes', () => {
const { next } = nextTestSetup({
files: __dirname,
})
// Recommended for tests that need a full browser
it('should apply styles after navigation', async () => {
const browser = await next.browser('/source')
await browser.elementByCss('a').click()
expect(
await browser.elementByCss('#global').getComputedCss('background-color')
).toBe('rgb(0, 255, 0)')
expect(
await browser.elementByCss('#module').getComputedCss('background-color')
).toBe('rgb(0, 255, 0)')
})
})

View file

@ -0,0 +1,6 @@
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {}
module.exports = nextConfig