next.js: Next14. app router with custom sever cannot setAssetPrefix

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/vercel-next-js-reproduction-template-go8s7s

To Reproduce

  1. create a custom app server from next({ .... }) and express()
  2. when app server has prepared, app.setAssetPrefix(‘https://google.com’)
const app = next({ dev, hostname, port });
app.prepare().then(() => {
  const server = express();
  server.all("*", async (req, res) => {
    try {
      /** add prefix to assets */
      app.setAssetPrefix("https://www.google.com");
      await handle(req, res, parsedUrl);
    } catch (err) {
      res.statusCode = 500;
      res.end("internal server error");
    }
  });
  server.listen(port, () => {
    console.log(`> Ready on http://${hostname}:${port}`);
  });
});
image

Current vs. Expected behavior

Current: when i get ‘http://localhost:3000’, link scripts’s src was like ‘/_next/static/xxxxxx.js’ in the source code,

Expected : it should be like ‘https://google.com/_next/static/xxxxxx.js

Does Next 14 not support custom server setAssetPrefix in app router?

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 22.3.0: Mon Jan 30 20:39:46 PST 2023; root:xnu-8792.81.3~2/RELEASE_ARM64_T6020
Binaries:
  Node: 18.16.0
  npm: 9.5.1
  Yarn: N/A
  pnpm: 7.32.3
Relevant Packages:
  next: 14.0.2
  eslint-config-next: 14.0.0
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.3
Next.js Config:
  output: N/A

latest support version app router: 13.4.2 pages router: 13.4.12

Which area(s) are affected? (Select all that apply)

App Router Page Router

Additional context

No response

About this issue

  • Original URL
  • State: closed
  • Created 6 months ago
  • Reactions: 4
  • Comments: 20 (4 by maintainers)

Commits related to this issue

Most upvoted comments

flowing up

Actually @adanperez coming back to this it does seem like there are some links using the build time value of assetPrefix in next.config.js 🤔 - luckily we haven’t released anything yet as we were hoping for the setAssetPrefix to get patched.

@shaunwarman are you doing the following?

  • Make a production build with some string like/production for assetPrefix in next.config.js
  • Then when you run that prod build yarn start, use a different string for assetPrefix in next.config.js, something like /THIS_IS_A_TEST

When I do this I see a mix of of asset prefixes being used of both /production and /THIS_IS_A_TEST

image

This is the same behavior I see when using a custom server and using app.setAssetPrefix function.

I am using Next.js 14.0.4.

We are running into the same issue. When running a custom server, the build assets for app router pages are not using the asset prefix that is set at runtime with app.setAssetPrefix("./custom");. App router pages are only using the prefix setting that is set at build time in the app router page’s page_client-reference-manifest.js.

globalThis.__RSC_MANIFEST=(globalThis.__RSC_MANIFEST||{});globalThis.__RSC_MANIFEST["/page"]={"moduleLoading":{"prefix":"/some-other-url/_next/",

Overview

Seeing the same issues for anything after 13.2

Example repository setup. You can choose the branch as the nextjs version if you want to pull the repo down and test. I notice that next.config.js assetPrefix works, but setting it dynamically in code with a custom server is not working in later versions.

Repo link: https://github.com/shaunwarman/nextjs-setprefix-bug

Versions

13.2 (13.2.4)

https://github.com/shaunwarman/nextjs-setprefix-bug/tree/13.2

next.config.js assetPrefix - https://cdn.staticprefix.com/abc/123/ - ✅ working

Screenshot 2024-01-08 at 9 34 22 AM

dynamic app.setAssetPrefix - https://cdn.dynamicprefix.com/abc/123/ - ✅ working

Screenshot 2024-01-08 at 8 39 46 AM

13.3 (13.3.4)

https://github.com/shaunwarman/nextjs-setprefix-bug/tree/13.3

next.config.js assetPrefix - https://cdn.staticprefix.com/abc/123/ - 🛑 not working dynamic app.setAssetPrefix - https://cdn.dynamicprefix.com/abc/123/ - 🛑 not working

Error stack

TypeError: Cannot set properties of undefined (setting 'current')
    at prepareHostDispatcher (/Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/compiled/react-dom/cjs/react-dom-server.edge.development.js:1896:37)
    at createRequest (/Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/compiled/react-dom/cjs/react-dom-server.edge.development.js:8299:3)
    at /Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/compiled/react-dom/cjs/react-dom-server.edge.development.js:10126:19
    at new Promise (<anonymous>)
    at Object.renderToReadableStream (/Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/compiled/react-dom/cjs/react-dom-server.edge.development.js:10092:10)
    at /Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/server/node-web-streams-helper.js:195:117
    at NextTracerImpl.trace (/Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/server/lib/trace/tracer.js:86:20)
    at renderToInitialStream (/Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/server/node-web-streams-helper.js:195:37)
    at /Users/shaunwarman/Development/Source/my-app/node_modules/next/dist/server/app-render/app-render.js:937:92
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  page: '/'
}

13.4 (13.4.19)

https://github.com/shaunwarman/nextjs-setprefix-bug/tree/13.4

next.config.js assetPrefix - https://cdn.staticprefix.com/abc/123/ - ✅ working

Screenshot 2024-01-08 at 9 54 00 AM

dynamic app.setAssetPrefix - https://cdn.dynamicprefix.com/abc/123/ - 🛑 not working

Screenshot 2024-01-08 at 9 55 04 AM

14 (14.0.4)

https://github.com/shaunwarman/nextjs-setprefix-bug/tree/14.0

next.config.js assetPrefix - https://cdn.staticprefix.com/abc/123/ - ✅ working

Screenshot 2024-01-08 at 9 58 03 AM

dynamic app.setAssetPrefix - https://cdn.dynamicprefix.com/abc/123/ - 🛑 not working

Screenshot 2024-01-08 at 9 58 47 AM

Same happens to me starting from v13.5, it used to work perfectly fine until v13.4.7. Not relevant if app or page router, it doesn’t work for both. Following up and looking forward to have a fix in order to run the upgrade.

So our approach going forward looks like we’ll keep relative paths to static assets across all environments. We’ll keep our CDN sync mechanism to get assets to our CDN (origin) before a new version of the application is deployed. We’ll then have to map a proxy or rewrite rule at CDN, edge, router based on hostname (knowing what is production) and send <hostname>/_next/static/* -> <prod_cdn>/<some_static_namespace_to_map_to>/_next/static/*.

If you’re using vercel, you shouldn’t have to worry about this thanks to smarts in the routing during deployments to version correctly: https://vercel.com/blog/version-skew-protection

Following up and I tried old version to verify this feature. Finally , next@13.4.2 was the latest version support setAssetPrefix method in app router