Search code examples
requirejsr.jsalmond

Understanding r.js, almond, and relative paths


I see this answer but AFAICT it's not working for me. Maybe I'm doing something stupid.

I'm using almond and grunt-contrib-requirejs. I've tried a bunch of stuff

Here's my layout

.
├── Gruntfile.js
├── 3rdparty
│   ├── require.js
├── src
│   ├── lib.js
│   └── main.js
└── node_modules
    └── almond
        └── almond.js

And here's my grunt-contrib-requirejs config

requirejs: {
  full: {
    options: {
      baseUrl: "./",
      name: "node_modules/almond/almond.js",
      include: [ "src/main.js" ],
      out: "dist/app.js",
      optimize: "none",
    },
  },
},

main.js looks like this

requirejs(['./lib',], function(lib) {
  lib.hello();
});

lib.js looks like this

define([], function() {
    return {
      hello: function() {
          console.log("hello from lib");
      },
    };
});

If run a page that uses require.js as in

<script src="3rdparty/require.js" data-main="src/main.js"></script>

It runs great. You can see it live it here. Check the console and you'll see it prints hello from lib

So I run grunt. Then I run a page that uses dist/app.js and I get the error

Uncaught Error: undefined missing lib

Here's a live page.

Checking the generated dist/app.js I see lib has been turned into this

define('src/lib',[], function() {
   ...
});

And main is including it like this

requirejs(['./lib'], function(lib) {
  ...
});

In other words, the id that r.js generated src/lib doesn't match the id that main is referencing ./lib.

This seems like a very straight forward example for r.js. Like practically "hello world".

What am I doing wrong?

One thing I've tried is changing the baseUrl to ./src

requirejs: {
  full: {
    options: {
      baseUrl: "./src",
      name: "node_modules/almond/almond.js",
      include: [ "src/main.js" ],
      out: "dist/app.js",
      optimize: "none",
    },
  },
},

But now I get

{ [Error: Error: ENOENT: no such file or directory, open '/Users/gregg/temp/grunt-contrib-requirejs-example/src/node_modules/almond/almond.js'
    at Error (native)
]
  originalError: 
   { [Error: ENOENT: no such file or directory, open '/Users/gregg/temp/grunt-contrib-requirejs-example/src/node_modules/almond/almond.js']
     errno: -2,
     code: 'ENOENT',
     syscall: 'open',
     path: '/Users/gregg/temp/grunt-contrib-requirejs-example/src/node_modules/almond/almond.js',
     fileName: '/Users/gregg/temp/grunt-contrib-requirejs-example/src/node_modules/almond/almond.js' } }

So I try fixing the almond path

requirejs: {
  full: {
    options: {
      baseUrl: "./src",
      name: "../node_modules/almond/almond.js",
      include: "main",
      out: "dist/app.js",
      optimize: "none",
    },
  },
},

But that fails as well

{ [Error: Error: ERROR: module path does not exist: ../node_modules/almond/almond.js for module named: ../node_modules/almond/almond.js. Path is relative to: /Users/gregg/temp/grunt-contrib-requirejs-example
    at /Users/gregg/temp/grunt-contrib-requirejs-example/node_modules/requirejs/bin/r.js:30214:35
]
  originalError: [Error: ERROR: module path does not exist: ../node_modules/almond/almond.js for module named: ../node_modules/almond/almond.js. Path is relative to: /Users/gregg/temp/grunt-contrib-requirejs-example] }

What am I not getting?

The entire thing is checked into github here if you'd like to work with it.


Solution

  • So here's the answer.

    r.js prefers module names not paths

    requirejs: {
      full: {
        options: {
          baseUrl: "./src",
          paths: {
            almond: "../node_modules/almond/almond",
          }
          name: "almond",
          include: [ "main.js" ],
          out: "dist/app.js",
          optimize: "none",
        },
      },
    },