vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.88k stars 26.97k forks source link

Static export `publicRuntimeConfig` issues #6249

Closed fikip closed 5 years ago

fikip commented 5 years ago

Bug report

Describe the bug

Hi, after upgrading from v7.0.2. to v8.0.0., I've been having issues running static export. After running next export, I get an error:

$ next export
> using build directory: /Users/fikip/Desktop/Projects/<project_name>/.next
  copying "static" directory
  copying "static build" directory
  launching 7 threads with concurrency of 10 per thread
TypeError: Cannot read property 'publicRuntimeConfig' of undefined

To be more specific, my publicRuntimeConfig in next.config.js is set up like this:

  publicRuntimeConfig: {
    API_URL: process.env.API_URL,
    SENTRY_URL: process.env.SENTRY_URL,
    SENTRY_SERVER_URL: process.env.SENTRY_SERVER_URL,
    VERSION: require("./package.json").version,
  }

Tracking down the error, it seems to occur here:

import getConfig from "next/config"
const { API_URL } = getConfig().publicRuntimeConfig

There have been no changes except updating next.js from v7.0.2 to v8.0.0.

I've noticed in the v8 release blog summary that

"publicRuntimeConfig and serverRuntimeConfig are not supported in the serverless mode. Use build-time configuration instead.", so that got me thinking that maybe setting target explicitly to server might help, but, alas, it did not.

To Reproduce

  1. Add a publicRuntimeConfig
  2. getConfig() somewhere in the app & access the publicRuntimeConfig object that should be returned
  3. Try to perform a static export
  4. See error

Expected behavior

Static export should finish without any errors.

Screenshots

image

System information

fikip commented 5 years ago

I've found a solution that helped in another (albeit not completely related) thread: https://github.com/zeit/next.js/issues/4024#issuecomment-377837421 Replace

const { API_URL } = getConfig().publicRuntimeConfig

with

const { publicRuntimeConfig = {} } = getConfig() || {}
const { API_URL } = publicRuntimeConfig

I'm not really clear on why this error started happening after the update. Is this the intended way I'm supposed to access publicRuntimeConfig in an app that is both statically served & dynamically served? Was it just 'luck' that it worked until now? 😄

timneutkens commented 5 years ago

I think this is a bug. Could you do me a favor and create a minimal github repository so that we can reproduce it faster when we start working on a fix 🙏

TheMaxoor commented 5 years ago

Here is a repo with the issue.

https://github.com/TheMaxoor/next-config-issue

garnerp commented 5 years ago

https://github.com/zeit/next.js/tree/canary/examples/with-universal-configuration-runtime

Its also failing when I try to do an export using the one from the example, when I add an export step.

dav-is commented 5 years ago

Fixed in 8.0.0-canary.24

tnunes commented 5 years ago

Thanks a lot for the fix! Any idea of when a 8.0.1 might be released?

timneutkens commented 5 years ago

Adding in a few more bugfixes. Most likely will do a new release today 👍

tnunes commented 5 years ago

Awesome, thanks! 🙏

NathanielHill commented 5 years ago

@bozskejkaja Your workaround would prevent errors, but I believe you will just have undefined values for all your environment variables if you export :thinking:

fikip commented 5 years ago

@NathanielHill You're absolutely right, it's definitely not an actual solution to the issue. In my case, it was a sufficient workaround since I'm not really using the env variables after statically exporting the app.

Luckily, it looks like the issue is already resolved in 8.0.1 that just got released 🎉

timneutkens commented 5 years ago

It's released as 8.0.1 👍

tnunes commented 5 years ago

Thanks again! 👌

kumarabhirup commented 5 years ago

Not working for me in Next v9

nik-john commented 5 years ago

I'm facing the same issue in Next v9 when trying to update my next.config.js webpack config:

require('dotenv').config();
const Dotenv = require('dotenv-webpack');
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = (config, { dev /* , isServer */ }) => {
  const { resolve } = config;
  /* If you update `modules`, make sure you also update 
  .eslintrc.js > settings > 'import/resolver' > node > moduleDirectory  */
  const modules = [...resolve.modules, __dirname];
  const extensions = [...resolve.extensions, '.js', '.jsx', '.react.js'];
  const mainFields = [...resolve.mainFields, 'browser', 'jsnext:main', 'main'];
  const plugins = dev
    ? [
        ...config.plugins,
        new Dotenv({
          path: path.join(__dirname, '.env'),
          systemvars: true
        })
      ]
    : config.plugins;
  return {
    ...config,
    resolve: {
      ...resolve,
      modules,
      extensions,
      mainFields
    },
    plugins,
    optimization: {
      minimizer: [
        new UglifyJsPlugin({
          uglifyOptions: {
            output: {
              comments: /@preserve/i
            }
          },
          extractComments: false
        })
      ]
    }
  };
};

Any idea why?

Sreilys commented 5 years ago

using Next v9 and this still works:

const { publicRuntimeConfig = {} } = getConfig() || {}; const { APP_NODE_ENV } = publicRuntimeConfig;

zhangciwu commented 4 years ago

I found that if you need it working for static pages, you need it set at build time, like:

API_IS_TEST=1 npm run build
eric-burel commented 4 years ago

Hi, I can repro in v9.4: https://github.com/VulcanJS/vulcan-next-starter/tree/bugfix/nextConfigStatic

git clone https://github.com/VulcanJS/vulcan-next-starter.git
git checkbout bugfix/nextConfigStatic
yarn run jest nextConfig # tests passes ok
DEBUG=next yarn run build:static # not OK

In the log you'll see the full config correctly computed. But in src/lib/i18n.ts, the getConfig() will return an object {serverRuntimeConfig: {}, publicRuntimeConfig: undefined}.

I keep exploring the issue, I have a complete setup with TS and Webpack so I am not sure where the problem happens.

Edit: I think I caught it, when the publicRuntimeConfig is an empty object, it gets scraped out and becomes undefined. If you just add yourConfig.publicRuntimeConfig = { foobar: true }, it is not scraped out and stays the same.

Quickfix is doing "publicRuntimeConfig || {}" when you get it but that's not intuitive. I can't find type definitions for getConfig either so we can't tell if this property is optional or not intuitively.

balazsorban44 commented 2 years ago

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.