Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/next-api/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@
/// E.g. `/home/user/projects/my-repo`.
pub root_path: RcStr,

/// A path which contains the app/pages directories, relative to [`Project::root_path`], always

Check warning on line 156 in crates/next-api/src/project.rs

View workflow job for this annotation

GitHub Actions / rustdoc check / build

public documentation for `project_path` links to private item `Project::root_path`
/// Unix path. E.g. `apps/my-app`
pub project_path: RcStr,

Expand Down Expand Up @@ -1078,6 +1078,7 @@
no_mangling: self.no_mangling(),
scope_hoisting: self.next_config().turbo_scope_hoisting(self.next_mode()),
debug_ids: self.next_config().turbopack_debug_ids(),
inline_css: self.next_config().inline_css(),
}))
}

Expand Down
5 changes: 4 additions & 1 deletion crates/next-core/src/next_client/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ pub struct ClientChunkingContextOptions {
pub no_mangling: Vc<bool>,
pub scope_hoisting: Vc<bool>,
pub debug_ids: Vc<bool>,
pub inline_css: Vc<bool>,
}

#[turbo_tasks::function]
Expand All @@ -448,6 +449,7 @@ pub async fn get_client_chunking_context(
no_mangling,
scope_hoisting,
debug_ids,
inline_css,
} = options;

let next_mode = mode.await?;
Expand Down Expand Up @@ -481,7 +483,8 @@ pub async fn get_client_chunking_context(
.current_chunk_method(CurrentChunkMethod::DocumentCurrentScript)
.export_usage(*export_usage.await?)
.module_id_strategy(module_id_strategy.to_resolved().await?)
.debug_ids(*debug_ids.await?);
.debug_ids(*debug_ids.await?)
.inline_css(*inline_css.await?);

if next_mode.is_development() {
builder = builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ export function getClientStyleLoader({
isAppDir,
isDevelopment,
assetPrefix,
experimentalInlineCss,
}: {
hasAppDir: boolean
isAppDir?: boolean
isDevelopment: boolean
assetPrefix: string
experimentalInlineCss?: boolean
}): webpack.RuleSetUseItem {
const isRspack = Boolean(process.env.NEXT_RSPACK)
const shouldEnableApp = typeof isAppDir === 'boolean' ? isAppDir : hasAppDir
Expand Down Expand Up @@ -52,7 +54,7 @@ export function getClientStyleLoader({
return {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: `${assetPrefix}/_next/`,
publicPath: experimentalInlineCss ? '/' : `${assetPrefix}/_next/`,
esModule: false,
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function getGlobalCssLoader(
isAppDir: ctx.isAppDir,
isDevelopment: ctx.isDevelopment,
assetPrefix: ctx.assetPrefix,
experimentalInlineCss: ctx.experimental.inlineCss,
})
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function getCssModuleLoader(
isAppDir: ctx.isAppDir,
isDevelopment: ctx.isDevelopment,
assetPrefix: ctx.assetPrefix,
experimentalInlineCss: ctx.experimental.inlineCss,
})
)
}
Expand Down
Binary file not shown.
6 changes: 6 additions & 0 deletions test/e2e/app-dir/app-inline-css/app/font.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import localFont from 'next/font/local'

export const font = localFont({
src: './font-noto-sans.woff2',
variable: '--font-1',
})
4 changes: 4 additions & 0 deletions test/e2e/app-dir/app-inline-css/app/global.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
p {
color: yellow;
}

body {
font-family: var(--font-1);
}
3 changes: 2 additions & 1 deletion test/e2e/app-dir/app-inline-css/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Link from 'next/link'
import './global.css'
import { font } from './font'

export default function RootLayout({ children }) {
return (
<html>
<html className={font.variable}>
<body>
<nav>
<Link href="/" prefetch={false}>
Expand Down
11 changes: 10 additions & 1 deletion test/e2e/app-dir/app-inline-css/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import { font } from './font'

export default function Home() {
return <p>Home</p>
return (
<div>
<p>Home</p>
<p id="with-font" className={font.className}>
Text with custom font
</p>
</div>
)
}
41 changes: 41 additions & 0 deletions test/e2e/app-dir/app-inline-css/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,46 @@ describe('app dir - css - experimental inline css', () => {
expect(styleTags).toHaveLength(1)
expect(linkTags).toHaveLength(0)
})

it('should apply font styles correctly via className', async () => {
const browser = await next.browser('/')

const fontElement = await browser.elementByCss('#with-font')
const computedFontFamily = await fontElement.getComputedCss('fontFamily')

expect(computedFontFamily).toBeTruthy()
expect(computedFontFamily).not.toBe('Times')
})

it('should apply font styles correctly via CSS variable', async () => {
const browser = await next.browser('/')

const bodyElement = await browser.elementByCss('body')
const computedFontFamily = await bodyElement.getComputedCss('fontFamily')

expect(computedFontFamily).toBeTruthy()
expect(computedFontFamily).not.toBe('Times')
})

it('should inline font-face with absolute src URL', async () => {
const $ = await next.render$('/')

const styleTag = $('style')
expect(styleTag.length).toBeGreaterThan(0)

const styleContent = styleTag.html()
expect(styleContent).toMatch(/@font-face/)
expect(styleContent).toMatch(/font-family/)

const srcMatch = styleContent.match(/src:\s*url\(([^)]+)\)/)
expect(srcMatch).toBeTruthy()

const fontUrl = srcMatch[1].replace(/['"]/g, '')
expect(fontUrl).toMatch(/^\//)

const res = await next.fetch(fontUrl)
expect(res.status).toBe(200)
expect(res.headers.get('content-type')).toContain('font')
})
})
})
13 changes: 13 additions & 0 deletions turbopack/crates/turbopack-browser/src/chunking_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ impl BrowserChunkingContextBuilder {
self
}

pub fn inline_css(mut self, inline_css: bool) -> Self {
self.chunking_context.inline_css = inline_css;
self
}
Copy link
Contributor

Choose a reason for hiding this comment

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

and this


pub fn asset_root_path_override(mut self, tag: RcStr, path: FileSystemPath) -> Self {
self.chunking_context.asset_root_paths.insert(tag, path);
self
Expand Down Expand Up @@ -278,6 +283,8 @@ pub struct BrowserChunkingContext {
export_usage: Option<ResolvedVc<ExportUsageInfo>>,
/// The chunking configs
chunking_configs: Vec<(ResolvedVc<Box<dyn ChunkType>>, ChunkingConfig)>,
/// Whether CSS should be prepared for inlining
Copy link
Contributor

Choose a reason for hiding this comment

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

and this

inline_css: bool,
}

impl BrowserChunkingContext {
Expand Down Expand Up @@ -322,6 +329,7 @@ impl BrowserChunkingContext {
module_id_strategy: ResolvedVc::upcast(DevModuleIdStrategy::new_resolved()),
export_usage: None,
chunking_configs: Default::default(),
inline_css: false,
},
}
}
Expand Down Expand Up @@ -629,6 +637,11 @@ impl ChunkingContext for BrowserChunkingContext {
self.minify_type.cell()
}

#[turbo_tasks::function]
fn should_inline_css(&self) -> Vc<bool> {
Copy link
Contributor

Choose a reason for hiding this comment

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

This should really be something like

Suggested change
fn should_inline_css(&self) -> Vc<bool> {
fn should_use_absolute_url_references(&self) -> Vc<bool> {

Vc::cell(self.inline_css)
Copy link
Contributor

Choose a reason for hiding this comment

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

this is still wrong

}

#[turbo_tasks::function]
async fn chunk_group(
self: ResolvedVc<Self>,
Expand Down
5 changes: 5 additions & 0 deletions turbopack/crates/turbopack-core/src/chunk/chunking_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,11 @@ pub trait ChunkingContext {
MinifyType::NoMinify.cell()
}

#[turbo_tasks::function]
fn should_inline_css(self: Vc<Self>) -> Vc<bool> {
Vc::cell(false)
}

#[turbo_tasks::function]
fn async_loader_chunk_item(
&self,
Expand Down
2 changes: 2 additions & 0 deletions turbopack/crates/turbopack-css/src/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,14 @@ impl ProcessCss for CssModuleAsset {
Some(gsm) => gsm.generate_source_map(),
None => Vc::cell(None),
};
let inline_css = *chunking_context.should_inline_css().await?;
Ok(finalize_css(
process_result,
chunking_context,
minify_type,
origin_source_map,
this.environment.as_deref().copied(),
inline_css,
))
}
}
Expand Down
4 changes: 3 additions & 1 deletion turbopack/crates/turbopack-css/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ pub async fn finalize_css(
minify_type: MinifyType,
origin_source_map: Vc<OptionStringifiedSourceMap>,
environment: Option<ResolvedVc<Environment>>,
inline_css: bool,
) -> Result<Vc<FinalCssResult>> {
let result = result.await?;
match &*result {
Expand All @@ -293,7 +294,8 @@ pub async fn finalize_css(
let mut url_map = FxHashMap::default();

for (src, reference) in (*url_references.await?).iter() {
let resolved = resolve_url_reference(**reference, chunking_context).await?;
let resolved =
resolve_url_reference(**reference, chunking_context, inline_css).await?;
if let Some(v) = resolved.as_ref().cloned() {
url_map.insert(RcStr::from(src.as_str()), v);
}
Expand Down
14 changes: 10 additions & 4 deletions turbopack/crates/turbopack-css/src/references/url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,22 @@ impl ValueToString for UrlAssetReference {
pub async fn resolve_url_reference(
url: Vc<UrlAssetReference>,
chunking_context: Vc<Box<dyn ChunkingContext>>,
inline_css: bool,
) -> Result<Vc<Option<RcStr>>> {
let context_path = chunking_context.chunk_root_path().await?;

if let ReferencedAsset::Some(asset) = &*url.get_referenced_asset(chunking_context).await? {
let path = asset.path().await?;
let relative_path = context_path
.get_relative_path_to(&path)
.unwrap_or_else(|| format!("/{}", path.path).into());

return Ok(Vc::cell(Some(relative_path)));
let url_path = if inline_css {
format!("/{}", path.path).into()
} else {
context_path
.get_relative_path_to(&path)
.unwrap_or_else(|| format!("/{}", path.path).into())
};

return Ok(Vc::cell(Some(url_path)));
}

Ok(Vc::cell(None))
Expand Down
Loading