create-react-app: require.context doesn't work in tests

I sometimes use webpack’s require.context to automatically load files from the filesystem. Example:

Directory structure:

- components
  - Button.js
  - Icon.js
  - index.js
- docs.js

index.js:

// `require` in every file except index.js from the current directory, then
// add their default export to module.exports based on their filename.
// eg module.exports["Button"] = require("./Button.js");
const req = require.context(".", false, /^\.\/(?!index).*\.js$/);
req.keys().forEach((fileName) => {
  const exportName = fileName.replace("./", "").replace(".js", "");
  module.exports[exportName] = req(fileName).default;
});

docs.js:

import * as components from "./components";
Object.entries(components).forEach(([componentName, ComponentClass]) => {
  /* generate docs for `componentName` using `ComponentClass` */
});

This example is somewhat contrived because index.js could just be replaced with:

import Button from "./Button";
import Icon from "./Icon";

export { Button, Icon }

but when you’re importing hundreds of files, this is both helpful and powerful; it’s easy to write a require.context that treats named exports differently, for example:

const req = require.context(".", false, /^\.\/(?!index).*\.js$/);
req.keys().forEach((fileName) => {
  const exportName = fileName.replace("./", "").replace(".js", "");
  // next line changed, now we export both the default export and the named docExamples export
  module.exports[exportName] = [req(fileName).default, req(fileName).docExamples];
});

This pattern allows you to co-locate documentation examples with your code, which discourages documentation getting out of sync with the component.

Although this example only addresses documentation, this pattern can be useful anywhere you have a lot of files with correlated features and enforcing an export signature convention is feasible and discourages code rot.


This is all possible using create-react-app today. However, it all breaks when you try to run your tests (in 0.3.0-alpha), because jest (naturally) doesn’t use webpack:

Using Jest CLI v14.1.0, jasmine2
 FAIL  src/__tests__/some-test.js (0s)
 Runtime Error
  - TypeError: require.context is not a function

Is require.context “too obscure” of a webpack feature? Should create-react-app start disallowing it or warning about its usage? Where and how do we draw the line on which webpack features should be supported and which should not be? Or, should we try to support require.context in the test runner enrivonment? If so, where and how do we draw the line on which webpack features should be supported in the test environment?

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 4
  • Comments: 24 (11 by maintainers)

Most upvoted comments

Inside of tests this is fine, you can require dynamic modules as much as you’d like and sometimes that is useful.

Outside of tests it is bad because those cases cannot be statically analyzed.

FYI for anyone who encounters this issue - instead of relying on require.context or manually building a file like @gaearon suggested, you can use directory-metagen automatically generate import/requires for files in a directory. It can output es6 modules, AMD, commonjs, and more. It even has a CLI 😃

No, unfortunately not… and just to be clear, I’m not expecting you to magic a solution out of thin air, I’ve just found from experience that it’s useful to receive feedback. I’m not expecting require.context to be suddenly supported, I just wanted to share my experience.

I’ll continue to try to find a good solution to the problem and will provide an update if and when I do.

I do appreciate you taking the time to answer though and provide suggestions.

All comments makes sense. Thanks for the discussion. Future readers: I was able to workaround this by providing mocks for each file that uses require.context, as @cpojer indicated. But as it is unsupported, I do not recommend using it. I plan on changing my code to not use it.