Now step number two,
is about those environment variables.
And that's a very useful feature,
since it allows us to use different values
in parts of our code, during development and production.
And Next.js has built-in support for environment variables.
Now to explore them, I actually wanna explore
another of concept first though.
We can configure Next.js.
Up to this point, this Next.js project
worked with all the default settings Next.js assumes.
And these are a sensible default, which often makes sense.
But maybe you want to fine-tune them.
And you can do this by adding
a special file to your project
a next.config.js file.
This is a special file which has to be named like this
and which has to sit in your root project folder,
if you add it.
And it's a file, which exports a JavaScript object
with this Node.js export syntax.
If you never worked with Node.js
you might not know this syntax.
This is in the end the equivalent to export default
in front-end JavaScript so to say.
So we export such an object here
and that's now our object
which allows you to set various configuration options.
Now, if you Google for next config
you'll find your official documentation
on that config file.
And here you learn all about that file
and what you can configure there.
You can configure a lot here, but for most of the settings
the defaults are fine.
But you can, for example add environment variables,
something we'll do in a second.
You could add a basePath
if you're hosting your next website,
not on the root level of some domain,
but in some nested path.
You can set up rewrites and redirects,
if you have some hard-coded redirects,
which should be taken into account
when the application is deployed and much more.
You can inject your own Webpack configuration
to really tap into that build process.
You can disable compression, it's enabled by default,
but you can disable it if you don't wanna use it
for whatever reason.
Compression will make your JavaScript files
and so on smaller.
So you should enable it by default and much more.
So you see, there are a couple of things you can set,
but to be honest most of the settings will rarely be needed.
And you will know when you need them.
The most helpful settings are probably redirects
and custom headers and environment variables
and the basePath.
For this project though, we need no rewrites.
We don't need to change the basePath.
We don't need any custom headers
but we will explore environment variables.
And the idea really is that in our API route here
we swap out some of these values here
from this connection string for dynamic values,
which can then differ between development and production.
So that we can have a development database connection
and a production database.
And we don't delete or manipulate production data
with our development tests.
And to make that work, I'll go to that next config file
and add the env key.
That's also what you see in the official docs here.
This allows you to set up key value pairs of your choices
and you will then be able to use your keys in your code
both in the API routes, as well as in any other component.
So you can use your environment variables
anywhere in your code base.
So here all of the setup a couple of environment variables
and I'll start with MongoDB username.
Now how you named that variable is up to you
but I'll name it like this and set this to Maximilian.
Then add the MongoDB password and set this to the password
I have here in my connection string
then I'll add the MongoDB cluster name.
And here I will use this cluster zero thing here,
so that if I had multiple clusters in my account
I can use different clusters for different environments.
So I'll add this here.
And then I'll also add the MongoDB database key.
And here, I wanna grab that database
to which I'm connecting my-site and set this here.
Now you might be wondering why I'm doing this here.
What's the benefit.
The benefit is that now we can tap into those values.
We'll do that in a second.
And when we then deploy our application
we can override these values
and you'll see how we can override them
in a couple of minutes, once we deploy.
And therefore we now need to switch
to using environment variables.
So back in the API route,
I'll now set up my connection string here
in a separate constant simply to make it
a bit easier to work with it.
And I'll set up a template literal here
because now I need to mix hard-coded and dynamic values.
And I'll still start with that MongoDB plus SRV part here
but then after the two slashes
I wanna inject the value from my environment variable
from that MongoDB username environment variable.
And here we see in the official docs
that we get access to those values
by tapping into the global process variable
which is exposed by Node.js, then dote env
and then into the key name of our choice.
Now this placeholder will be replaced
with the concrete value during the build process.
That's important.
So this will not be resolved to dynamically
after we built the app
but it will be swapped out during the build process.
And that allows us to replace it
with our environment variable value.
And it allows us to use different values
for building, for production, then during development.
But again, we're going to see this in a second.
So they are for now in contact.js here.
I now want to use process.env.mongodb username here.
Then we have a colon here.
So this is hard-coded and there after the password
which we get from process.env.mongodb_password.
And here I'm using the keys.
I have set up in my env part of that configuration.
Now we also wanna replace the cluster and the database.
So back here in contact.js.
Now we have a @ after the password
and then the cluster name.
So here, I wanna tap into process.env.mongodb cluster name
then thereafter, I have this hard-coded part.
So I'll add that here again.
And then inject process.env.mongodb database.
And then there after add this query parameter like this.
Okay, so now that's our dynamic connection string.
That's now what I'll use here for connecting
that connection string.
And now here we use environment variables.
Now that should work.
If I now start the development server again with NPM run dev
we should again be able to successfully test everything.
Specifically I should still be able to send a message here.
This should still work.
Let's see sent message success.
And we got no error here either.
So that works and now we're using environment variables.
Now, environment variables are only helpful
if we don't always use the same values.
And at the moment, the only thing we did
is that we moved these hard-coded values
from contact.js into next.config.js
But there they are still always the same
at the moment we don't differentiate
between production and development.
Now there will be certain hosting providers
which allow us to push our code to them
and then they will do the build for us.
And then there we can define different environment variables
which they should use during the build process.
And we'll see an example for this later
but we're not necessarily always using a hosting provider
that does to build for us.
And therefore for in next.config.js
we can actually define different values
for the environment variables,
for the different phases we might be in.
To be precise, when we run NPM run dev
to start the development server
we clearly are in development.
Our current phase is development.
If we run NPM run build though
to trigger the next build script,
or if we run the export script
which I explained a couple of minutes ago
then we are clearly building for production
because that's the idea behind next build and next export.
So then our face is production.
We want to use the production values.
And because we have this clear way of telling Next.js
whether we're building for development or production.
Next.js allows us to define
different sets of configuration values
for development and production.
For this we just need to import something.
And we do this with this strange looking import syntax
which is the default Node.js import syntax.
And we have to use it here in this config file
because this config file is read in a way
that other import statements won't work yet.
Here we need to import from next constants
and make sure you import exactly like this
with the require function
on the right side of the equal sign.
And then here we can import different phases
to be precise we have to face development server,
which will be used if we run NPM run dev.
We have the phase export which will be used
if we do that export command.
And then we got the production build and production server,
production build will be used if we run NPM run build
and production server will be used after that build
for the server side code once our server is up and running.
So what we could do here is we can import
that phase development server and then utilize the fact
that our export the thing here in this config file
can be an object but can also be a function.
And I'll change this to a function, to a function
which returns this configuration object then.
So we moved that into this returned object now
and I'm doing this because when using the function form
we can add a if check to check in which phase we are.
So if this configuration is loaded
for the development server or for production.
And we can find out in which phase we are
because there's function here will be executed by Next.js
and it will get the phase parameter.
And then we can check if the phase
for which this config file is being read in.
If that is equal to phase development server
and then we can say, if that's the case
if we are in development then we wanna return
a different config object than we do otherwise.
So now here I'll grab these settings and add them here.
And now that's my configuration object
for this Next.js project, if we are in development.
If we make it past this if check, we are not in development
and in all those cases
I could now set up different values here.
For example, I could use a different database.
I could say here, I'm not using my-site
but my-site-dev during development.
And then I use my-site in production.
If we change everything like that, and we save this file.
If I start the development server again with NPM run dev,
then we'll see that if I reload this context page
and I now do test this again, it should still work.
But if I then log into MongoDB and explore my collections,
what we'll see is that once this loaded here
that we now have this my-site-dev database
with a messages collection
and that collection contains our one message.
For some reason it doesn't load him for me
but we can see that there's one document in there
and we can clearly see that it's the right database name.
So now we're using this during development
and we'll use different settings for production.
And that allows us to not accidentally override
or mess with data from our real users during development.
And that is why environment variables can be very useful
and are another feature you should be aware of.