2
votes

I'm currently using the Grunt-contrib-requirejs optimizer so that my final package structure looks essentially like this:

Public/
  css
  js
   -myapp.js
   -require.js

I'd like to use requirejs-handlebars to render my templates (also using Express3-handlebars on the server side). I've got the NPM package requirejs-handlebars working, but only if I expose the module in my express server with the following line:

app.use('/node_modules/handlebars/dist/',  express.static(path.join(__dirname, './node_modules/handlebars/dist/' )));

without this fix, I get the following console error when loading my app:

GET http://localhost:3300/node_modules/handlebars/dist/handlebars.runtime.amd.js require.js:166 Uncaught Error: Script error for: handlebars.runtime

I'm guessing this error is a result of my final build structure, and my require optimizer.. For obvious reasons, the script doesn't exist since my final build structure didn't include it. I guess what I'd like is to not have to include handlebars.runtime using express middleware, or to merge it with my final myapp.js (which I'm not sure what is the best way to do this). Any ideas? Sorry for the n00bness...any advice would be greatly appreciated!

Thanks!

my main.js file looks like this:

   require.config({
  shim: {
    jquery: {
      exports: '$'
    },
    underscore: {
      exports: '_'
    },
    backbone: {
      deps: [
        'jquery',
        'underscore'
      ],
      exports: 'Backbone'
    },
    marionette: {
      deps: [
        'jquery',
        'underscore',
        'backbone'
      ],
      exports: 'Marionette'
    },
    bootstrap: {
      deps: [
        'jquery'
      ]
    }
  },
  paths: {
    backbone: '../../bower_components/backbone/backbone',
    marionette: '../../bower_components/backbone.marionette/lib/backbone.marionette',
    jquery: '../../bower_components/jquery/jquery',
    underscore: '../../bower_components/underscore/underscore',
    requirejs: '../../bower_components/requirejs/require',
    text: '../../node_modules/requirejs-text/text',
    hb: '../../node_modules/requirejs-handlebars/hb',
    'handlebars.runtime': '../../node_modules/handlebars/dist/handlebars.runtime.amd',
  },
  packages: [
    {
      name: 'handlebars',
      location: '../../node_modules/handlebars/dist/amd',
      main: './handlebars'
    }
  ]
});


require([
  './app',
], function(App){

  'use strict';
  var myapp = new App();
  myapp.start();

});

my Gruntfile:

     requirejs: {
          compile: {
            options: {
              baseUrl: "client/src",
              optimize: '', //uglify
              mainConfigFile:'client/src/main.js',
              name: "main",
              out: "build/app.js",
              removeCombined: true,
              logLevel: 0,
              findNestedDependencies: true,
              fileExclusionRegExp: /^\./,
              inlineText: true,
            }
          },
     },
1

1 Answers

1
votes

It seems grunt requirejs doesn't inline the handlebars.runtime module, which is why you had to add that remote route for it in your express code.

I managed to fix it by declaring paths for both handlebars and handlebars.runtime and I also had to shim them. So, my main.js looks something this:

paths: {
    'handlebars.runtime': '../bower_components/handlebars/handlebars.runtime',
    handlebars: '../bower_components/handlebars/handlebars',
    hbs: '../bower_components/requirejs-handlebars/hb',
},
shim: {
    'handlebars.runtime': {
        exports: 'handlebars.runtime'
    },
    handlebars: {
        deps: ['handlebars.runtime']
    },
}

And now when I grunt build I can see both handlebars and handlebars.runtime get inlined into my app.js. That should save you from having to expose node_modules dirs from express.