vigetlabs / blendid

A delicious blend of gulp tasks combined into a configurable asset pipeline and static site builder
MIT License
4.97k stars 680 forks source link

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

Closed slorber closed 9 years ago

slorber commented 10 years ago

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)

slorber commented 10 years ago

Some useful things to read about this: https://github.com/substack/node-browserify/issues/767 (I had problems using the transforms declaration inside package.json, like mentionned at the end)

https://github.com/defunctzombie/node-browser-resolve/issues/41 https://github.com/defunctzombie/node-browser-resolve/issues/42

greypants commented 10 years ago

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

slorber commented 10 years ago

hehe :)

tell me if you had the same issues I had please

slorber commented 10 years ago

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

Rodeoclash commented 10 years ago

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 :)

chasevida commented 10 years ago

nice. thanks.

greypants commented 10 years ago

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.

slorber commented 10 years ago

@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

slorber commented 10 years ago

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

LeonB commented 10 years ago

@slorber thanks for documenting this!

solomonhawk commented 10 years ago

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

slorber commented 10 years ago

thanks @solomonhawk I added it to my SO answer

EvanCarroll commented 10 years ago

Perhaps gulp-started needs to be updated with this?

https://github.com/gulpjs/gulp/blob/master/docs/recipes/fast-browserify-builds-with-watchify.md

brianmriley commented 10 years ago

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));
});
rossthedevigner commented 9 years ago

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
mykone commented 9 years ago

Did you try?

var player = require('lib/player')
rossthedevigner commented 9 years ago

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

greypants commented 9 years ago

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

slorber commented 9 years ago

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

greypants commented 9 years ago

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.

rjdlee commented 9 years ago

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

dimes commented 9 years ago

Is there a command line version of this?

Heliodromel commented 8 years ago

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.

slorber commented 8 years ago

yes @Heliodromel it's just and env variable