DEV Community

Cover image for How to Set Up Environment Variables using JSON files with Rollup and TypeScript
Luis Aviles for This Dot

Posted on • Originally published at labs.thisdot.co

How to Set Up Environment Variables using JSON files with Rollup and TypeScript

In previous posts, I explained How to setup a TypeScript project using Rollup.js from scratch. Also, I covered How to Serve a Single Page Application(SPA) using Rollup.js and Web Dev Server step by step. Then, I covered How to Build a LitElement Application with Rollup.js and TypeScript.

In this article, I'll take the result of those tutorials as a starting point to set up environment variables using JSON files.

Environment Variables

Reading environment variables is very common in software development. It's a helpful way to cover security concerns and even provides the convenience to set configuration parameters in your application.

For example, in the Node.js world, you may need to set the port number to serve your application. For example:

const app = require('http').createServer((req, res) => res.send('Hello world'));
const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server is ready to listen on port ${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode

In the previous code, the app will read the value of PORT through process.env.PORT. If the value doesn't exist, it will take 3000 as a fallback.

JSON Modules

In today's JavaScript world, it's possible to read JSON Modules as follows:

import config from '../../config.json'; 
Enter fullscreen mode Exit fullscreen mode

Also, recent versions of Node.js enables the use of --experimental-json-module flag for the module to work.

Let's explore a practical way to add the same support to the current Single-Page Application which is based on TypeScript, LitElement, Rollup.js, and Web Dev Server.

Project Setup

Base Project

Let's create a clone or download the project seed before adding the new configurations and tools:

git clone https://github.com/luixaviles/typescript-rollup.git
cd typescript-rollup/
git checkout tags/03-build-litelement -b 04-env-config-json
Enter fullscreen mode Exit fullscreen mode

The previous commands will download the project and create a new branch 04-env-config-json to get started.

Source Code Files

The previous project already contains a set of files and configurations ready to configure and support JSON Modules. Open it with your favorite code editor and take a look at the project structure:

|- typescript-rollup
    |- src/
        |- math/
            |- math.ts
            |- index.ts
        |- string/
            |- string.ts
            |- index.ts
        |- main.ts
    |- index.html
    |- package.json
    |- rollup.config.js
    |- tsconfig.json
    |- web-dev-server.config.js
Enter fullscreen mode Exit fullscreen mode

Installing Rollup Plugins

Since the Single-page application considers Rollup.js as the module bundler, we'll need to install a couple of node modules first:

npm install --save-dev @rollup/plugin-json @web/dev-server-rollup
Enter fullscreen mode Exit fullscreen mode
  • @rollup/plugin-json will be in charge to convert .json files to ES6 modules.
  • @web/dev-server-rollup is an adapter for using rollup plugins in Web Dev Server, which is used to "serve" the web application in development mode.

The package.json file should have the new dependencies listed as follows:

{
  ...
  "devDependencies": {
    ...
    "@rollup/plugin-json": "^4.1.0",
    "@web/dev-server-rollup": "^0.3.2",
    ...
  },
}
Enter fullscreen mode Exit fullscreen mode

Reading the JSON Configuration

Let's add the following env-config.json file into the root of the project:

{
  "environment": "production",
  "host": {
    "protocol": "http",
    "hostname": "localhost",
    "port": 8080
  }
}
Enter fullscreen mode Exit fullscreen mode

Of course, you can set your variables according to the requirements: access keys, platform, etc.

Since you may have sensitive data in that file, it should not be versioned in any case. It's good practice to add it to the .gitignore file:

# Environment variables
env-config.json
Enter fullscreen mode Exit fullscreen mode

Also, you can provide a env-config.json.example file as an example so that developers, Dev Ops, or any member of the team can create a configuration file from it:

{
  "environment": "development",
  "host": {
    "protocol": "http",
    "hostname": "localhost",
    "port": 8080
  }
}
Enter fullscreen mode Exit fullscreen mode

Creating the TypeScript Model

It's time to define the TypeScript model for our configurations. First, let's create a src/environment/environment-model.ts:

// environment-model.ts
export interface Host {
  protocol: string;
  hostname: string;
  port: number | string;
}

export interface EnvConfig {
  environment: string;
  host: Host;
}
Enter fullscreen mode Exit fullscreen mode

Next, create a src/environment/environment.ts file with the following content:

import { EnvConfig } from './environment-model';
import envConfig from '../../env-config.json'; 

export const env = envConfig as EnvConfig;
Enter fullscreen mode Exit fullscreen mode

From now on, the configurations will be available in the env variable.

TypeScript Configuration

You may see a couple of compilation errors from TypeScript after adding the environment.ts file. To avoid them, it's required to add new compiler options in the tsconfig.json file:

{
  "compilerOptions": {
    ...
    "resolveJsonModule": true,
    "allowSyntheticDefaultImports": true
  }
}
Enter fullscreen mode Exit fullscreen mode

Why are these changes needed?

  • The resolveJsonModule flag allows the compiler to include modules with .json extension.
  • The allowSyntheticDefaultImports flag allows default imports from modules with no default export. As the documentation says, it's just type checking.

Reading Configuration Values

Let's read the configuration values to be rendered into an existing web component. Update the main.ts file with the following content:

// main.ts
import { LitElement, html, customElement, css, property } from 'lit-element';
import { env } from './environment/environment';

@customElement('comp-main')
export class CompMain extends LitElement {

    static styles = css`
    :host {
        display: flex;
    }
    `;

    @property({ type: String }) message: string = 'Welcome to LitElement';

    render() {
        return html`
        <div>
            <h1>${this.message}</h1>
            <span>This App uses:</span>
            <ul>
                <li>TypeScript</li>
                <li>Rollup.js</li>
                <li>es-dev-server</li>
            </ul>
            <span>Running environment: ${env.environment}</span>
            <ul>
                <li>Protocol: ${env.host.protocol}</li>
                <li>Hostname: ${env.host.hostname}</li>
                <li>Port: ${env.host.port}</li>
            </ul>
        </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

Just pay attention to the import line: import { env } from './environment/environment'. Then the EnvConfig object (TypeScript model) will be available as the env variable.

Rollup Configuration

As stated above, the project is already configured and uses Rollup as the module bundler. Let's move forward to allow reading the JSON content for the build.

// rollup.config.js
import merge from 'deepmerge';
import { createSpaConfig } from '@open-wc/building-rollup';
import json from '@rollup/plugin-json';

const baseConfig = createSpaConfig({
  developmentMode: process.env.ROLLUP_WATCH === 'true',
  injectServiceWorker: false
});

export default merge(baseConfig, {
  // any <script type="module"> inside will be bundled by rollup
  input: './index.html',
  plugins: [
    json()
  ]
});
Enter fullscreen mode Exit fullscreen mode

For every building process, the new json() plugin will be in charge to process the .json files. You can call any other Rollup plugin in the plugins array.

Web Dev Server Configuration

If you try to serve the application at this point, you'll find a blank page and some errors in the browser's console:

Failed to load module script: The server responded with a non-JavaScript MIME type of "application/json". 
Strict MIME type checking is enforced for module scripts per HTML spec.
Enter fullscreen mode Exit fullscreen mode

Failed to load module script non-JavaScript MIME type

That is because we configured Rollup for the build process only. However, for serving the app in a "development mode", we're using Web Dev Server.

Let's apply a couple of changes in the web-dev-server.config.js file to fix it:

// web-dev-server.config.js

const { rollupAdapter } = require('@web/dev-server-rollup');
const json =  require('@rollup/plugin-json');

module.exports = {
    port: 8000,
    nodeResolve: true,
    open: true,
    watch: true,
    appIndex: 'index.html',
    mimeTypes: {
      // serve all json files as js
      '**/*.json': 'js'
    },
    plugins: [rollupAdapter(json())],
  };
Enter fullscreen mode Exit fullscreen mode

Let's explain what's happening in that code:

  • The @web/dev-server-rollup package allows using Rollup plugins in Web Dev Server.
  • Instead of using json() plugin directly, it needs to be passed through the rollupAdapter function first.

When you're done with those changes, run npm run start again to see the final result.

Running Single-page app with JSON Environment variables

Source Code of the Project

Find the complete project in this GitHub repository: typescript-rollup. Do not forget to give it a star ⭐️ and play around with the code.

Feel free to reach out on Twitter if you have any questions. Follow me on GitHub to see more about my work.


This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit thisdotlabs.com.

This Dot Media is focused on creating an inclusive and educational web for all. We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit thisdot.co.

Top comments (0)