Next JS и переменные окружения - получение значений на стороне клиента - PullRequest
0 голосов
/ 23 января 2020

Я прошу прощения, если на этот вопрос уже был дан ответ, но я бьюсь головой об стену с чем-то, что должно быть просто ....

Мой проект работает в режиме server. Нам нужно иметь возможность передавать переменные окружения в время выполнения и иметь их в наличии на и на стороне сервера и на стороне клиента

Я использую publicRuntimeConfig подход, описанный в документах , и я ничего необычного не сделал (код, который следует соблюдать)

Проблема заключается в том, что при работе в режиме разработки (yarn dev) все работает как ожидается, но когда я собираю проект и докеризирую его (или перемещаю в kubernetes для развертывания), он работает неправильно.

Вот код: next.config.js

const nextConfig = {
  publicRuntimeConfig: {
    PARAM_A: process.env.PARAM_A || "defaultA",
    PARAM_B: process.env.PARAM_B || "defaultB"
  }
};

module.exports = nextConfig;

_app.tsx

import React from "react";
import App, { AppContext } from "next/app";
import Head from "next/head";
import { Menu } from "../src/components/menu";


class CustomApp extends App {
  static async getInitialProps({ Component, ctx }: AppContext) {
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
      console.log("[_app.tsx] pageProps", pageProps);
    }

    return { pageProps };
  }

  render() {
    const { Component, pageProps } = this.props;

    return (
      <>
        <Head>
          <title>Testing Area</title>
        </Head>
        <Menu />
        <Component {...pageProps} />
      </>
    );
  }
}

export default CustomApp;

index.tsx, otherpage.tsx и help.tsx идентичны, кроме их формулировок, поэтому для экономии места я только опишу index.tsx:

import React, { Component } from "react";
import getConfig from "next/config";
import { NextPageContext } from "next";

class Index extends Component {
  static async getInitialProps(ctx: NextPageContext) {
    const nextConfig = getConfig();
    const clientConfig = (nextConfig && nextConfig.publicRuntimeConfig) || {};
    const settings =  Object.keys(process.env).length > 1 ? process.env : clientConfig;
    console.log("[INDEX PAGE] - nextConfig", nextConfig);
    console.log("[INDEX PAGE] - clientConfig", nextConfig.publicRuntimeConfig);
    console.log("[INDEX PAGE] - settings", settings);
    console.log("[INDEX PAGE] - process.env", process.env);

    return { settings };
  }

  render() {
    return <div>INDEX Page</div>;
  }
}

export default Index;

Когда я запускаю yarn dev, вывод в инструментах разработчика браузера для этой строки console.log("[INDEX PAGE] - nextConfig", nextConfig); будет таким, как ожидалось (примечание PARAM_A и PARAM_B):

[INDEX PAGE] - nextConfig 
{serverRuntimeConfig: {…}, publicRuntimeConfig: {…}}
serverRuntimeConfig: {}
publicRuntimeConfig:
PARAM_A: "mycustomAvalue"
PARAM_B: "mycustomBvalue"
__proto__: Object
__proto__: Object

Когда я докеризую спроецируйте и предоставьте переменные env, результат будет следующим для всех страниц, и ничего не передается со стороны сервера на сторону клиента для publicRuntimeConfig:

[INDEX PAGE] - nextConfig 
{serverRuntimeConfig: {…}, publicRuntimeConfig: {…}}
serverRuntimeConfig: {}
publicRuntimeConfig: {}
__proto__: Object

Первая страница получает значения (потому что getInitialProps выполняется в _app.tsx), но всякий раз, когда я перехожу на любую другую страницу (используя next / link), я теряю переменные. Мне нужно, чтобы эти значения были доступны в моем приложении на всех страницах. Пожалуйста, скажите мне, что я упускаю что-то очевидное.

1 Ответ

0 голосов
/ 24 января 2020

При создании приложения publicRuntimeConfig будет объединено.

Сборка приложения происходит при создании образа Docker. Однако ваши переменные среды в настоящее время недоступны.

Когда вы запускаете свой контейнер, вы предоставляете переменные среды, чтобы код на стороне сервера мог их использовать, а код на стороне клиента - нет.


Одним из решений было бы создание приложения при запуске контейнера, поскольку сборка будет иметь доступ к указанным переменным env. Хотя я бы не рекомендовал этот подход.

Другое решение было бы использовать Docker аргументы сборки для установки переменных среды во время сборки:

Dockerfile

ARG PARAM_A
ARG PARAM_B

ENV PARAM_A=$PARAM_A
ENV PARAM_B=$PARAM_B

# ...

Затем передайте переменные env в качестве аргументов сборки:

docker build --build-arg PARAM_A=something --build-arg PARAM_B=something ...

Это позволяет передавать различные аргументы сборки для каждой среды.

Однако это означает, что вы есть отдельное изображение для каждой из ваших сред.

Надеюсь, это поможет.

...