When developing a React app, you might need to include or change scripts or HTML tags based on the environment you are building for. This is especially true when dealing with SEO or tracking tools, such as Google Analytics or HotJar.
What you may not know is that React applications initialized with Create React App offer you the possibility to do so. Although it’s very difficult to find documentation for it online, it is actually a cool feature. In fact, with only a handful of lines of code, you can make your index.html
file content depend on environment variables.
Let’s learn more about this little-known feature and see how to use it.
Conditional Code With HtmlWebpackPlugin
HtmlWebpackPlugin
comes with Create React App, and it is employed for bundling. Specifically, it uses public/index.html
as a template and injects a <script>
with the path provided by webpack
to produce the final HTML page.
Also, HtmlWebpackPlugin
offers developers the ability to deal with conditional code with the following syntax:
<% if (condition) { %> // code inserted in the final HTML file only if // condition is true <% } %>
You can also use the else
and/or if else
branch as follows:
<% if (condition1) { %> // code inserted in the final HTML file only if // condition1 is true <% } else if (contition2) { %> // code inserted in the final HTML file only if // condition1 is true <% } else { %> // code inserted in the final HTML file only if // both condition1 and contition2 are false <% } %>
Plus, while debugging, you may also need to print the value of a variable or condition. You can do that with this syntax:
<%= variable %>
At the end of an npm build
or npm start
process, you will find its value printed in the HTML file generated.
Conditional Code in Action
Let’s say you wanted only your production React app to be crawled by Google and Google Analytics to be present only in production. You might think about writing two custom build scripts, but this is not required.
In fact, you can easily achieve both of these results. You only have to conditionally change the code of your public/index.html
file based on the current environment, as follows:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="theme-color" content="#000000"> <!-- GOAL 1 --> <% if (process.env.NODE_ENV !== 'production') { %> <!-- avoid being crawled --> <meta name="robots" content="noindex" /> <% } %> <!-- manifest.json provides metadata used when your web app is added to the homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/ --> <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <!-- GOAL 2 --> <% if (process.env.NODE_ENV === 'production') { %> <!-- Google Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=<YOUR_ID>"></script> <% } %> <!-- Notice the use of %PUBLIC_URL% in the tags above. It will be replaced with the URL of the `public` folder during the build. Only files inside the `public` folder can be referenced from the HTML. Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> <title>React App</title> </head> <body> <noscript> You need to enable JavaScript to run this app. </noscript> <div id="root"></div> <!-- This HTML file is a template. If you open it directly in the browser, you will see an empty page. You can add webfonts, meta tags, or analytics to this file. The build step will place the bundled scripts into the <body> tag. To begin the development, run `npm start` or `yarn start`. To create a production bundle, use `npm run build` or `yarn build`. --> </body> </html>
What happens is that the two sections written with the special syntax presented above will be included in the final HTML file only when process.env.NODE_ENV
has the desired value. This environment variable is part of Create React App, as stated in the official documentation.
“[…] a built-in environment variable called
NODE_ENV
. You can read it fromprocess.env.NODE_ENV
. When you runnpm start
, it is always equal to'development'
, when you runnpm test
it is always equal to'test'
, and when you runnpm run build
to make a production bundle, it is always equal to'production'
. You cannot overrideNODE_ENV
manually.” — Create React App
Et voilà! Your index.html
content now depends on environment variables.
Conclusion
Today, we looked at how to make the index.html
file change based on environment variables. Achieving this goal is easy and involves only a few lines of code. In particular, this is possible thanks to HtmlWebPackPlugin
, which comes with Create React App by default. This useful, yet not widely known, React feature can save your day by allowing you to avoid writing custom scripts for your environment-targeted builds.
Thanks for reading! I hope that you found this article helpful.