browserify icon indicating copy to clipboard operation
browserify copied to clipboard

Look for transform modules in global node modules

Open svicalifornia opened this issue 10 years ago • 9 comments

Steps to reproduce issue:

  1. Install 'coffeeify' globally: npm install -g coffeeify
  2. Try to run browserify with coffeeify: browserify -t coffeeify
  3. Browserify complains that it can't find coffeeify in the local directory.

Same with any transform module. Browserify only finds transforms if they are installed locally.

I shouldn't have to install coffeeify locally in each separate app. Please make transform lookup check the global node modules also.

svicalifornia avatar Apr 11 '15 04:04 svicalifornia

I have thought about this as well. It introduces some complexities, though, because of all the ways that people can have global modules installed. For example, beefy uses find-global-packages but that breaks on npm config set prefix.

Alternatively I've been using npm-which in my own tools, but this only works with modules that have a "bin" in their package.json.

The easiest way to do it is to determine your npm path (e.g. npm config get prefix) and then use that as an argument.

browserify index.js -t /Users/matt/npm/lib/node_modules/babelify/ > foo.js

But you probably shouldn't be using global installs in the first place; it's poor practice.

mattdesl avatar Apr 11 '15 20:04 mattdesl

Thanks for the reply, Matt. It seems that I need to install browserify globally to get the browserify command. Therefore it would make sense to install coffeeify globally too, right?

On Apr 11, 2015, at 1:39 PM, Matt DesLauriers [email protected] wrote:

I have thought about this as well. It introduces some complexities, though, because of all the ways that people can have global modules installed. For example, beefy uses find-global-packages but that breaks on npm config set prefix.

Alternatively I've been using npm-which in my own tools, but this only works with modules that have a "bin" in their package.json.

The easiest way to do it is to determine your npm path (e.g. npm config get prefix) and then use that as an argument.

browserify index.js -t /Users/matt/npm/lib/node_modules/babelify/ > foo.js

But you probably shouldn't be using global installs in the first place; it's poor practice.

— Reply to this email directly or view it on GitHub.

svicalifornia avatar Apr 11 '15 21:04 svicalifornia

Ah, this is probably something the docs could explain a bit more. Using global install is a quick and easy way of testing a CLI, but it has some drawbacks:

  • there are security concerns since modules can run arbitrary system code
  • there's a fair bit of complexity with the "npm path" and how it works on different systems
  • patch/minor versions will not be pulled in until the next time you globally install that module
  • it can cause lots of headaches when users are unknowingly running an outdated (global) install rather than what they presume to be in their node_modules
  • users who clone/test your app or project won't get the same tools when they npm install, and they might even get conflicting versions

This is why you will often see people recommending local installs instead. First, make sure you have a package.json in your app/library, then:

npm install browserify coffeeify --save-dev

And then add a script to your package.json, like so:

"scripts": {
  "build": "browserify index.js -t coffeeify > bundle.js"
}

Now when you enter npm run build it will run the locally installed browserify/coffeeify modules.

mattdesl avatar Apr 11 '15 23:04 mattdesl

Now when you enter npm run build it will run the locally installed browserify/coffeeify modules.

I'd like to suggest that to do something repeatable like that instead of some ad-hoc or once-off operation, you don't need to worry about the CLI at all -- if you don't mind creating a file you can just write a script with the API:

var
  browserify = require('browserify'),
  coffeeify = require('coffeeify'),
  fs = require('fs');

browserify('index.js')
  .transform(coffeeify)
  .pipe(fs.createWriteStream('bundle.js'));

jmm avatar Apr 13 '15 13:04 jmm

I'm having a similar issue when using npm install --prefix /node and executing /node/node_modules/.bin/karma outside of /node (e.g. cd /code/app).

// karma.conf.js
module.exports = function(config) {
  config.set({

    browserify : {
      transform : ['babelify']
    },
   // ...
  });
};
ERROR [karma]: [Error: Cannot find module 'babelify' from '/code/app']
Error: Cannot find module 'babelify' from '/code/app'
    at /node/node_modules/karma-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:50:17
    at process (/node/node_modules/karma-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:119:43)
    at /node/node_modules/karma-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:128:21
    at load (/node/node_modules/karma-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:60:43)
    at /node/node_modules/karma-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:66:22
    at /node/node_modules/karma-browserify/node_modules/browserify/node_modules/resolve/lib/async.js:21:47
    at FSReqWrap.oncomplete (fs.js:95:15)

Even though it starts with /node/node_modules, it then looks for /code/app/node_modules.

I'm glad to help debug, just need some direction for where to start.

c0 avatar May 14 '15 13:05 c0

I was able to create a workaround based on @jmm's technique.

// karma.conf.js
var babelify = require('babelify');
module.exports = function(config) {
  config.set({

    browserify : {
      transform : [babelify]
    },
   // ...
  });
};

c0 avatar May 14 '15 13:05 c0

More recently I'm starting to want a feature like this. The use case is allowing globally-installed tools like hihat to accept global transforms/plugins. Similar to how it's common to install nodemon globally and use it during TDD, rather than installing and using it as a local devDependency.

# global tools
npm install hihat tap-dev-tool -g

# using the global tools
hihat tests.js -p tap-dev-tool

mattdesl avatar Jun 12 '15 17:06 mattdesl

It would be useful for users of tools like nodenv and nodeenv if browserify supported globally installed transforms. For example, it would make possible to create a virtual node environment with all the common development dependencies ready, instead of installing them in each one of the users projects.

rocha avatar Apr 05 '17 13:04 rocha

Any news for this ? I'm browserifying a whole lot of modules and it's a hassle to have all of them have a local dependency to each transform that is needed...

If you use yarn (and yarn workspaces), yarn will optimize the location of all dependencies, which is not working for transforms (since browserify needs them installed exactly where they are used).

snajjar avatar Feb 12 '19 18:02 snajjar