facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.7k stars 26.84k forks source link

Add environment variables to manifest.json files #7953

Open chrisvltn opened 4 years ago

chrisvltn commented 4 years ago

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.

paulmwatson commented 4 years ago

Any solutions found to this?

svengau commented 4 years ago

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

slevy85 commented 4 years ago

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

Marian0 commented 4 years ago

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!

gustavopch commented 4 years ago

@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.

paulmwatson commented 4 years ago

@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.

slevy85 commented 4 years ago

Two other solutions :

Marian0 commented 4 years ago

@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)

iamchathu commented 4 years ago

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

bkeating commented 4 years ago

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

sdegetaus commented 3 years ago

I would also love to see this included!

Mhbuur commented 3 years ago

yes, this would be quite useful

dlech commented 3 years ago

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)],
                                );
                        },
                    },
                ],
            }),
johannbuscail commented 2 years ago

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

loopmode commented 2 years ago

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)] || ''
Tommuh commented 6 days ago

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)] || '',
);