vigetlabs / blendid

A delicious blend of gulp tasks combined into a configurable asset pipeline and static site builder

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Use the `paths` option of browserify to avoid relative paths hell

slorber opened this issue · comments

Based on your project, I've build some starter app structure (that I'll publish soon), to create Phonegap/Cordova apps using Gulp / Browserify / React...

What really bothered me with your project was the fact that in our app, the browserify components we create could not be required using module style but only relative paths.

This leads to things like `require("./../../../../MyModule") which is a real pain when we refactor, move files and need our brain to think about how much nesting we need or things like that...

One solution to this problem is to use the paths option of browserify.

In my case, I have just added some /js/ folder to this paths, because it is the folder in which I put all js files I develop:

    return browserify({
        entries: ['./src/js/app.js'],
        extensions: ['.jsx'],
        paths: ['./node_modules','./src/js/']
    })
        .transform('reactify')
        .bundle({debug: true})
        .on('error', handleErrors)
        .pipe(source('app.js'))
        .pipe(gulp.dest('./www'));

(for an unknown reasons, I had to put the ./node_modules or it wouldn't work, I opened some bug for that)

This way, instead of doing require("./../../common/MyUtil") or require("./../../../../../common/MyUtil") based on where I am currently in the path, I can simply do require("common/MyUtil") everywhere in my code.

Another option is that the build file can find all subdirectories of the /js/ directory and then add them all to the path, like shown here: https://gist.github.com/sbrekken/05937e81927802452f48

This way one can simply use require("MyUtil")
(maybe in this case it would worth trying to see how browserify handle naming conflicts in case your own filename already matches an existing npm module)

Some useful things to read about this:
browserify/browserify#767
(I had problems using the transforms declaration inside package.json, like mentionned at the end)

browserify/browser-resolve#41
browserify/browser-resolve#42

!!!!!!!!!!! THANK YOU. I've been looking for a way to do that for some time now! This is awesome.

hehe :)

tell me if you had the same issues I had please

hello @greypants

still not in gulp starter? :) maybe i'll do a PR then

Btw I've done a project inspired by your gulp starter that you may mention on your Readme for interested users:

https://github.com/stample/gulp-browserify-react-phonegap-starter

This isn't a requirement for me but it would be good to see pull requests like this making it into the repo. At the moment this project has been the best (and simplest) setup of Gulp that I've found.

@greypants have you thought about adding other contributors to the repo? (like @slorber) I'd hate to see the repo stagnate :)

nice. thanks.

Thanks for reminding me about this. I've been hesitant to immediately add it, since it's not a documented browserify option. Is there a good reason for that? It certainly is super useful, but I wanted to take some time to think about any negative implications before adding it. Can you guys think of any? Naming conflicts is the only one I can think of.

@greypants I use this in a real application and didn't have any problem until now.

You can find it there too:
https://github.com/stample/gulp-browserify-react-phonegap-starter
https://github.com/stample/gulp-browserify-react-phonegap-starter/blob/master/gulp/tasks/browserify.js

This works fine for me. As I use relative paths that are relative to my src folders, I do not use simple requires like require("someModule") but it's rather require("someSrcPath/subPath/someModule") thus it's improbable that I get a conflict.

But it may happen if you name one of your own module express and put it in the src root and require it with require("express"): I don't know at all the behavior in this case, maybe it depends on the list order

@greypants I've updated my SO answer as I have more insights on this:
See http://stackoverflow.com/a/23608416/82609

@slorber thanks for documenting this!

Another possible option if there's hesitation to use paths: https://github.com/joeybaker/remapify

thanks @solomonhawk I added it to my SO answer

Thanks! This was huge, especially when trying to use browserify-shim on bower dependencies like angular.

package.json

"browser": {
    "angular": "../client/libs/vendor/angular/angular.js"
},
"browserify": {
    "transform": ["browserify-shim"]
},
"browserify-shim": {
    "angular": "angular"
}

gulpfile.js

var srcDir = "../client/src/app/";
var libDir = "../client/libs/";
var vendorDir = libDir + "vendor/";
var buildDir = "../dist/dev/";

gulp.task("browserify", function() {
    return browserify({
            entries: srcDir + "ApplicationModule",
            paths: [vendorDir]
        })
        .bundle()
        .pipe(source("app.js"))
        .pipe(gulp.dest(buildDir));
});

I'm having a bit of an issue with this as well as I don't want '../../../' all over my files. In my browserify task, I have the following config

var config = {
  // Enable source maps
  debug: true,
  // Additional file extensions to make optional
  extensions: ['.js'],
  // A separate bundle will be generated for each
  // bundle config in the list below
  bundleConfigs: [{
      entries: './app/js/index-app.js',
      dest: './app/js',
      outputName: 'app.js',
      paths: ['./node_modules', './app']
  }]
}

And in my index-app.js, I'm trying to include a module:

var player = require('./lib/player');

But when I run gulp scripts for testing, this error occurs:

[12:53:05] Starting 'scripts'...
[12:53:05] Bundling app.js
[12:53:05] gulp-notify: [Compile Error] Cannot find module './lib/player' from '/git/player/app/js'
[12:53:05] Bundled app.js in 106 ms
[12:53:05] Finished 'scripts' after 136 ms

Since I'm specifying a root path, I'm confused as to why ./lib does not work with the following structure:

./app
  /js
   index-app.js
   /lib
     player.js

Did you try?

var player = require('lib/player')

Right, I must have inadvertently moved /lib out of /js. Things seem to be functioning properly now.

Moved from browserifyi to webpack, so closing this out. The option in webpack is: resolve-modulesdirectories

By chance is it explained somewhere why you choose to replace browserify with webpack?

Blog post forthcoming perhaps. In short, it's way more powerful. You can output multiple bundles, extract shared dependencies into a shared bundle, async module loading is silly easy, it's smart about dynamic requires, and more. Been using it for almost a year now and haven't looked back.

I'm having issues with babelify caching my src/node_modules files, does anyone know how to get around that?

commented

Is there a command line version of this?

Hello, i'm also looking for a command line version for this path option. Any tips ?
EDIT: actually it seems that we can do the following "NODE_PATH=./modules browserify App.js"
It worked for me.

yes @Heliodromel it's just and env variable