Skip to content
This repository has been archived by the owner on Apr 16, 2018. It is now read-only.

config-aliases-main #1

Open
desandro opened this issue Jul 16, 2013 · 9 comments
Open

config-aliases-main #1

desandro opened this issue Jul 16, 2013 · 9 comments

Comments

@desandro
Copy link
Owner

The config-aliases-main example is broken, but if you know a way resolve it, and/or you believe it to be the best way to implement the example, please chime in.

@goldibex
Copy link

I think the solution here is not to use relative dependencies of the type './internal_dependency_name', but rather to be more explicit, as this is good Require.js practice anyway.

Your example code would be

// recipient/recipient.js relies on recipient/name.js
define( [ 'recipient/name' ], function( recipientName ) {

@necolas
Copy link

necolas commented Jul 17, 2013

You can change the config to:

  paths: {
    greeter: 'components/greeter',
    recipient: 'components/recipient'
  }

Configure the path to point to the lib roots.

That way you can use ./name in the library, like we do for Twitter Flight. People have to configure the require path for flight to bower_components/flight.

desandro added a commit that referenced this issue Jul 17, 2013
@desandro
Copy link
Owner Author

@necolas I like it, I like it. It allows relative dependencies. I've added config-aliases-dir example to the repo.

@brianarn
Copy link

+1 to @necolas' approach here. If you're going to have packages of code wherein you have multiple modules that all live in a common directory, it is not unreasonable to ask your users to configure a top-level path for the package of code.

In fact, RequireJS does have a concept of setting up packages. http://requirejs.org/docs/api.html#packages has a bit more detail. Having used packages heavily with Dojo's AMD loader, this would be my choice with any AMD loader that supports it. Paths and packages are subtly different, but having it be formal packages instead of just path aliases feels nice and clean.

@necolas
Copy link

necolas commented Jul 17, 2013

Another approach I've started trying (which feels a bit more Node-like), is to set the baseUrl to wherever Bower is going to install the components. Then you use paths to alias your application code if needed.

requirejs.config({
  baseUrl: 'bower_components',
  paths: {
    'app': 'custom_components',
  }
});

This means you don't have to keep adding paths for every Bower component you have installed.

@desandro
Copy link
Owner Author

@necolas I'm curious, why not use the component-path technique?

@necolas
Copy link

necolas commented Jul 17, 2013

Components can be more portable. Imagine you write your module to work on the server and client. You want your require statements to make sense in Node-land, e.g., require('greeter/greeter'). The RequireJS configure lets you wire everything up correctly.

I think the general pattern is to go from the library root. If you're using a lot of client-side modules, then setting the baseUrl to the Bower-install directory gets it set up a bit more like how you'd expect from Node (but not exactly the same). You can do this in your module, and someone else can do similar in their application that uses your module.

define(function(require, exports, module) {
  var Greeter = require('greeter/greeter');
  module.exports = recipient;

  function recipient() {
    // ...
  }
});

…at least, that's what I'm thinking based on my experience so far. There's a lot I don't know about this stuff.

@jrburke
Copy link

jrburke commented Jul 18, 2013

My advice:

  • Single JS file dependencies should be configured with a paths setting (or ideally just installed as a single file in baseUrl).
  • a package that provides multiple modules should have its modules referred to by dirname/modulename, or an adapter module is written to point to the 'main' module for the package.

My larger answer: the package manager should be doing this work, and lay out files to avoid big config blocks. Big config blocks are an antipattern.

ES6 modules will have similar baseUrl + moduleID + '.js' default convention lookup for browsers that AMD systems do, so supporting working with that convention within the package manager would be future facing.

What does that mean for the package manager when it installs a package:

  1. If that package is just one module, just install that single file in baseUrl. Use a companion directory if it wants to keep metadata around for that file for use on further installs.

  2. If the package is many usable modules, install an adapter module under baseUrl that points to the package's main module. Using this repo as an example, the recipient package is such a package. So, when it is installed in the components directory, the file layout looks like this:

bower_components/
  recipient.js (added by package manager)
  recipient/
    recipient.js
    name.js

Where the package manager creates bower_components/recipient.js with this content:

define(['recipient/recipient'], function (main) { return main; });

Then, I also suggest using the base config that @necolas mentions: set baseUrl to the packages area and have one paths entry to the app code, and that app code uses relative IDs to refer to its code. An example of that type of project layout (not using bower, just plain requirejs). This way, there is no need to touch the config again for finding modules.

The above approach for installing packages is what volo does. Bower could support an amd and baseUrl config as volo does, which would instruct it how to do this work. Bower supports something like baseUrl via the bowerrc 'directory', but I suggest folding that into the bower.json metadata file for the project instead of another file. The amd: {} would trigger writing the adapter file in AMD format.

Later, when es6 comes out, maybe support an es: {} or esmodules: {} property that works like the amd one, but writes out those adapter modules in ES6 format instead of AMD format.

An easy intermediate approach for bower could be to just always do the path 2 approach of writing an adapter module for every package even if it is just one JS module. Longer term though I suggest trying to support just single file installs in the baseUrl to avoid the extra module hop, as I expect the bulk of basic dependencies to be single module file packages.

@desandro
Copy link
Owner Author

@jrburke Thanks for much for going into detail about this. Your expertise is much appreciated.

desandro added a commit to desandro/masonry that referenced this issue Jul 20, 2013
desandro referenced this issue in desandro/imagesloaded Jul 29, 2013
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants