caolan / jam

JavaScript package manager - using a browser-focused and RequireJS compatible repository
MIT License
1.5k stars 105 forks source link

Pass require.config() data or app.build.js file to jam compile #127

Open nfriedly opened 11 years ago

nfriedly commented 11 years ago

Short version:

I'm using a hbs! plugin that's not in jam. I define the path in a require.config() call at the top of my main init.js file, but when I run jam compile, it doesn't parse that config and doesn't know the path to the plugin, and then chokes when the plugin gets called. How can I tell jam compile about that path?

Long version:

This is the start of my main init.js file:

require.config({
    hbs: {
        disableI18n: true,
        // write "templatename.handlebars" - this is required because we have some templates with the same name as .js
        // files and require.js gets confused since the normalized hanes have no file extension
        templateExtension: false
    },
    // todo: delete this once hbs is available in jam https://github.com/SlexAxton/require-handlebars-plugin/issues/79
    paths: {
        "hbs": "lib/require-handlebars-plugin/hbs",
        "handlebars": "lib/require-handlebars-plugin/Handlebars",
        "json2": "lib/require-handlebars-plugin/hbs/json2",
        "i18nprecompile":  "lib/require-handlebars-plugin/hbs/i18nprecompile"
    },
    baseUrl: "/scripts"
});

define([...

When I do my jam compile, I include that file first, but jam doesn't execute the file, so it never gets the configuration info from it. Then it chokes when looking for the hbs! plugin because it doesn't know the path to it.

This is the command I run:

jam compile -v --almond --wrap --out out/CUSTOMER_NAME.min.js -i CUSTOMER_NAME_config.js -i init.js -i modules/gallery/gallery -i modules/connector/connector -i modules/fblike/fblike -i modules/welcome/welcome -i modules/popularmos/popularmos -i modules/streampublish/streampublish -i modules/activitystream/activitystream

And this is the output from that command:

compiling out/CUSTOMER_NAME.min.js
include CUSTOMER_NAME_config.js, init.js, modules/gallery/gallery, modules/connector/connector, modules/fblike/fblike, modules/welcome/welcome, modules/popularmos/popularmos, modules/streampublish/streampublish, modules/activitystream/activitystream
using almond.js

Tracing dependencies for: requireLib
Error: ENOENT, no such file or directory '/usr/local/SociableLabs/1.553f5b0/conductor/webapps/rondavu.war/scripts/hbs.js'
In module tree:
    modules/gallery/gallery

Error: ENOENT, no such file or directory '/usr/local/SociableLabs/1.553f5b0/conductor/webapps/rondavu.war/scripts/hbs.js'
In module tree:
    modules/gallery/gallery

    at Object.fs.openSync (fs.js:338:18)

Failed

That hbs.js file it's choking on is actually located at /usr/local/SociableLabs/1.553f5b0/conductor/webapps/rondavu.war/scripts/lib/require-handlebars-plugin/hbs.js and it loads correctly when I'm running non-compiled js.

I've looked into this a little and found that r.js (which I think jam uses under the hood) has a -o app.build.js config flag where the app.build.js file includes this info. But with jam, the -o flag specifies the output file. (I tried it anyways, but it still failed with the same error. I assume if it had been successful, it would have overwritten my app.build.js file.)

Is it possible to do this with jam? If not, would you be willing to add this feature? I think if https://github.com/caolan/jam/issues/95 were done, that would do the trick too.

nfriedly commented 11 years ago

I've been thinking about this for a while, trying to come up with a way that doesn't involve duplicating your configs or editing the files in jam/ and I have a proposal: Add a new field to the top-level package.json with extra config options for require.js. Then any time jam rebuilds the jam/require.js and jam/require.config.js files, it automatically merges in this config if it exists. And, when jam compile is run, this config is included there too.

I'm thinking jam.requireconfig for the package.json field name, but I'm open to suggestions.

What do you say to this? I'd be happy to code it up if there's some chance that a pull request would be accepted.

caolan commented 11 years ago

@nfriedly yes, I think a property in package.json is the way to go in this case :)

nfriedly commented 11 years ago

Cool, I'll get working on it as soon as I have the chance.

nfriedly commented 11 years ago

BTW, I think this is done - see https://github.com/nfriedly/jam/tree/extraconfig, but the compile test is failing. It looks like it's the same root cause as https://github.com/caolan/jam/issues/134

heme commented 11 years ago

I believe that I'm running into a related issue...

Shim dependencies in the config section of my package.json are being overwritten by jamjs. This specifically happens when I try to use lodash for backbone instead of underscore.

My package.json:

{
  "jam": {
    ...
    "config": {
      ...
      "packages": [
        {
          "name": "lodash",
          "location": "./libs/jam/lodash/",
          "main": "dist/lodash.underscore.js"
        }
      ],
      "shim": {
        "lodash": {
          "exports": "_"
        },
        "backbone": {
          "deps": [
            "lodash",
            "jquery"
        ],
          "exports": "Backbone"
        }
      }
    }
  }
}

Jam's require.config output:

require.config({
    ...
    "packages": [
        {
            "name": "lodash",
            "location": "./libs/jam/lodash/",
            "main": "dist/lodash.underscore.js"
        }
        {
            "name": "backbone",
            "location": "libs/jam/backbone",
            "main": "backbone.js"
        },
        {
            "name": "lodash",
            "location": "libs/jam/lodash",
            "main": "./lodash.js"
        },
        {
            "name": "underscore",
            "location": "libs/jam/underscore",
            "main": "underscore.js"
        }
    ],
    "shim": {
        "lodash": {
            "exports": "_"
        },
        "backbone": {
            "deps": [
                "underscore",
                "jquery"
            ],
            "exports": "Backbone"
        },
        "underscore": {
            "exports": "_"
        }
    }
});

I apologize if this is designed functionality. However, I'd rather not load a separate require.config if possible. I assume that causes problems when optimizing/building.

I will try to debug, but this is my first time jumping in with an NPM module. I'm still learning; any advice is appreciated. Thanks for all your hard work.

nfriedly commented 11 years ago

hum.. I was under the impression that that only applied to packages in the jam repository and not your top-level package.json for your project. But the docs don't seem to say that.

I have a separate branch I'm working on for the top-level stuff, but I'm not satisfied with it yet. Maybe I need to look into this a bit more and possibly rework my branch.

heme commented 11 years ago

Not sure. I'm not seeing the config section in the docs on the site, but I did notice it in README and issue discussion.

When including backbone, I assume jam is managing all the dependencies for backbone. However, I would expect that adding a config -> shim -> backbone in my project's package.json would tell jam to use my redefined settings/dependencies.

Is this assumption wrong? Does it always use Backbone's package.json -> jam -> shim -> deps from the jam repository?

Sounds like #117 might be related as well?

CameronJ commented 9 years ago

Any updates on this issue? I'm really just looking to be able to support passing a "baseUrl" through to require.config.js. I understand that JAM needs it's own packageDir and baseUrl to know things about site root, etc, but I really would prefer not to need to call every js file by doing:

require(["/assets/js/test.js"], function(){});

Putting the path seems a little redundant, when require.js already has the baseUrl functionality supported.

While it might not be accurate, it seems like development has gone a little stagnant on this repository, surprised that this issue hasn't been resolved in 2 years.

CameronJ commented 9 years ago

As an FYI, I've come up with a temporary solution for the problem... not a great solution, but it does seem to work (at least thus far).

First, my folder structure is built in the following format:

"jam": {
    "packageDir": "views/assets/js/lib",
    "baseUrl": "views/assets/js"
}

To temporarily solve for this problem, I created the require.config.override.js file with the following contents:

var config = requirejs.s.contexts._.config;
config.baseUrl = "/assets/js/";

requirejs.config(config);

Then, on the page, I've included 2 script files:

<script language="JavaScript" type="text/javascript" src="/assets/js/lib/require.js"></script>
<script language="JavaScript" type="text/javascript" src="/assets/js/lib/require.config.override.js"></script>
<script type="text/javascript">
    require(["test"], function(){
        console.log("loaded");
    });
</script>

First, I realize that this is a bit of a hack, and not exactly a good solution; however, I'm all ears for a better solution.

[edit: I accidentally hit comment, before I finished writing it, updated with the missing content]

nfriedly commented 9 years ago

Sorry, I know I started this and then kind of abandoned it. I was hoping that I'd get a chance to send a PR, but I no longer work in that position and don't really use jam or require.js for much these days.

I'm pretty sure that they just got a hack similar to yours in place and left it at that.

CameronJ commented 9 years ago

@nfriedly Thanks for replying! Do you happen to recall what issues you had with your code? Or more accurately, how significant a fix would be? Worth asking, but I'm not really familiar with the JAM code base; however, I'd love to see it finished, and might be willing to do it myself... I'm just looking to start using JAM, as I have a real requirement for Require.JS, which server side dependency injection (like browserify) cannot solve for, and JAM seems like the best solution for handling dependencies with Require.JS, especially when a private (corporate) repository has been added.

nfriedly commented 9 years ago

Yea, it's been a couple of years and I don't remember so much now. Looking through the history here, it looks like I modified one of the other packages to work without any configuration, and then also modified JAM a bit - see https://github.com/nfriedly/jam/commits/extraconfig

However, that's so outdated that I'm not sure if it's still relevant.