How to access .env variables

System Information
  • Strapi Version: 4.3.0
  • Operating System: Ubuntu 20.04
  • Database: SQLite
  • Node Version: 16.16
  • NPM Version: 8.11.0
  • Yarn Version: 1.22.19

I have created Preview button for an article collection type. I’m using the blog template. I managed to make the Preview button appear. if I hard code the link it works with the Preview button. Now, I want the plugin to use environment variables to generate the link and I don’t have a clue how to do that.

My objective:

I want to replace


href={`http://localhost:3000?secret=abc&slug=${initialData.slug}`}

with


href={${CLIENT_FRONTEND_URL}?secret=${CLIENT_SECRET}&slug=${initialData.slug}`}

in ./src/plugins/previewbtn/admin/src/components/PreviewLink/index.js

where CLIENT_FRONTEND_URL and CLIENT_SECRET are environment variables declared like so in .env:

CLIENT_FRONTEND_URL=http://localhost:3000
CLIENT_PREVIEW_SECRET=abc

Here’s a run down of the code I used:

// Create strapi app named backend with a blog template
 $  yarn create strapi-app backend  --quickstart --template @strapi/template-blog@1.0.0 blog && cd backend

// Create plugin
$ yarn strapi generate

Next, I created a PreviewLink file

// ./src/plugins/previewbtn/admin/src/components/PreviewLink/index.js
import React from 'react';
import { useCMEditViewDataManager } from '@strapi/helper-plugin';
import Eye from '@strapi/icons/Eye';
import { LinkButton } from '@strapi/design-system/LinkButton';

const PreviewLink = () => {
  const {initialData} = useCMEditViewDataManager();
  if (!initialData.slug) {
    return null;
  }

  return (
    <LinkButton
      size="S"
      startIcon={<Eye/>}
      style={{width: '100%'}}
      href={`http://localhost:3000?secret=abc&slug=${initialData.slug}`}
      variant="secondary"
      target="_blank"
      rel="noopener noreferrer"
      title="page preview"
    >Preview
    </LinkButton>
  );
};

export default PreviewLink;

Then I edited this pregenerated file

// ./src/plugins/previewbtn/admin/src/index.js
import { prefixPluginTranslations } from '@strapi/helper-plugin';
import pluginPkg from '../../package.json';
import pluginId from './pluginId';
import Initializer from './components/Initializer';
import PreviewLink from './components/PreviewLink';
import PluginIcon from './components/PluginIcon';

const name = pluginPkg.strapi.name;
export default {
  register(app) {
    app.addMenuLink({
      to: `/plugins/${pluginId}`,
      icon: PluginIcon,
      intlLabel: {
        id: `${pluginId}.plugin.name`,
        defaultMessage: name,
      },
      Component: async () => {
        const component = await import(/* webpackChunkName: "[request]" */ './pages/App');
        return component;
      },

      permissions: [
        // Uncomment to set the permissions of the plugin here
        // {
        //   action: '', // the action name should be plugin::plugin-name.actionType
        //   subject: null,
        // },
      ],
    });

    app.registerPlugin({
      id: pluginId,
      initializer: Initializer,
      isReady: false,
      name,
    });
  },

  bootstrap(app) {
    app.injectContentManagerComponent('editView', 'right-links', {
      name: 'preview-link',
      Component: PreviewLink
    });
  },

  async registerTrads({ locales }) {
    const importedTrads = await Promise.all(
      locales.map(locale => {
        return import(
          /* webpackChunkName: "translation-[request]" */ `./translations/${locale}.json`
        )

          .then(({ default: data }) => {
            return {
              data: prefixPluginTranslations(data, pluginId),
              locale,
            };
          })

          .catch(() => {
            return {
              data: {},
              locale,
            };
          });
      })
    );
    return Promise.resolve(importedTrads);
  },
};

And lastly this file

// ./config/plugins.js
module.exports = {
    // ...
    'preview-btn': {
      enabled: true,
      resolve: './src/plugins/previewbtn' // path to plugin folder
    },
    // ...
  }


I solved this by adding a custom webpack configuration to enable Strapi’s admin frontend to access the environment variables as global variables.

I renamed ./src/admin/webpack.example.config.js to ./src/admin/webpack.config.js. Refer to the v4 code migration: Updating the webpack configuration from the Official Strapi v4 Documentation.

I then inserted the following code, with help from Official webpack docs: DefinePlugin | webpack :

// ./src/admin/webpack.config.js
'use strict';

/* eslint-disable no-unused-vars */
module.exports = (config, webpack) => {
  // Note: we provide webpack above so you should not `require` it
  // Perform customizations to webpack config
  // Important: return the modified config
  config.plugins.push(
    new webpack.DefinePlugin({
      CLIENT_FRONTEND_URL: JSON.stringify(process.env.CLIENT_FRONTEND_URL),
      CLIENT_PREVIEW_SECRET: JSON.stringify(process.env.CLIENT_PREVIEW_SECRET),
    })
  )

  return config;
};

I rebuilt my app afterwards and it worked.

2 Likes

Hello, is there a way NOT to this inside webpack.config.js ? I mean I only want to reach CLIENT_FRONTEND_URL and CLIENT_PREVIEW_SECRET from .env file directly or is there any workaround not to use webpack.config.js?

1 Like

As described per docs you can also do:

:bulb: Tip

Prefixing an environment variable name with STRAPI_ADMIN_ exposes the variable to the admin front end (e.g., STRAPI_ADMIN_MY_PLUGIN_VARIABLE is accessible through process.env.STRAPI_ADMIN_MY_PLUGIN_VARIABLE).