expatfile/next-runtime-env

Support loading custom config files

Opened this issue · 4 comments

Thank you for this package it solves one consistent frustration I've had with Next.js!

We have a config file that gets written to the image at start up and we would like to make it available in the browser in the same way you have made the environment available. My idea is to add an additional public file __CONFIG.js that will add the config to the window and add a function config() that will return that config both client side and server side.

// __CONFIG.js

window.__CONFIG={"foo": "bar", "list":["foo", "bar"]}

Ideally this solution would support config files written in json, yml, js, or ts.

I've only looked into the v1.x.x implementation so far as we are still on the page directory, but I suppose we could do something similar with providers for v2.x.x.

If you're interested I would be happy to contribute this feature.

@nicklpeterson Thanks for the suggestion.

Would it be possible to:

  1. Create a utility that reads/parses the config file and save it to process.env.
  2. Run that util on server startup (like our makeEnvPublic) before configureRuntimeEnv.
  3. Then business as usual for accessing the variables.

What do you think?

I don't think that will quite work for our use case. The config is an object the contains nested objects and arrays, so it's not something we want to parse into environment variables. Additionally we have multiple apps, so we'd ideally like something that can take a generic json or js config file and make it available at runtime.

@nicklpeterson - That's fair.

We could create something on top of our script solution (v3). We're more than happy to collaborate on your initiative.

The general outline would be:

  • Parse a config file (and optionally configure its location.)
  • Expose the parsed file to the browser.
  • Provide a utility function (e.g. config()) that can read eighter for the window or from the process.

Looking forward to your input 🙂

@HofmannZ Yes - I think that would work!

Are you thinking the new functions would be something like this?

export interface ConfigScriptProps {
    filePath: string;
    nonce?: string;
}

export const ConfigScript: FC<ConfigScriptProps> = ({ filePath, nonce }) => {
  noStore(); // Opt into dynamic rendering

  // set nonce string (omitted for brevity)

  // This value will be evaluated at runtime
  const parsedConfig = config(filePath);

  return <Script
        nonce={nonceString}
        dangerouslySetInnerHTML={{
          __html: `window.__CONFIG__ = ${parsedConfig}`,
        }}
   />
};
export const config = (filePath?: string = DEFAULT_PATH) => {
     if (isBrowser()) {
          return window.__CONFIG__;
     } else {
         // attempt to read from cache 
         // if cache is empty read from the file path
         // parse and return object
     }
}