React:有条件地需要 CSS 文件始终包含在构建中

React: Conditionally required CSS file always included in build

出于测试目的,我包含了一个 CSS 文件,该文件禁用某些 CSS class 的动画,这样 differencify 测试就不会产生虚假差异。此 CSS 文件仅在设置了某些环境变量时才会包含:

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

这在 运行 本地时完美运行,当后端为 localhost 时禁用动画,当 运行 对其他后端时启用动画。但出于某种原因,动画在使用 react-scripts build 构建的已部署代码中也被禁用。 moment.now() 在构建代码中被覆盖,因此似乎 react-scripts build 将包括传递给 require() 的所有资源,而不管它们的条件性如何?有没有办法避免这种情况?有没有更好的方法来实现这个?

所有 require() 将在最终构建中添加静态文件,无论它们是在 true 还是 false 条件下。我会说解决方法可能是您使用 StyleSheet.create() 代替并在其中使 CSS 动态。您应该能够从逻辑上控制任何 CSS 属性,甚至最后输出一个空的 StyleSheet 对象,因此不包括构建中不相关的任何内容。

来自https://facebook.github.io

const styles = StyleSheet.create({
  container: {
    borderRadius: 4,
    borderWidth: 0.5,
    borderColor: '#d6d7da',
  },
  title: {
    fontSize: 19,
    fontWeight: 'bold',
  },
  activeTitle: {
    color: 'red',
  },
});

在你的情况下它可能是这样的:

const isIncluded = true;
const styles = isIncluded ? StyleSheet.create({
  container: {
    borderRadius: 4,
    borderWidth: 0.5,
    borderColor: '#d6d7da',
  },
  title: {
    fontSize: 19,
    fontWeight: 'bold',
  },
  activeTitle: {
    color: 'red',
  },
}) : null;

编辑:虽然在大多数情况下这是正确的,正如@Keith 所指出的那样,“...严格来说这不是正确的,例如...如果您这样做了 if (false) { require("something"); } 编译器将知道这是死代码并将排除它...”。换句话说,在编译器确定永远不会到达此代码的情况下,require() 将不会包含在构建

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

在上面的if条件中,求值是动态的,编译器不知道这是一个编译时指令,它只会在运行时才知道求值。

如果使用 webpack,有一种方法可以告诉编译器这是一个构建时间常量,例如 process.env.NODE_ENV,编译器将在构建时而不是运行时计算这个值。它通过用它的值替换 NODE_ENV 中的内容来做到这一点,例如

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

在生产过程中,上面的内容实际上会转换为 ->

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

因此 require('./disable-animations.css'); 将从构建中排除。

如果你想使用更复杂的构建时间常量,还有 https://webpack.js.org/plugins/define-plugin/ ,有了它你可以比仅仅开发和生产有更好的控制,例如。您可能需要启用日志记录等的生产构建。