How To Conditionally Change index.html in React

How To Conditionally Change index.html in React

Make your index.html content depend on environment variables

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 from process.env.NODE_ENV. When you run npm start, it is always equal to 'development', when you run npm test it is always equal to 'test', and when you run npm run build to make a production bundle, it is always equal to 'production'. You cannot override NODE_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.


The post "How To Conditionally Change index.html in React" appeared first on Writech.