'next build' not respecting publicPath property in webpack config

Viewed 19

I have a next.js project where I customize the webpack settings in next.config.js. I am setting a publicPath property as part of the output but when I later run npm run build which triggers a next build the links generated in the head of the index.html file do not have the publicPath prepended.

package.json:

{
  "name": "container",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "export": "next export",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "next": "12.3.0",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "devDependencies": {
    "@types/node": "18.7.17",
    "@types/react": "18.0.19",
    "@types/react-dom": "18.0.6",
    "eslint": "8.23.1",
    "eslint-config-next": "12.3.0",
    "typescript": "4.8.3"
  }
}

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  webpack: (config, options) => {
    const { dev } = options;
    if (!dev) {
      config.output = {
        ...config.output,
        publicPath: '/container/latest/',
      };
    }
    return config;
  },
};

module.exports = nextConfig;

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charSet="utf-8"/>
    <meta name="viewport" content="width=device-width"/>
    <title>container</title>
    <meta name="next-head-count" content="3"/>
    <link rel="preload" href="/_next/static/css/ab44ce7add5c3d11.css" as="style"/>
    <link rel="stylesheet" href="/_next/static/css/ab44ce7add5c3d11.css" data-n-g=""/>
    <link rel="preload" href="/_next/static/css/ae0e3e027412e072.css" as="style"/>
    <link rel="stylesheet" href="/_next/static/css/ae0e3e027412e072.css" data-n-p=""/>
    <noscript data-n-css=""></noscript>
    <script defer="" nomodule="" src="/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js"></script>
    <script src="/_next/static/chunks/webpack-b0082d3321e5f282.js" defer=""></script>
    <script src="/_next/static/chunks/framework-09a2284fdc01dc36.js" defer=""></script>
    <script src="/_next/static/chunks/main-017a64f48d901a37.js" defer=""></script>
    <script src="/_next/static/chunks/pages/_app-fcb935ebbac35914.js" defer=""></script>
    <script src="/_next/static/chunks/pages/index-a059660f80beee89.js" defer=""></script>
    <script src="/_next/static/tE04v1pZdHo3sCwUsPHpc/_buildManifest.js" defer=""></script>
    <script src="/_next/static/tE04v1pZdHo3sCwUsPHpc/_ssgManifest.js" defer=""></script>
  </head>
    <body>
      <div id="__next"><div class="Home_container__bCOhY"><main class="Home_main__nLjiQ"><p>Hello Next</p></main></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/","query":{},"buildId":"tE04v1pZdHo3sCwUsPHpc","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script>
    </body>
</html>

The script tags start with "/_next" but I expect then to start with "/container/latest/_next". Am I misunderstanding how this property works?

Everything works fine in development (obviously) but it breaks in production (because I am deploying to aws s3 and cloudfront and I create a 'folder' structure matching the publicPath above of '/container/latest/' to place the files from the 'out' directory created by running next export.)

1 Answers

I think this was my mistake. I should have used assetPrefix instead of trying to change webpack's publicPath property.

next.config.js:

/** @type {import('next').NextConfig} */
const isProd = process.env.NODE_ENV === 'production';

const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  assetPrefix: isProd ? '/container/latest/' : undefined,
  webpack: (config, options) => {
    // config webpack as required...
    return config;
  },
};

module.exports = nextConfig;
Related