hard-source-webpack-plugin icon indicating copy to clipboard operation
hard-source-webpack-plugin copied to clipboard

Prevent update of environment variables

Open dguayrobotiq opened this issue 7 years ago • 6 comments

Expected Behavior

Environment variables should not be cached.

Actual Behavior

Environment

Is an error being thrown?

No

Steps to Reproduce

  1. Add an environment variable in .env file and use it in Environment.js.
  2. webpack-serve your website
  3. Stop webpack-serve
  4. Modify the environment variable in .env
  5. Restart webpack-serve
  6. The environment variable still holds the first value

Operating System, Node, and NPM dependency versions

Mac OS 10.13.5
Node 8.11.3

"devDependencies": {
    "@sentry/webpack-plugin": "^1.5.2",
    "@types/chai": "^4.1.4",
    "@types/classnames": "^2.2.3",
    "@types/jquery": "^3.2.16",
    "@types/js-cookie": "^2.1.0",
    "@types/lodash": "^4.14.110",
    "@types/mocha": "^5.2.3",
    "@types/mock-fs": "^3.6.30",
    "@types/node": "^8.0.51",
    "@types/query-string": "^6.1.0",
    "@types/react": "^16.0.22",
    "@types/react-dom": "^16.0.3",
    "@types/react-intl": "^2.3.8",
    "@types/react-modal": "^3.2.0",
    "@types/react-router-dom": "^4.2.1",
    "@types/sinon": "^5.0.1",
    "@types/webrtc": "0.0.23",
    "aws-sdk": "^2.266.1",
    "chai": "^4.1.2",
    "classnames": "^2.2.6",
    "concurrently": "^3.5.1",
    "css-loader": "^0.28.11",
    "deploy-aws-s3-cloudfront": "^0.2.9",
    "dotenv-webpack": "^1.5.7",
    "electron": "2.0.5",
    "electron-builder": "^20.15.1",
    "electron-rebuild": "^1.8.1",
    "file-loader": "^1.1.5",
    "hard-source-webpack-plugin": "^0.12.0",
    "html-webpack-plugin": "^3.2.0",
    "ignore-styles": "^5.0.1",
    "jsdom": "^11.11.0",
    "jsdom-global": "^3.0.2",
    "mocha": "^5.2.0",
    "mocha-webpack": "^1.1.0",
    "mock-fs": "^4.5.0",
    "native-ext-loader": "^2.1.0",
    "node-sass": "^4.9.0",
    "npm-run-all": "^4.1.2",
    "query-string": "^6.1.0",
    "react-hot-loader": "^4.3.3",
    "resolve-url-loader": "^2.3.0",
    "sass-loader": "^6.0.7",
    "sinon": "^6.0.1",
    "source-map-loader": "^0.2.3",
    "source-map-support": "^0.5.6",
    "style-loader": "^0.21.0",
    "ts-loader": "^4.4.1",
    "ts-node": "^7.0.0",
    "tslint": "^5.11.0",
    "tslint-consistent-codestyle": "^1.13.2",
    "tslint-loader": "3.6.0",
    "tslint-react": "^3.4.0",
    "typescript": "^2.8.3",
    "uglifyjs-webpack-plugin": "^1.2.7",
    "url-loader": "^1.0.1",
    "webpack": "^4.5.0",
    "webpack-cli": "^3.0.8",
    "webpack-dev-middleware": "^3.1.3",
    "webpack-hot-middleware": "^2.22.2",
    "webpack-merge": "^4.1.3",
    "webpack-obfuscator": "^0.17.3",
    "webpack-serve": "^2.0.1",
    "webpack-strip-block": "^0.2.0"
  },
  "dependencies": {
    "@material-ui/core": "^1.4.2",
    "apollo-boost": "^0.1.10",
    "apollo-client": "^2.3.7",
    "async-mutex": "^0.1.3",
    "graphql": "^0.13.2",
    "install": "^0.12.1",
    "is-electron-renderer": "^2.0.0",
    "jquery": "^3.2.1",
    "js-cookie": "^2.2.0",
    "lodash": "^4.17.10",
    "minimist": "^1.2.0",
    "mngen": "^1.1.0",
    "mobx": "^3.1.5",
    "mobx-react": "^4.1.3",
    "npm": "^6.1.0",
    "raven-js": "^3.26.3",
    "react": "^16.1.1",
    "react-apollo": "^2.1.9",
    "react-dom": "^16.1.1",
    "react-electron-web-view": "^2.0.1",
    "react-hot-loader": "^4.3.3",
    "react-intl": "^2.4.0",
    "react-modal": "^3.5.1",
    "react-router": "^4.0.0",
    "react-router-dom": "^4.0.0",
    "robotjs": "^0.5.1"
  }

dguayrobotiq avatar Aug 03 '18 20:08 dguayrobotiq

Have you tried including .env in the environmentHash?

kmui2 avatar Aug 03 '18 23:08 kmui2

Optimally dotenv-webpack would be reflected in the configHash. You can console.log sorted in defaultConfigHash.js if you want to find out what hard-source is hashing by default. Maybe there isn't enough detail about the DefinePlugin in the hash.

Beyond that hard-source cannot support this issue. configHash is the support mechanism and we can try to support that but a dynamic way to not cache DefinePlugin or dotenv-webpack is not possible because of how they work.

mzgoddard avatar Aug 05 '18 12:08 mzgoddard

@mzgoddard How can I add dotenv-webpack to the configHash? My webpack config looks like this:

plugins: [
    new Dotenv({
        systemvars: true,
        path: path.join(__dirname, "../.env"),
    }),
    new HardSourceWebpackPlugin(),
],

dguayrobotiq avatar Aug 06 '18 11:08 dguayrobotiq

Have you tried including .env in the environmentHash?

Actually, this seems to be working !

dguayrobotiq avatar Aug 06 '18 11:08 dguayrobotiq

Sure, but what if you aren't using .env for everything that might change across builds! (Like you have npm run start-XX, where XX targets a different API using env vars right before the command)

EX:

"scripts": {
  "start-qa": "REACT_APP_ENV=qa npm-run-all -p watch-css start-js",

This worked for me w/o any 3rd party libraries. Note the recommended node-object-hash didn't for some reason.

const util = require('util');
const crypto = require('crypto');
....

new HardSourceWebpackPlugin({
  configHash: webpackConfig => crypto
    .createHash('md5')
    .update(
      JSON.stringify(
        util.inspect({
          webpackConfig,
          reactAppVars: Object.entries(process.env).filter(([name]) =>
            name.toUpperCase().includes('REACT_APP')
          ),
        })
      )
    )
    .digest('hex'),
  environmentHash: {
    root: process.cwd(),
    directories: [],
    files: ['package-lock.json', '.env', 'package.json'],
  },
....

I really like this lib but I think something like the above should be talked about more in the docs (or even be the default) as this burned me pretty bad for awhile till I figured out what was happening.

johnculviner avatar Jul 12 '19 15:07 johnculviner

@johnculviner I think with this approach you lose any caching when you switch between different envs. I mean I have something similar that looks like this:

"test:e2e:ci": "npm run test:e2e:ENV_1 && npm run test:e2e:ENV_2 && npm run test:e2e:ENV_3"

And in webpack config I have something like this:

{
  plugins: [
    // ...
    new webpack.EnvironmentPlugin({
      PROJECT_NAME,
      PROJECT_INTL,
      PROJECT_REGION_INTL,
    // ...
    }),
    new HardSourceWebpackPlugin(),
    // ...
  ],
  resolve: {
    alias: {
      "@projectImages": PROJECT_IMAGES,
      "@projectIntl": PROJECT_INTL,
      "@projectRegionIntl": PROJECT_REGION_INTL,
    }
  }
}

Each different env changes values of PROJECT_NAME, PROJECT_INTL and PROJECT_REGION_INTL and because of this HardSourceWebpackPlugin writes new cache for each npm run test:e2e:ENV_X call.

It would be nice to be able to switch between envs without loosing caching possibilities but recomputing modules that rely on env.

alexeychikk avatar Sep 12 '19 16:09 alexeychikk