Environment variables not working (Next.JS 9.4.4)

Perdixo picture Perdixo · Jun 15, 2020 · Viewed 11.6k times · Source

So i'm using the Contentful API to get some content from my account and display it in my Next.Js app (i'm using next 9.4.4). Very basic here. Now to protect my credentials, i'd like to use environment variables (i've never used it before and i'm new to all of this so i'm a little bit losted).

I'm using the following to create the Contentful Client in my index.js file :

const client = require('contentful').createClient({
    space: 'MYSPACEID',
    accessToken: 'MYACCESSTOKEN',
});

MYSPACEID and MYACCESSTOKEN are hardcoded, so i'd like to put them in an .env file to protect it and don't make it public when deploying on Vercel.

I've created a .env file and filled it like this :

CONTENTFUL_SPACE_ID=MYSPACEID
CONTENTFUL_ACCESS_TOKEN=MYACCESSTOKEN

Of course, MYACCESSTOKEN and MYSPACEID contains the right keys.

Then in my index.js file, i do the following :

const client = require('contentful').createClient({
  space: `${process.env.CONTENTFUL_SPACE_ID}`,
  accessToken: `${process.env.CONTENTFUL_ACCESS_TOKEN}`,
});

But it doesn't work when i use yarn dev, i get the following console error :

{
  sys: { type: 'Error', id: 'NotFound' },
  message: 'The resource could not be found.',
  requestId: 'c7340a45-a1ef-4171-93de-c606672b65c3'
}

Here is my Homepage and how i retrieve the content from Contentful and pass them as props to my components :

const client = require('contentful').createClient({
    space: 'MYSPACEID',
    accessToken: 'MYACCESSTOKEN',
});

function Home(props) {
  return (
    <div>
      <Head>
        <title>My Page</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main id="page-home">
        <Modal />
        <NavTwo />
        <Hero item={props.myEntries[0]} />
        <Footer />
      </main>
    </div>
  );
}

Home.getInitialProps = async () => {
  const myEntries = await client.getEntries({
    content_type: 'mycontenttype',
  });

  return {
    myEntries: myEntries.items
  };
};

export default Home;

Where do you think my error comes from?

Researching about my issue, i've also tried to understand how api works in next.js as i've read it could be better to create api requests in pages/api/ but i don't understand how to get the content and then pass the response into my pages components like i did here..

Any help would be much appreciated!

EDIT :

So i've fixed this by adding my env variables to my next.config.js like so :

const withSass = require('@zeit/next-sass');

module.exports = withSass({
  webpack(config, options) {
    const rules = [
      {
        test: /\.scss$/,
        use: [{ loader: 'sass-loader' }],
      },
    ];

    return {
      ...config,
      module: { ...config.module, rules: [...config.module.rules, ...rules] },
    };
  },
  env: {
    CONTENTFUL_SPACE_ID: process.env.CONTENTFUL_SPACE_ID,
    CONTENTFUL_ACCESS_TOKEN: process.env.CONTENTFUL_ACCESS_TOKEN,
  },
});

Answer

Nikolai Kiselev picture Nikolai Kiselev · Jun 15, 2020

You can't make this kind of request from the client-side without exposing your API credentials. You have to have a backend.

You can use Next.js /pages/api to make a request to Contentful and then pass it to your front-end.

Just create a .env file, add variables and reference it in your API route as following:

process.env.CONTENTFUL_SPACE_ID

Since Next.js 9.4 you don't need next.config.js for that.


By adding the variables to next.config.js you've exposed the secrets to client-side. Anyone can see these secrets.

New Environment Variables Support

Create a Next.js App with Contentful and Deploy It with Vercel

Blog example using Next.js and Contentful