mzgoddard / hard-source-webpack-plugin

https://www.npmjs.com/package/hard-source-webpack-plugin
ISC License
2.71k stars 160 forks source link

Prevent update of environment variables #417

Open dguayrobotiq opened 6 years ago

dguayrobotiq commented 6 years ago

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"
  }
kmui2 commented 6 years ago

Have you tried including .env in the environmentHash?

mzgoddard commented 6 years ago

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.

dguayrobotiq commented 6 years ago

@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 commented 6 years ago

Have you tried including .env in the environmentHash?

Actually, this seems to be working !

johnculviner commented 5 years ago

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.

alexeychikk commented 5 years ago

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