Search code examples
reactjsreact-scripts

React: Conditionally required CSS file always included in build


For testing purposes I include a CSS file that disables animation for certain CSS class, this is used so that differencify tests do not produce spurious diffs. This CSS file is only included if certain environmental variables are set:

if (process.env.REACT_APP_BACKEND_URL === 'localhost') {
  // Use a fixed clock against local backend
  moment.now = () => 1558396800000;

  // Disable animations when running localcd to avoid diff on visual tests
  if (process.env.REACT_APP_DISABLE_ANIMATIONS === 'true') {
    require('./disable-animations.css');
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

This works perfectly when running locally, the animations are disabled when backend is localhost and enabled when running against other backends. But for some reason the animations are also disabled in the deployed code that is built using react-scripts build. moment.now() is not overriden in the built code, so it seems that react-scripts build will include all resources passed to require() regardless of their conditionality? Is there a way to avoid that? Is there a better way to achieve this?


Solution

  • if (process.env.REACT_APP_DISABLE_ANIMATIONS === 'true') {
      require('./disable-animations.css');
    }
    

    In the above if condition, the evaluation is dynamic, the compiler does not know this is a compile time directive, it will only know to evaluate at runtime.

    If using webpack there is a way to tell the compiler this is a build time constant, an example of that is the process.env.NODE_ENV, with this the compiler will evaluate this value at build time and not runtime. It does this by replacing what's in NODE_ENV with it's value, so for example.

    if (process.env.NODE_ENV !== 'production') {
      require('./disable-animations.css');
    }
    

    During production the above will actually get converted to ->

    if ('production' !== 'production') {
      require('./disable-animations.css');
    }
    

    As such the require('./disable-animations.css'); will be excluded from build.

    If you have more complicated build time constants you want to use, there is also the https://webpack.js.org/plugins/define-plugin/ , with this you can have even finer control than just development & production, eg. you might want a production build with logging enabled, etc.