architecture-it/react-env¶
Librería que contiene el estándar de manejar variables de entorno necesarias para las aplicaciones frontend (CRA, NextJS, Microfrontend).
Variables accesibles en el navegador
Para que realmente sean disponibles en el navegador deben contener el prefijo REACT_APP_
o NEXT_PUBLIC_
en el caso de NextJS
Dicho prefijo se puede configurar (caso microfrontends)
La razón de está librería es para mantener el estandar de Dockerización que se tiene en la empresa, actualmente el build se hace en Azure, y luego la misma imagen se utiliza en qa y producción, por defecto webpack inyecta las variables cuando hace el build, por lo que el manejo de las variables dentro de nuestro estandar no es posible de este modo (necesitaríamos un build para cada entorno), por lo que está librería se encarga de resolver este punto.
Este fork contiene mejoras con respecto al testing y a la sobreescritura (caso microfrontend)
Toma las variables en tiempo de ejecucion en vez de en tiempo de construccion de la aplicación (webpack), para darle soporte al principio de dockerización de CICD de la empresa.
- Soporta SSR y CSR.
- Soporta multiples
.env
.
Instalación¶
Configuración necesaria
Si aún no has configurado npm para traer paquetes internos de andreani por favor volver a [configuración](../../Architecture_Packages/index.md#npm)
pnpm i @architecture-it/react-env
Ejemplo¶
REACT_APP_API_URL=https://localhost:5800/api/
REACT_APP_ANOTHER=ejemplo
# Protegidas y no devueltas en el wrapper, no contienen el prefijo
API_TOKEN=1234
import env from "@architecture-it/react-env";
export default function App(props) {
return (
<div>
<small>
Funciona en el navegador: <b>{env("API_URL")}</b>.
</small>
<small>
Funciona también en SSR: <b>{env("ANOTHER")}</b>.
</small>
<small>
Solo obtienes las que contienen en el prefijo por seguridad (no contiene API_TOKEN):
<pre>
<code>{{JSON.stringify(env())}}</code>
</pre>
</small>
</div>
)
};
Excepción
En el caso de variables que modifican el comportamiento de nuestra app según el modo de levantarla NODE_ENV
(que en modo desarrollo tiene el valor "development" y en cuando se hace build de la aplicación siempre tiene el valor "production") debemos seguir usando process.env
Ejemplo
if(process.env.NODE_ENV !== "production"){
console.log("Información solo relevante en modo de desarrollo")
}
NextJs SSR
En el caso de NextJs en las funciones getServerSideProps
, getStaticProps
o en cualquier endpoint generado se debe seguir utilizando el process.env
Implementacion¶
# ...Otras propiedades ignoradas por brevedad
# Solo debería ser autogenerado
/public/__ENV.js
# ...Otras propiedades ignoradas por brevedad
import Script from "next/script";
//omitido por brevedad
//en el componente principal
<Script src="/__ENV.js" strategy="beforeInteractive" />
{
//..otras opciones ignoradas
"scripts":{
//..otros scripts ignorados
"predev": "react-env --prefix NEXT_PUBLIC --",
//..otros scripts ignorados
},
//..otras opciones ignoradas
}
<script src="%PUBLIC_URL%/__ENV.js"></script>
{
//..otras opciones ignoradas
"scripts":{
//..otros scripts ignorados
"prestart": "react-env --",
//..otros scripts ignorados
},
//..otras opciones ignoradas
}
.env file orden de prioridad¶
Se establecen ciertos ordenes de prioridad segun parametros y/o archivos encontrados
{path-to-file} // from the --path, -p argument
.env.{key} // from the --env, -e argument
.env.local
.env
Tu configuración esta disponible en el navegador (siempre y cuando cuente con el prefijo), y process.env
en el caso del servidor.
Buena practica
Se establece que el .env.local esté agregado al .gitignore ( que nunca se suba al repositorio)
Especificando el .env¶
{
...
"scripts": {
"start": "react-env --path .env.example -- next start"
}
...
}
Especificando prefijos¶
En el caso de NextJS para mantenernos con el estandar del framework se recomienda hacer lo siguiente:
{
...
"scripts": {
"start": "react-env --prefix NEXT_PUBLIC -- next start"
}
...
}
# .env
NEXT_PUBLIC_NEXT=Next.js
NEXT_PUBLIC_CRA=Create React App
NEXT_PUBLIC_NOT_SECRET_CODE=1234
SECRET_CODE=super-secret-token
Uso con testing¶
Necesitas agregar REACT_ENV_PREFIX
como variable de entorno antes de usar jest si usas la utilidad env()
durante tus tests:
{
...
"scripts": {
"test": "REACT_ENV_PREFIX=NEXT_PUBLIC jest --maxWorkers=3"
}
...
}
Uso con Docker¶
# ...Omitido por brevedad...
FROM ghcr.io/architecture-it/nextjs:latest AS runner
COPY --from=builder /app/next.config.js ./
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder /app/package.json ./package.json
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# WORKAROUND si se tiene problemas con permisos, (Evitar)
# RUN chmod -R 777 ./public/__ENV.js
CMD ["/bin/sh", "-c", "react-env --prefix NEXT_PUBLIC -- && node server.js"]
# ...Omitido por brevedad...
FROM ghcr.io/architecture-it/nginx:latest
COPY --from=builder /app/build .
# WORKAROUND si se tiene problemas con permisos, (Evitar)
# RUN chmod -R 777 ./__ENV.js
CMD ["/bin/sh", "-c", "react-env -d ./ -- && nginx -g \"daemon off;\""]
Deprecated runtime-env-cra
7- En caso de que estemos usando Typescript debemos configurar a window para que entienda que tiene la propiedad __RUNTIME_CONFIG__
. Para esto en el archivo src/types/global.ts
debemos agregar lo siguiente.
export { };
declare global {
interface Window {
/**
* environment variables available on runtime
*/
__RUNTIME_CONFIG__: {
// its posible define your env file
REACT_APP_URL_API: string;
[key: string]: string,
};
}
}
tsconfig.json
específicamente en include
json title="tsconfig.json"
{
"compilerOptions": {
//... Omitido para brevedad
},
"include": [
"src",
"src/types" // Para que reconozca el globals.ts
]
}
##### Testing
Para hacer uso de las variables y que los test en jest funcionen hay que declarar la propiedad `__RUNTIME_CONFIG__` en el objeto window ( con cuantas variables tengamos declaradas en el archivo .env), por lo que debemos agregar al archivo `setupTests.ts` o `setupTests.js` lo siguiente.
```js title="setupTests.ts" hl_lines="2"
// resto de las imports y configuraciones ...
import "../public/runtime-env";
```