jmm / pathmodify

In a nutshell, rewrite (AKA alias, map) `require()` IDs / paths / directories to different values in browserify.
MIT License
27 stars 1 forks source link

browserify cwd(?) changing, effecting relative path #4

Closed andrewc89 closed 8 years ago

andrewc89 commented 8 years ago

Here's a good issue for the weekend. Here is a basic outline of my project:

GreenField
- Accounting
----- Javascript
-------- Confidential
----------- Check
-------------- bundle
----------------- dev.js
-------------- index.js
- Assets
----- JS
-------- modules
----------- resize.js
----------- jquery
-------------- jquery.ajax.postList.js

relevant part of my Gruntfile

var pathmodify = require("pathmodify");
var config = require("./../config");

module.exports = function (grunt) {

    function browserifyConfigure(b) {
        // alias dir for global modules location outside project scope
        b.plugin(pathmodify(), { mods: [pathmodify.mod.dir("assets", config.globalModulesDir)] });
    }

    grunt.initConfig({

        // config level instances
        scriptsDir: config.scriptsDir,
        folder: grunt.option("folder"),
        subfolder: grunt.option("subfolder"),

        browserify: {
            options: {
                configure: browserifyConfigure
            },
            // bundles all JS files in dir, ignoring those in bundle dir
            default: {
                src: ["<%= scriptsDir %>/<%= folder %>/<%= subfolder %>/**/*.js", "!<%= scriptsDir %>/<%= folder %>/<%= subfolder %>/bundle/*.js"],
                dest: "<%= scriptsDir %>/<%= folder %>/<%= subfolder %>/bundle/dev.js"
            },
        },

        watch: {
            options: {
                livereload: true
            },
            // bundle JS if any JS files are updated, excluding compiled-jsx and bundle dirs
            js: {
                files: ["<%= scriptsDir %>/<%= folder %>/<%= subfolder %>/**/*.js", "!<%= scriptsDir %>/<%= folder %>/<%= subfolder %>/bundle/*.js"],
                tasks: ["browserify:default"]
            }
        },
    });

    // when JS file changes, set folder and subfolder config values from filepath of changed file
    grunt.event.on("watch", function (action, filepath, target) {
        if (target === "js") {
            var split = filepath.split('/');
            grunt.config.set("folder", split[1]);
            grunt.config.set("subfolder", split[2]);
        }
    });

config.js

var config = {
    // dir containing layout JS
    layoutDir: "Assets/JS/layout",
    // entry point for layout JS
    layoutEntry: "index.js",
    // root JS folder in project
    scriptsDir: "Javascript",
    // relative to {projectFolder}/{rootFolder}/{folder}/{subfolder}
    globalModulesDir: "./../../../../Assets/JS/modules",
};

module.exports = config;

and the imports in index.js

$ = require("jquery");
require("block-ui");
var ko = require("knockout");
var resize = require("assets/resize").resize;
var postList = require("assets/jquery/jquery.ajax.postList");

When I run the watch task, I get the following output:

Running "watch" task
Waiting...
>> File "Javascript\Confidential\Check\index.js" changed.
Running "browserify:default" (browserify) task
>> Error: Cannot find module './../../../../Assets/JS/modules/resize' from 'C:\Development\GreenField\Accounting\Javascript\Confidential\Check\bundle'

If I change globalModulesDir to ./../../../../../Assets/JS/modules (by adding a ../), I get the following output:

Running "watch" task
Waiting...
>> File "Javascript\Confidential\Check\index.js" changed.
Running "browserify:default" (browserify) task
>> Error: Cannot find module './../../../../../Assets/JS/modules/jquery/jquery.ajax.postList' from 'C:\Development\GreenField\Accounting\Javascript\Confidential\Check'

The important part is the path in the "from" part of the error. It is changing the cwd (?) in the middle of a build. This may be an issue more suited for grunt-browserify, but I figured since I was using pathmodify for the path I should start here.

jmm commented 8 years ago

@gwely I think the problem is that globalModulesDir is a relative path. I think it'll be fixed if you make it an absolute path. You can do it with something like path.resolve(__dirname, config.globalModulesDir).

That second argument should usually be an absolute path, although if you need to you can access the path of the parent (requiring) module and calculate a relative path from that.

Can you please see if that resolves it and let me know? If I didn't read this carefully enough, let me know.

Thanks!

andrewc89 commented 8 years ago

Of course. I tried using path.join so I was on the right track but didn't know about resolve.

Thanks for your help.

Would you like a pull request to update the README on using pathmodify with grunt-browserify? I can throw your example in there.

jmm commented 8 years ago

You're welcome.

Would you like a pull request to update the README on using pathmodify with grunt-browserify?

Thanks for the offer! I'd say not in the main README, because it's a browserify plugin and that's the only API integration I want to document there. I'll think about if a separate Integrations document would make any sense and ping you. I somewhat feel like grunt-browserify is where that kind of documentation belongs, since that's wrapping the browserify API.

They specifically document how to implement remapify there, so I'd say maybe it'd make sense to ask them to do it for pathmodify, but before I'd suggest that I think I want to push a new release that changes the export from a factory to the actual plugin function. And I may make my proposal to legitimize something in browserify that pathmodify needs to stop relying on undocumented behavior.

I can throw your example in there.

Do you mean the path.relative () example? I'll think about if there's somewhere for that to fit in. I don't want to clutter the docs with too much general info, but I'll see if I need to emphasize more using an absolute path for that argument and if it makes sense to specifically mention path.relative(). Feel free to share your thoughts.

Thanks!

andrewc89 commented 8 years ago

I am not sure why they recommend remapify. I could not get it to work I found several others with similar issues (i.e. it just doesn't seem to do anything).

I was just referencing your example code from the previous issue here.

jmm commented 8 years ago

I was just referencing your example code from the previous issue here.

Oh, gotcha.

I am not sure why they recommend remapify. I could not get it to work I found several others with similar issues (i.e. it just doesn't seem to do anything).

Must have seemed like the best option at the time. But yeah, I've had that same experience -- I was trying to use that before I created this and had a variety of problems. I opened an issue in December that's still open about how the "hello world" usage of it as described in the README didn't even work. I had too many problems and created this, which I think is better anyway, for a variety of reasons, including that it doesn't use globbing, it just works from the dependency graph; it doesn't transform files, so it's probably faster; it can also control exposure of modules.

andrewc89 commented 8 years ago

Yes, your solution is much more manageable. Good luck getting some recognition at grunt-browserify!

jmm commented 8 years ago

@gwely Thanks! For all I know they'd add it if someone brought it up, I just haven't really had the motivation to ask, and might rather improve the plugin more first anyway.