babel: Babel Presets can't be found when installed normally with NPM (T6692)

Issue originally made by @bdkjones

Bug information

  • Babel version: 6.2.0 (core 6.2.1)
  • Node version: 0.12.7
  • npm version: 3.x

Options

SUMMARY:

Babel doesn't load plugins/presets correctly when used from the CLI.


STEPS TO REPRODUCE:

1. Create a folder on your desktop: ~/Project
2. Create a different folder on your desktop: ~/Tools

3. From the Terminal, cd to "Tools".
4. Using NPM 3.x, run this command: npm install babel, babel-cli, babel-preset-react (note that we are not using -g here).

5. cd to "Projects"
6. In "Projects", create "file.js" and throw some React into that file.

7. Run Babel by calling the CLI: ~/Tools/babel-cli/bin/babel.js 
8. Pass the --presets react option.
9. Pass the path to "file.js" as the input path.
10. Pass any desired path for the output path. I used "file-out.js" in the same folder.

11. Babel will complain that it can't find the React preset.

12. Babel is trying to find the React preset by looking for it ONLY in the current working directory, which is "~/Project". (This is line 322 of option-manager.js in babel-core).


EXPECTED RESULTS:

Babel-CLI **SHOULD** locate the babel-preset-react node package that is installed in the same node_modules folder as Babel itself (in the "Tools" folder).


ACTUAL RESULTS:

Babel-CLI forgets to follow standard Node.js semantics for locating required packages. It looks only in the current working directory instead of checking A) the global locations for npm packages and B) each parent directory starting from the one where babel-cli was called, looking for a node_modules folder at that directory level and then checking for the required package.


PROPOSED SOLUTION:

Babel should *start* by checking for presets/plugins in the current working directory, as it does now. But if it can't resolve them there, it should fall back to the standard pattern used by all Node tools: look in the global install locations, then walk the directory tree up and check each level for "node_modules". 

This gives precedence to the version of presets/plugins bundled with a project but provides flexibility to use Babel in a more standard/global way.


WHY THIS MATTERS

You can't simply assume that folks will install plugins/presets in the same directory as the JS that they want to transpile with Babel. In my case, I'm bundling Babel into a Cocoa application. The Babel files (including all plugins/presets) are part of my app bundle and are called from a completely different location. This lets me make Babel "just work" for folks that don't want to muck around with configurations and npm and packages (I get to do all of that for them, huzzah).

Plus, you just split Babel into like 900 different node packages; the least you can do is make sure it follows the standard Node.js semantics for actually locating and loading those packages.

Description

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 4
  • Comments: 25 (2 by maintainers)

Most upvoted comments

Comment originally made by @Meettya

Hack for this problem if babel used with API from code, not for CLI or kind of.

Just do with require preset and use as object, not name.

  babel = require('babel-core');
  preset_react = require('babel-preset-react'); // preset for example
  // and then use requires code, not name
  result = babel.transform(code_text, {presets:[preset_react]});

This possibility exist in code, but not documented.