skip to Main Content

I was going through the React codebase, and I noticed how React’s require doesn’t quite behave like in Nodejs. I don’t get what’s going on here.

Looking at line 19 on ReactClass.js for instance, there’s a require('emptyObject'), but emptyObject isn’t listed in package.json, nor does it say anywhere where that module’s coming from.

https://github.com/facebook/react/blob/master/src/isomorphic/classic/class/ReactClass.js#L19

I did find “emptyObject” on npmjs, but the API there seems different from the one used in React; the .isEmpty grepped in React isn’t related to emptyObject.

So where is emptyObject getting loaded from, and how is React’s require doing what it’s doing? This is not intuitive. At all.

2

Answers


  1. I noticed how React’s require doesn’t quite behave like in Nodejs.

    Right. Facebook has its own module loader. All modules have unique identifiers, provided by the @providesModule directive in each module. This allows you to use the identifier to load the module, instead of the file path.

    Of course that doesn’t work in a Node.js based environment. So when React or any other Facebook project is published to npm, all require calls are rewritten automatically to something that Node understands.

    This functionality is provided by fbjs which contains shared dependencies and build helpers for all Facebook projects. This is where you find the emptyObject module.

    If you look at React’s gulp file, you can see how the module maps are constructed and that a custom Babel plugin is used to convert all require calls.

    Login or Signup to reply.
  2. The location of the emptyObject module which React refers to is https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/emptyObject.js#L9 Note that it doesn’t follow the CommonJS module system.

    To make it easier for Facebook to share and consume our own JavaScript. Primarily this will allow us to ship code without worrying too much about where it lives, keeping with the spirit of @providesModule but working in the broader JavaScript ecosystem.

    From https://github.com/facebook/fbjs#purpose

    The way of defining a module by adding @providesModule in the license header and loading those modules with require in Node is called Haste, a customized module system built for Facebook’s open source projects.

    In fact, unless you would like to understand the inner workings of React or contribute to Facebook’s open source projects, you don’t need to know that. In other words, it’s not recommended to use Haste to write your own project.

    Along the same lines, the invariant module being loaded at line 10 of ReactClass.js is declared at https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/__forks__/invariant.js#L9

    As far as I know, both Eclipse and WebStorm don’t support Haste so IDE can’t help. But with Haste, the name of file and module should be the same, so you can find a module by searching for the filename, i.e. double shift in Webstorm and Ctrl+Shift+r in Eclipse. However, the emptyObject you asked about or invariant are not part of React so it’s still cumbersome to find their origin.

    Otherwise, there is a team that shares and organizes what they learn from hacking React that I contribute to occasionally and they have linked those requires by following Haste to the corresponding origin file e.g. https://annot.io/github.com/facebook/react/blob/cc3dc21/src/isomorphic/classic/class/ReactClass.js?l=19 You may want to see that.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search