React: How to import images dynamically depending on environment variables?

Viewed 1972

I need to import a different logo image depending on the process environemnt variable.

import logo from `./assets/flavour/${process.env.REACT_APP_API_BASE_DIR}/logo.png`;

This raises an error: Unexpected token error.

How can I accomplish that? Is that possible?

2 Answers

Try using dynamic imports or webpack.

Dynamic imports

Your import will look something like this:

let logo;
import(`./assets/flavour/${process.env.REACT_APP_API_BASE_DIR}/logo.png`).then((module) => {
  logo = module.default; // <= base64 image
});

...

<img src={logo} alt="logo" />

But in this way you will get the desired logo value only at the next render and if logo was loaded before.

Therefore, there is the option to use this useState and imports within our functional components:

export const Logo = () => {
  const [logo, setLogo] = useState('');

  import(`./assets/flavour/${process.env.REACT_APP_API_BASE_DIR}/logo.png`).then((module) => {
    setLogo(module.default);
  });

  return (
    <img src={logo} />
  );
};

If you have a lot of such images import, then this component can be rewritten so that it is reusable:

export const Image = ({path, alt}) => {
  const [imageSrc, setImageSrc] = useState('');

  import(path).then((module) => {
    setImageSrc(module.default);
  });

  return (
    <img src={imageSrc} alt={alt} />
  );
};

Wepback aliases

The second option that came to my mind is try using Webpack aliases. To do this add to your webpack.config.js

module.exports = (env) => ({
  // ...
  resolve: {
    // ...
    alias: {
      '@assets': path.join(__dirname, 'assets', 'flavour', env.REACT_APP_API_BASE_DIR),
    },
  },
  // ...
})

And then use in your code:

import logo from `@assets/logo.png`;

I did a write up on how I managed it, along with an example: Dynamic Enviroment Based Imports in React / Javascript / Node. You can customize this solution to meet your needs.

My solution uses a python script to set the targets and change the imports.

npm run target-ios

Modifying imports to match the specified platform: ios

Line modified in file: ./app/components/profiles/Avatar.tsx
Org: import PlatformAvatar from "./Avatar.webandroid"; // !dynamic-import options=["webandroid", "ios"]
New: import PlatformAvatar from "./Avatar.ios"; // !dynamic-import options=["webandroid", "ios"]
Related