Add CSS URL deployment ID suffix support#89771
Merged
Conversation
Collaborator
Tests Passed |
packages/next/src/build/webpack/loaders/css-loader/src/plugins/postcss-url-parser.ts
Outdated
Show resolved
Hide resolved
Merging this PR will not alter performance
Comparing Footnotes
|
Collaborator
Stats from current PR✅ No significant changes detected📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles: **437 kB** → **437 kB**
|
| Canary | PR | Change | |
|---|---|---|---|
| middleware-b..fest.js gzip | 758 B | 756 B | ✓ |
| Total | 758 B | 756 B | ✅ -2 B |
Build Details
Build Manifests
| Canary | PR | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 451 B | 449 B | ✓ |
| Total | 451 B | 449 B | ✅ -2 B |
📦 Webpack
Client
Main Bundles
| Canary | PR | Change | |
|---|---|---|---|
| 5528-HASH.js gzip | 5.47 kB | N/A | - |
| 6280-HASH.js gzip | 57 kB | N/A | - |
| 6335.HASH.js gzip | 169 B | N/A | - |
| 912-HASH.js gzip | 4.53 kB | N/A | - |
| e8aec2e4-HASH.js gzip | 62.5 kB | N/A | - |
| framework-HASH.js gzip | 59.7 kB | 59.7 kB | ✓ |
| main-app-HASH.js gzip | 256 B | 252 B | 🟢 4 B (-2%) |
| main-HASH.js gzip | 39.1 kB | 39.1 kB | ✓ |
| webpack-HASH.js gzip | 1.68 kB | 1.68 kB | ✓ |
| 262-HASH.js gzip | N/A | 4.53 kB | - |
| 2889.HASH.js gzip | N/A | 169 B | - |
| 5602-HASH.js gzip | N/A | 5.49 kB | - |
| 6948ada0-HASH.js gzip | N/A | 62.5 kB | - |
| 9544-HASH.js gzip | N/A | 57.7 kB | - |
| Total | 230 kB | 231 kB |
Polyfills
| Canary | PR | Change | |
|---|---|---|---|
| polyfills-HASH.js gzip | 39.4 kB | 39.4 kB | ✓ |
| Total | 39.4 kB | 39.4 kB | ✓ |
Pages
| Canary | PR | Change | |
|---|---|---|---|
| _app-HASH.js gzip | 194 B | 194 B | ✓ |
| _error-HASH.js gzip | 183 B | 180 B | 🟢 3 B (-2%) |
| css-HASH.js gzip | 331 B | 330 B | ✓ |
| dynamic-HASH.js gzip | 1.81 kB | 1.81 kB | ✓ |
| edge-ssr-HASH.js gzip | 256 B | 256 B | ✓ |
| head-HASH.js gzip | 351 B | 352 B | ✓ |
| hooks-HASH.js gzip | 384 B | 383 B | ✓ |
| image-HASH.js gzip | 580 B | 581 B | ✓ |
| index-HASH.js gzip | 260 B | 260 B | ✓ |
| link-HASH.js gzip | 2.49 kB | 2.49 kB | ✓ |
| routerDirect..HASH.js gzip | 320 B | 319 B | ✓ |
| script-HASH.js gzip | 386 B | 386 B | ✓ |
| withRouter-HASH.js gzip | 315 B | 315 B | ✓ |
| 1afbb74e6ecf..834.css gzip | 106 B | 106 B | ✓ |
| Total | 7.97 kB | 7.97 kB | ✅ -1 B |
Server
Edge SSR
| Canary | PR | Change | |
|---|---|---|---|
| edge-ssr.js gzip | 126 kB | 126 kB | ✓ |
| page.js gzip | 249 kB | 250 kB | ✓ |
| Total | 375 kB | 376 kB |
Middleware
| Canary | PR | Change | |
|---|---|---|---|
| middleware-b..fest.js gzip | 612 B | 616 B | ✓ |
| middleware-r..fest.js gzip | 156 B | 155 B | ✓ |
| middleware.js gzip | 33.3 kB | 33 kB | ✓ |
| edge-runtime..pack.js gzip | 842 B | 842 B | ✓ |
| Total | 34.9 kB | 34.6 kB | ✅ -269 B |
Build Details
Build Manifests
| Canary | PR | Change | |
|---|---|---|---|
| _buildManifest.js gzip | 733 B | 735 B | ✓ |
| Total | 733 B | 735 B |
Build Cache
| Canary | PR | Change | |
|---|---|---|---|
| 0.pack gzip | 3.84 MB | 3.85 MB | 🔴 +9.87 kB (+0%) |
| index.pack gzip | 104 kB | 104 kB | ✓ |
| index.pack.old gzip | 103 kB | 102 kB | ✓ |
| Total | 4.04 MB | 4.05 MB |
🔄 Shared (bundler-independent)
Runtimes
| Canary | PR | Change | |
|---|---|---|---|
| app-page-exp...dev.js gzip | 316 kB | 316 kB | ✓ |
| app-page-exp..prod.js gzip | 168 kB | 168 kB | ✓ |
| app-page-tur...dev.js gzip | 315 kB | 315 kB | ✓ |
| app-page-tur..prod.js gzip | 167 kB | 167 kB | ✓ |
| app-page-tur...dev.js gzip | 312 kB | 312 kB | ✓ |
| app-page-tur..prod.js gzip | 166 kB | 166 kB | ✓ |
| app-page.run...dev.js gzip | 312 kB | 312 kB | ✓ |
| app-page.run..prod.js gzip | 166 kB | 166 kB | ✓ |
| app-route-ex...dev.js gzip | 70.5 kB | 70.5 kB | ✓ |
| app-route-ex..prod.js gzip | 49 kB | 49 kB | ✓ |
| app-route-tu...dev.js gzip | 70.5 kB | 70.5 kB | ✓ |
| app-route-tu..prod.js gzip | 49 kB | 49 kB | ✓ |
| app-route-tu...dev.js gzip | 70.1 kB | 70.1 kB | ✓ |
| app-route-tu..prod.js gzip | 48.8 kB | 48.8 kB | ✓ |
| app-route.ru...dev.js gzip | 70.1 kB | 70.1 kB | ✓ |
| app-route.ru..prod.js gzip | 48.8 kB | 48.8 kB | ✓ |
| dist_client_...dev.js gzip | 324 B | 324 B | ✓ |
| dist_client_...dev.js gzip | 326 B | 326 B | ✓ |
| dist_client_...dev.js gzip | 318 B | 318 B | ✓ |
| dist_client_...dev.js gzip | 317 B | 317 B | ✓ |
| pages-api-tu...dev.js gzip | 43.2 kB | 43.2 kB | ✓ |
| pages-api-tu..prod.js gzip | 32.9 kB | 32.9 kB | ✓ |
| pages-api.ru...dev.js gzip | 43.2 kB | 43.2 kB | ✓ |
| pages-api.ru..prod.js gzip | 32.8 kB | 32.8 kB | ✓ |
| pages-turbo....dev.js gzip | 52.5 kB | 52.5 kB | ✓ |
| pages-turbo...prod.js gzip | 39.4 kB | 39.4 kB | ✓ |
| pages.runtim...dev.js gzip | 52.5 kB | 52.5 kB | ✓ |
| pages.runtim..prod.js gzip | 39.4 kB | 39.4 kB | ✓ |
| server.runti..prod.js gzip | 62.7 kB | 62.7 kB | ✓ |
| Total | 2.8 MB | 2.8 MB |
5cba3cc to
723b09f
Compare
mischnic
reviewed
Feb 11, 2026
…pack CSS `url()` references for images and fonts now include the `?dpl=<deployment_id>` suffix for skew protection. This applies to CSS modules, global CSS, and SCSS in both Turbopack and Webpack bundlers. Turbopack: Added `css_url_suffix` method to ChunkingContext trait, implemented in BrowserChunkingContext and NodeJsChunkingContext, and applied in resolve_url_reference. Webpack: Threaded deploymentId through the CSS loader pipeline from webpack-config through to postcss-url-parser where it's appended to asset URL hashes. https://claude.ai/code/session_01DE5Q9pRLpzjwbh7EnPiBTF
Place the dpl query parameter before the hash fragment in CSS url() references so it's a server-visible query parameter. Add missing sass dependency to the css-url-deployment-id test fixture.
Replace the separate `css_url_suffix` method on the ChunkingContext trait with a `static_suffix` field on the existing `UrlBehavior` struct. This unifies the dynamic (JS runtime) and static (CSS build-time) URL suffix mechanisms into a single configuration point, as suggested in code review. CSS URL resolution now calls `url_behavior(None)` and uses `static_suffix` instead of the removed `css_url_suffix()` method.
723b09f to
e6fa053
Compare
mischnic
approved these changes
Feb 11, 2026
ijjk
added a commit
that referenced
this pull request
Feb 11, 2026
Fixes deployment test failure from #89771 x-ref: https://github.com/vercel/next.js/actions/runs/21921362927/job/63302154502 ## Summary - update the SCSS `url-global` background-image assertion to allow optional query suffixes on emitted svg asset URLs - this handles deploy-mode URLs that include `?dpl=...` while keeping the existing path checks intact ## Verification - validated against deploy logs from failing job `63302154502`: URLs are correct and include `?dpl=...` - local run: `NEXT_SKIP_ISOLATE=1 NEXT_TEST_MODE=dev pnpm testonly test/e2e/app-dir/scss/url-global/url-global.test.ts` - `sass` case passed - `sass-embedded` case blocked locally by missing `sass-embedded` module in this environment
Collaborator
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
1 similar comment
Collaborator
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
mischnic
added a commit
that referenced
this pull request
Feb 13, 2026
This caused two requests and the preloading to not be effective at all #89771 added the dpl id in CSS for `url()`s
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Adds deployment ID suffix (
?dpl=<deployment_id>) to asset URLs referenced in CSSurl()declarations (images, fonts) for both Turbopack and Webpack builds. This enables proper cache busting for CSS-referenced assets when usingdeploymentIdinnext.config.js.Turbopack
static_suffixfield to the existingUrlBehaviorstruct, providing a build-time constant suffix for contexts that cannot use dynamic JS expressions (e.g., CSSurl()references)url_behavior(None)and usesstatic_suffixinstead of a separate methodnext.config.jsdeploymentIdthroughasset_suffix_path()into all three chunking contexts (client, server, edge) viadefault_url_behaviorandurl_behavior_overrideWebpack
deploymentIdthrough the CSS loader config pipeline (webpack-config.ts→config/index.ts→css/loaders/→postcss-url-parser.ts)?dpl=<id>to resolved asset URLs in the PostCSS URL parser plugin, placed before any hash fragment so it remains a server-visible query parameterTest
test/production/css-url-deployment-id/) covering global CSS, CSS modules, and SCSS modules with image and fonturl()referencesdplquery parameter in both Turbopack and Webpack modes