4
votes

Webpack: process.env non défini à l'aide de DefinePlugin et DotEnv

Je voudrais récupérer ma variable depuis mon fichier .env mais j'obtiens toujours undefined

Voici mon code js:

const webpack = require("webpack");
const merge = require("webpack-merge");
const path = require("path");
const common = require("./webpack.common.js");

module.exports = merge.smart(common, {
    devServer: {
        contentBase: path.resolve(__dirname, "dist"),
        hot: true,
        overlay: {
            warnings: true,
            errors: true
        },
        inline :true,
        historyApiFallback: true,
        port: 8085
    },
    devtool: "inline-sourcemap",
    optimization: {
        namedModules: true
    },
    plugins: [
        new webpack.HotModulReplacementPlugin(),
        new webpack.DefinePlugin({
            "process.env.NODE_ENV": JSON.stringify("development"),
            "process.env.REACT_APP_MYAPP": JSON.stringify(process.env.REACT_APP_MYAPP)
        })
    ],
    mode: "development"
});

Ceci imprime:

Développement NODE_ENV

REACT_APP_MYAPP non défini

Dans mon package.json, il y a:

"scripts":{
      "start" : "webpack-dev-server --config webpack.dev.js",
      "build" : "webpack --config webpack.prod.js"
 }

Et dans mon webpack.dev.js:

require('dotenv').config();
class Header extends React.Component{
    constructor(props){...}
    render(){
        console.log("NODE ENV", process.env.NODE_ENV);
        console.log("REACT_APP_MYAPP", process.env.REACT_APP_MYAPP);
        ...
   }
}


2 commentaires

Double possible de React + webpack: "process.env" n'est pas défini


Pas un doublon


4 Réponses :


1
votes

Il existe plusieurs façons de faire en sorte que cela fonctionne.

Le plus simple à tester est de changer votre "start": "webpack-dev-server --config webpack.dev.js", en "start": "REACT_APP_MYAPP = http : // localhost: 8080 / node webpack-dev-server --config webpack.dev.js ",

Cela injectera la variable d'environnement et elle sera disponible pendant le processus de construction du webpack. Vous pouvez utiliser cette technique lorsque vous utilisez npm ou node pour exécuter une commande. Par exemple, NODE_ENV = 'development REACT_MY_APP = http: // localhost: 8080 / node myapp.js et les deux seront disponibles sur process.env .

Vous pouvez également appeler votre fichier require ('dotenv'). config () dans votre webpack.dev.js . Ensuite, il serait défini lors de votre utilisation du DefinePlugin.

En général, vous n'utilisez pas la commande npm start pour exécuter votre serveur de développement.

Au fur et à mesure que l'application grandit, vous devriez consulter l ' environnement Webpack Plugin . Ensuite, vous pouvez utiliser le .env pour les paramètres de construction "production", en l'exigeant dans le webpack.prod.js de production, tout en définissant vos variables d'environnement par défaut / de secours à l'aide du plugin.


5 commentaires

Pourquoi ne devrais-je pas utiliser npm start pour mon serveur de développement?


Lors du déploiement pour la production, la plupart des solutions par défaut exécuteront npm start pour lancer l'application (après avoir exécuté npm build ). Ce n'est pas forcé. Vous pouvez créer un start: production , mais il serait exécuté en tant que npm run start: production ... donc il s'agit plus simplement de suivre "l'hypothèse par défaut". Il ne nécessite pas non plus le run devant la commande npm .


Je vais tester pour confirmer, mais il semble que l'exécution de webpack-dev-server ne passe pas l'ENV_VARS dans le processus dans lequel il exécute le webpack. Je pense que l'ajout de node devant résoudre ce problème. De plus, si votre application doit être uniquement côté client et que vous téléchargez tous les fichiers de construction à servir de manière statique, le fait que npm start exécute le devServer n'a pas vraiment d'importance, car vous avez gagné. t exécuter un serveur node.js "production" pour lancer la construction. Ce serait plus important s'il s'agissait d'une application React "Server Side Rendered" (SSR).


Vous ne devez absolument pas utiliser de fichiers .env dans votre production, ni même les inclure dans votre contrôle de code source. Suivez le développement d'applications à 12 facteurs: "Les applications stockent parfois la configuration sous forme de constantes dans le code. Il s'agit d'une violation de douze facteurs, ce qui nécessite une séparation stricte de la configuration du code. La configuration varie considérablement d'un déploiement à l'autre, contrairement au code."


Ce débat sur les 12 facteurs stricts se déroule beaucoup au travail. Les applications modernes construites par Webpack nécessitent des hacks funky, sauf si vous autorisez les builds par environnement.



2
votes

La première solution en ajoutant REACT_APP_MYAPP au démarrage n'a pas fonctionné. Mais la deuxième solution a fonctionné.

SOLUTION:

Ajout du fichier require ('dotenv'). Config () dans mon webpack.dev.js et en remplaçant:

    new webpack.EnvironmentPlugin(['NODE_ENV', 'REACT_APP_MYAPP']);

par

   new webpack.DefinePlugin({
        "process.env.NODE_ENV": JSON.stringify("development"),
        "process.env.REACT_APP_MYAPP": JSON.stringify(process.env.REACT_APP_MYAPP)
    })

Merci!


0 commentaires

0
votes

Cela fonctionne pour moi dans mon modèle d'application React personnalisé, uniquement si je n'inclus pas 'REACT_APP_' dans les noms de variables:

dans webpack.config.js:

NODE_ENV=development
API=http://localhost:5000

en .env:

// Node import
const path = require('path');

const webpack = require('webpack');

require('dotenv').config();

module.exports = [
   plugins: [
    new webpack.EnvironmentPlugin(['NODE_ENV', 'API'])
  ],
]

Quand je déploie l'application (sur Netlify par exemple), j'exclus NODE_ENV des variables d'environnement de production.

p >


0 commentaires

1
votes

Voyager dans le terrier profond et sombre du lapin vous mènera aux faits suivants:

declare var process: any;
console.log(process) // will NOT work, because process hasn't been injected
console.log(process.env); // will work but risky
console.log(process.env.USERNAME); // correct: 'Donald Hump'

Dans le frontend:

plugins: [
    new DefinePlugin({
        // this might expose confidential data about your environment
        'process.env': JSON.stringify(process.env),

        // the correct way
        'process.env.USERNAME': JSON.stringify('Donald Hump')
    })
  ]

Si vous avez plusieurs objets avec des variables, il est logique d'abstraire la stringification:

// Create a function to stringify values
function stringifyValues(object: {[key: string]: any;}){
    return Object.entries(object).reduce((acc, curr) => ({...acc, [`${curr[0]}`]: JSON.stringify(curr[1]) }), {} as { [key: string]: string; });
}

// use with DefinePlugin
plugins: [
    new DefinePlugin({
      ...stringifyValues(dotenv.config().parsed),
      ...stringifyValues(dotenv.config({ path: '/.env.special' }).parsed),
      'myObject': stringifyValues({ 
            name: 'Object', 
            description: 'to be an object' 
      })
    })
  ]

Si vous vraiment voulez accéder à process.env:

declare var myString: string;
console.log(myString); // 'IAmAString'

Dans le frontend:

plugins: [
    new DefinePlugin({
        // With dotenv (values must be stringified)
        ...Object.entries(dotenv.config().parsed).reduce((acc, curr) => ({...acc, [`${curr[0]}`]: JSON.stringify(curr[1]) }), {}),
        
        // Without dotenv 
        'myString': JSON.stringify('IAmAString')
    })
  ]


0 commentaires