create-react-app icon indicating copy to clipboard operation
create-react-app copied to clipboard

Add environment variables to manifest.json files

Open chrisvltn opened this issue 6 years ago • 16 comments

Is your proposal related to a problem?

In the application, we have several places where we put the values that are in the manifest file, like the theme color, the app name, etc. Unfortunately, if we need to change them one day, we would need to do it everywhere we use them.

Describe the solution you'd like

It would be of very good use if we were able to insert those names in an environment variable file, such as .env, and use it in the manifest.json as well, just like we do in the index.html file.

{
  "short_name": "%REACT_APP_SHORT_NAME%",
  "name": "%REACT_APP_NAME%"
}

Describe alternatives you've considered

The only solution to have it automatic would be to or eject the configuration and apply the JSON files to the compilation files, or to add another compilation script that would run during the build process.

chrisvltn avatar Nov 09 '19 10:11 chrisvltn

Any solutions found to this?

paulmwatson avatar Feb 11 '20 10:02 paulmwatson

it could be also useful with robots.txt (for example to use PUBLIC_URL to point to the sitemap).

svengau avatar Feb 19 '20 04:02 svengau

It could be useful also for any file which is in public folder.

slevy85 avatar Feb 22 '20 08:02 slevy85

Hi, I'm having the same problem. I need to inject env variables to files within the public directory like manifest.json and other service workers js files. Do you guys know if there is any solution to this ? Any thoughts ? Thanks!

Marian0 avatar May 27 '20 19:05 Marian0

@Marian0 You can run some script with package.json's postbuild that will read the manifest.json file, change it and save. That will only be useful for builds, not for dev.

gustavopch avatar May 27 '20 20:05 gustavopch

@Marian0 In webpack.config.js I used CopyPlugin which has a transform method that you can do string replacements on. e.g.

module.exports = {
...
  plugins: [
    new CopyPlugin([
      {
        from: 'manifest.json',
        transform(content, path) {
          return content
            .toString()
            .replace(
              'process.env.API_BASE_URL',
              process.env.API_BASE_URL
            )
        },
      },
...

This works in dev and builds.

paulmwatson avatar May 28 '20 06:05 paulmwatson

Two other solutions :

  • Extract the manifest.json to an api, this api will build the manifest.json the way you wish :
 <link rel="manifest" href="https://api.example.com/manifest/%REACT_APP_SOME_VARIABLE%">

This way you can give a different manifest.json according to REACT_APP_SOME_VARIABLE. Note that the manifest.json should declare a full start_url :

{
   ...
   start_url: "https://my.pwa.com"
}
  • Another solution is to have many manifest.json in public folder and to pick the correct one with an env variable :
 <link rel="manifest" href="/manifests/%REACT_APP_MANIFEST%/manifest.json">

And file structure :

public
 |__manifests
        |___env1
              |___manifest.json
        |___env2
              |___manifest.json
        |___env3
              |___manifest.json

slevy85 avatar May 28 '20 09:05 slevy85

@paulmwatson @slevy85 Thank you guys for your suggestions! 🎉

Finally I've solved it using webpack CopyPlugin and react-app-rewired (because I don't want to eject)

Marian0 avatar May 28 '20 18:05 Marian0

I think better this to be included in react scripts. Rather than using rewired

iamchathu avatar Jun 29 '20 04:06 iamchathu

Would love to env var support build into CRA for any/all(?) public dir files.

bkeating avatar Jul 13 '20 03:07 bkeating

I would also love to see this included!

sdegetaus avatar Dec 03 '20 00:12 sdegetaus

yes, this would be quite useful

Mhbuur avatar Mar 29 '21 12:03 Mhbuur

Here is a more generic workaround to replace all %-delimited identifiers (based on https://github.com/facebook/create-react-app/issues/7953#issuecomment-635146861):


            new CopyPlugin({
                patterns: [
                    {
                        from: 'public/manifest.json',
                        transform(content, path) {
                            return content
                                .toString()
                                .replace(
                                    /%\w+%/g,
                                    (m) => process.env[m.slice(1, m.length - 1)],
                                );
                        },
                    },
                ],
            }),

dlech avatar Jun 23 '21 19:06 dlech

Any update on this ? Would be great to see this implemented in cra !

johannbuscail avatar Feb 22 '22 07:02 johannbuscail

Here is a more generic workaround to replace all %-delimited identifiers (based on #7953 (comment)):

            new CopyPlugin({
                patterns: [
                    {
                        from: 'public/manifest.json',
                        transform(content, path) {
                            return content
                                .toString()
                                .replace(
                                    /%\w+%/g,
                                    (m) => process.env[m.slice(1, m.length - 1)],
                                );
                        },
                    },
                ],
            }),

This is great. To avoid ending up with "undefined" in case of missing env var, fall back to e.g. empty string:

                                     (m) => process.env[m.slice(1, m.length - 1)] || ''

loopmode avatar Aug 05 '22 08:08 loopmode

Is there any way that this could also be done with Dotenv and DefinePlugin? "process.env" is not filled with these values.

Figured out:

const DotenvObject = new Dotenv();

const values = {
    ...DotenvObject.getEnvs().env
};

return content.toString().replace(
    /%\w+%/g,
    (m) => values[m.slice(1, m.length - 1)] || '',
);

Tommuh avatar Oct 13 '24 06:10 Tommuh