- Published on
Why being able to use dotenv with Next.js is so huge
- Authors
- Name
- interglobalmedia
- @letsbsocial1
Today I pretty much completed the revamp
of this website. My previous build had been with GatsbyJS
, but from the beginning, I seemed to constantly encounter issues
with it. I had chosen it as a static framework
because of the image optimization
it provided. I also was interested in GraphQL
at the time (still am, but more on the backend
), so that is why I went with it.
But these days, there are more options to choose from, and which have more features to offer out of the box.
I had heard about Next.js
for a while, and what attracted me to it the most was its server side rendering
and the ability to tack on a backend
. But what does server side rendering
mean?
According to Educative,
Server-side rendering (SSR), is the ability of an application to contribute by displaying the web-page on the server instead of rendering it in the browser. Server-side sends a fully rendered page to the client; the client’s JavaScript bundle takes over and allows the SPA framework to operate. There is also client-side rendering which slows down the procedure of viewing and interacting with the web page. — Educative.io
But why is this such a big deal, you may ask.
There are great advantages to using SSR
.
Pages load faster, which means better
UX
.It greatly contributes to
Search Engine Optimization
(SEO
), and correctly indexes pages.Google
favors web pages with fasterload time
.It contributes to the
loading
of auser
's page when they have a slowinternet connection
.
GatsbyJS
also has server side rendering
, but not in the same way as Next.JS
. It is still a purely static
, frontend framework
. AND build time
was never blazing fast
!
With Next.js
, there is also the ability to use environment variables
, which would be typically used in an application
with a backend
. Well, we CAN add a backend
to our Next.js
applications! But we can also use them in our Next.js
static sites by adding the NEXT_PUBLIC
prefix.
And why is the ability to use environment variables
so huge? It means that we can hide our little sensitive secrets from the browser
. With purely static
, frontend
applications, we cannot do that, thereby exposing our sensitive data to the world within our pages' parsed HTML
markup.
That's great, you may say. But what is the big deal about being able to use dotenv
with Next.js
? Doesn't Next.js
already have its own way of dealing with environment variables
?
YES. It does. However, the process is a bit "circular"
, and not as simple to implement. Honestly, I did not even try to learn it after reading about it in several places. I thought there had to be an easier way. And since I have used dotenv
since learning about it some years ago, I thought there had to be a way of using it in Next.js
. And there sure is. Above all, it is SO EASY to implement. Why would I want to configure my environment variables
in ANY OTHER WAY?
How did I find out about it? I came across an article on Medium
entitled Environmental Variables in Next.js with dotenv, by Deepak Surya
, which provided the answer to my question
: "How can I use dotenv with Next.js?
"
I did make a slight modification to the code
Deepak Surya presented in the article
, making the process
even easier.
The first environment variables
I added were for my ConvertKit
newsletter form inside the Next.js Tailwindcss starter blog I use(d) to build this site
. And the process was the following:
First, I had to specifiy convertkit
inside my siteMetadata.js
file:
//data/siteMetadata.js
newsletter: {
// supports mailchimp, buttondown, convertkit, klaviyo, revue, emailoctopus
// Please add your .env file and modify it according to your selection
provider: 'convertkit',
},
Next, I added the NEXT_PUBLIC
prefix to the ConvertKit
related variables I was using in convertkit.js
:
//api/convertkit.js
const FORM_ID = process.env.NEXT_PUBLIC_CONVERTKIT_FORM_ID
const API_KEY = process.env.NEXT_PUBLIC_CONVERTKIT_API_KEY
const API_URL = process.env.NEXT_PUBLIC_CONVERTKIT_API_URL
which initially was:
const FORM_ID = process.env.CONVERTKIT_FORM_ID
const API_KEY = process.env.CONVERTKIT_API_KEY
const API_URL = process.env.CONVERTKIT_API_URL
I added the NEXT_PUBLIC
prefix to make the environment variables
accessible to the browser
.
But none of this meant anything until I installed the dotenv
npm package in my Next.js
application from inside the root of the application
. I installed it using the following npm command
:
npm i dotenv -S
Then I had to actually use this package somewhere. It is always used in the backend
and therefore is required
instead of imported
into a file. So that meant requiring it inside the next.config.js
file where the require
keyword can be used. It is not a JavaScript
keyword, but a Node.js
keyword. It is a built-in Node.js
function whith the sole purpose of loading modules such as dotenv
! So right above my module.exports
in Next.js
, which is also used in Node.js
instead of JavaScript
's export default
or export const
, for example, I added the following:
const webpack = require('webpack')
const dotenv = require('dotenv')
dotenv.config()
It is essential to require webpack, as done above. Otherwise, an error will be thrown. Something like the following:
npm run dev
> tailwind-nextjs-starter-blog@1.5.5 dev
> next dev
ready - started server on 0.0.0.0:3000, url: http://localhost:3000
info - Loaded env from /Users/mariacam/Development/interglobalmedia-tailwind-nextjs/.env.local
info - Loaded env from /Users/mariacam/Development/interglobalmedia-tailwind-nextjs/.env
info - Disabled SWC as replacement for Babel because of custom Babel configuration ".babelrc" https://nextjs.org/docs/messages/swc-disabled
info - `compiler` options in `next.config.js` will be ignored while using Babel https://nextjs.org/docs/messages/ignored-compiler-options
ReferenceError: webpack is not defined
at Object.webpack (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/next.config.js:90:11)
at Object.webpack (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/@next/bundle-analyzer/index.js:19:29)
at Object.getBaseWebpackConfig [as default] (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/next/dist/build/webpack-config.js:1176:32)
at async Promise.all (index 0)
at async Span.traceAsyncFn (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/next/dist/trace/trace.js:79:20)
at async Span.traceAsyncFn (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/next/dist/trace/trace.js:79:20)
at async HotReloader.start (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/next/dist/server/dev/hot-reloader.js:337:25)
at async DevServer.prepare (/Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/next/dist/server/dev/next-dev-server.js:292:9)
at async /Users/mariacam/Development/interglobalmedia-tailwind-nextjs/node_modules/next/dist/cli/next-dev.js:127:9
It is necessary to make sure it is explicitly required in the file, because process.env
is not available in browsers
, but as already mentioned, Next.js
both runs in the server
as well as the browser
.
Then I had to require dotenv
. THEN, instead of what Deepak states, all we have to do is add dotenv.config()
. I would do the same if working solely in a Node.js
application, and was not requiring dotenv
in a file
located in the root of the application, but inside another subfolder. That is all you have to do to make it work anywhere. And since I had placed my .env
file in my application's root folder
, I did not have to set the path
to my .env
file. In fact, when working with dotenv
, you always have to place the .env
file inside the root folder
of your application.
Next, inside my module.exports
, I had to add the following:
//next.config.js
config.plugins.push(
new webpack.EnvironmentPlugin(
'NEXT_PUBLIC_CONVERTKIT_API_URL',
'NEXT_PUBLIC_CONVERTKIT_API_KEY',
'NEXT_PUBLIC_CONVERTKIT_FORM_ID',
),
)
I already was using webpac
k inside next.config.js
, so I did not need to include webpack(config) {}
. webpack
was already there. So I placed the above code right before the return config
statement, which was also already there. I also included environment variables
for Giscus Github comments
, and Google Analytics
. The process is the same. And that is it!
As Deepak
mentions in her article, the webpack.EnvironmentPlugin()
"parses" the destructured object
she includes in her code
. However, that is not a good demonstration of what actually should be done. The above is the correct approach. Please refer to the webpack documentation
regarding the webpack.EnvironmentPlugin()
: (webpack) EnvironmentPlugin.
And THAT is IT!
As I mention in my Tweet
on July 4, 2022
,
@nextjs is a good reason why one ever again should be revealing sensitive data on client side. No excuse. And I am seeing it out there when using Nextjs. No no no!
—
Happy dotenving
!
Related Resources
Environmental Variables in Next.js with dotenv - by Deepak Surya on medium.com
(webpack) EnvironmentPlugin - Webpack Documentation