8

I've been poking around with this for at least an hour and so far I'm stumped. Perhaps I'm not understanding the docs or the medium articles. But, as I understand it NextJS (I have have the latest version installed) provides a built in env variable solution. So, there is no need for the dotenv package.

Since NextJS is setup all I would need to do is create an env.local to store my API_KEY and other sensitive information. Then, once I save that updated file, I should be able to access ${process.env.API_KEY} and have access to that value anywhere in my code.

Provided the above statements are true, I'm not able to get that to work.

In my case I'm using environmental variables to connect to Firebase. In the code below it's being implemented. I get a 500 malformed error:

Connection GRPC stream error. Code: 3 Message: 3 INVALID_ARGUMENT: 
Project id parakeat-a1-7706, is malformed: it either contains invalid 
characters or is too long. Look at https://cloud.google.com
/resource-manager/docs/creating-managing-projects#identifying_projects 
for instructions in how to get a project's id.
import * as firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
import 'firebase/analytics';

const config = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.FIREBASE_DATABASE_URL,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
  measurementId: process.env.FIREBASE_MEASUREMENT_ID,
};
// Initialize Firebase
try {
  firebase.initializeApp(config);
} catch (err) {
  // we skip the "already exists" message which is
  // not an actual error when we're hot-reloading
  if (!/already exists/.test(err.message)) {
    console.error('Firebase initialization error', err.stack);
  }
}

// const firebaseAnalytics = firebase.analytics();
const firebaseStorage = firebase.storage();
const firebaseFirestore = firebase.firestore();

export { firebaseStorage, firebaseFirestore };

The ID is correct shown above, so what's wrong? Why is it that if I put the actual value directly in and skip the process.env it successfully connects?

kevin
  • 2,707
  • 4
  • 26
  • 58

2 Answers2

18

By default all environment variables loaded through .env.local are only available in the Node.js environment (in methods like getStaticProps), meaning they won't be exposed to the browser.

In order to expose a variable to the browser, you have to prefix the variable with NEXT_PUBLIC_. For example:

NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk

Docs

hangindev.com
  • 4,573
  • 12
  • 28
  • 1
    Hm, i believe adding the `NEXT_PUBLIC ...` prefix also causes the given env var to be exposed to the client as well. That is bad for API_KEYS and other information we want to protect – kevin Aug 05 '20 at 11:34
  • 5
    The web config Firebase provided you are meant to be used in the client-side. Check out this [question](https://stackoverflow.com/questions/37482366/is-it-safe-to-expose-firebase-apikey-to-the-public). For environment variables you want to use in both client and server-side, add `NEXT_PUBLIC` prefix. For environment variables you want to use only in server-side, do not add the prefix. – hangindev.com Aug 05 '20 at 11:43
  • 2
    Ah, thank you so much for that. That adds a lot of clarity, so in that case I dont need to `process.env` all of those values. Regarding your last comment, I think there is a contradiction in your statements. "For environment variables you want to use in both client and server-side, add NEXT_PUBLIC prefix. For environment variables you want to use only in server-side, do not add the prefix." "You do not want that private key to be revealed in the client-side which means you should add the NEXT_PUBLIC prefix for that key." was that a typo? – kevin Aug 05 '20 at 12:24
  • 1
    Oh right, that's a typo. I am going to delete it so that it will not confuse others. Here is what I meant: Firebase also provides you with a private key for you to use the Firebase Admin SDK. You do not want that private key to be revealed in the client-side which means you should not add the NEXT_PUBLIC prefix for that key. – hangindev.com Aug 05 '20 at 13:27
  • Hello there. I am attempting to do the exact same thing here. I have my firebaseConfig.js file with the Keys. I created a ```env.local``` file with my secret stuff. And set the config object with the same syntax as stated above at the top of this question. The thing is that I am getting an error ```FIREBASE FATAL ERROR: Can't determine Firebase Database URL. Be sure to include a Project ID when calling firebase.initializeApp()``` – Arp Dec 12 '20 at 18:23
  • firebase is not reognizing my secrev env vars – Arp Dec 12 '20 at 18:23
  • If I turn these env variables into public ones, it will leak these keys, right? So how can we overcome this? Should we init this on a node environment? – Arp Dec 12 '20 at 18:29
0

I have used the above solution before but later on needed to include my .env variables in the bundle which is why I used the next.config.js file to house my variables.

Check this link to their documentation for reference:

Nextjs - next.config.js

  • The docs say that following version `9.4` there is the built in solution that i'm trying above. It says using `.env.local` would expose the variables to my application. Hm.. – kevin Aug 05 '20 at 11:35