I'm using RequireJS on a multipage project, with a Javascript folder structure that looks kinda like this (how do you make those fancy dir trees again in Markdown?):
common.js
lib/
-- jquery-1.9.1.min.js
-- modernizr-2.6.2.min.js
-- underscore-amd.min.js
page/
-- index.js
-- start.js
-- checkout.js
Anyway, common.js
is my main script file that is where I set up the configuration parameters. This is what that looks like:
common.js file
// Configure RequireJS
requirejs.config({
baseUrl: "assets/js/lib",
paths: {
page: '../page',
jquery: [
'//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
//If the CDN location fails, load from this location
'jquery-1.9.1.min'
],
modernizr: [
'//cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min',
//If the CDN location fails, load from this location
'modernizr-2.6.2.min'
],
underscore: [
'underscore-amd.min'
]
}
});
All the page calls work as expected (with the CDN location being loaded), but I can't get my head around the minification part. The r.js
optimizer simply refuses to cooperate, throwing an Error: paths fallback not supported in optimizer. Please provide a build config path override for underscore
even though Underscore doesn't have a CDN specified.
build.js file
{
appDir: '../www',
baseUrl: 'js/lib',
dir: '../www-built',
mainConfigFile: '../www/assets/js/common.js',
modules: [
//First set up the common build layer.
{
//module names are relative to baseUrl
name: '../common',
include: ['jquery',
'modernizr',
'underscore'
]
},
// Now the page scripts
{
//module names are relative to baseUrl/paths config
name: '../page-index',
include: ['page/index'],
exclude: ['../common']
},
],
paths: {
jquery: "empty",
modernizr: "empty"
},
optimize: "uglify2",
removeCombined: true
}
Please help me figure out how to build this project to create the common.js
script along with the individual page scripts.
(Note: I based the structure of my build.js
file on this example
I've updated the question to include the correct syntax for empty:
(thanks Travis!), and now the build runs without error. However, my JS files are not concatenated or uglified. The CSS files are, at the import points, so something's happening. Complete build.js
file below (forgive me, but she's a tall one):
{
appDir: '../www',
baseUrl: 'assets/js', // relative to appDir
dir: '../www-built',
mainConfigFile: '../www/assets/js/common.js',
modules: [
//First set up the common build layer.
{
//module names are relative to baseUrl
name: 'common',
//List common dependencies here. Only need to list
//top level dependencies, "include" will find
//nested dependencies.
include: ['jquery',
'modernizr',
'underscore',
'bootstrap'
]
},
//Now set up a build layer for each page, but exclude
//the common one. "exclude" will exclude nested
//the nested, built dependencies from "common". Any
//"exclude" that includes built modules should be
//listed before the build layer that wants to exclude it.
//"include" the appropriate "app/main*" module since by default
//it will not get added to the build since it is loaded by a nested
//require in the page*.js files.
{
//module names are relative to baseUrl/paths config
name: 'pages/home',
include: ['pages/home'],
exclude: ['common']
},
{
//module names are relative to baseUrl/paths config
name: 'pages/start',
include: ['pages/start'],
exclude: ['common']
},
{
//module names are relative to baseUrl/paths config
name: 'pages/checkout',
include: ['pages/checkout'],
exclude: ['common']
},
],
paths: {
jquery: "empty:",
modernizr: "empty:"
// underscore: "empty:"
},
optimize: "uglify2",
optimizeCss: "standard",
removeCombined: true,
preserveLicenseComments: false
}
Thanks to Travis below, everything is working great! (the files are getting minified and concatenated). Since his solution is hosted on Dropbox, and could be lost in the future (who knows amirite?), I'll just sum up the fixes he made:
define
and require
calls in a single file.I had a couple of files where I'd mixed them like so:
page/start.js
define(['jquery','underscore'],function($,_) {
...
});
require(['jquery','page/start'], function($, Y) { // BAD!
...
});
and the fix was to do this:
page/start.js
require(['jquery','app/start_helper'], function($, Y) {
...
});
app/start_helper.js
define(['jquery','underscore'],function($,_) {
...
});
"empty:"
not "empty"
That's a tricky one, though the RequireJS docs mention them.
what kind of list has just 2 bullet points?
Awesomelicious - now it works like a charm :)
Looks like requireJs thinks that you're trying to provide a paths fallback for underscore, since you're specifying its path value as an array. Try just doing it as a string instead.
paths: {
underscore: 'underscore-amd.min'
}
Also note that the correct symbol for empty paths is empty:
(with a ':') not empty
.
Finally, as an unrelated side note you could always look at lodash which is IMHO a more customizable, cross-browser compliant, faster underscore replacement with an identical API and it's hosted on cdnjs and is AMD-compliant
UPDATE
Following up on the conversation within the comments, here's my updated version of your project: https://dl.dropboxusercontent.com/u/21823728/so_rjs.tar.gz
As mentioned in the comments, your problem seemed to be that you were define
ing modules within the same file that you were requiring those modules in, and that I believe was causing r.js to believe that these modules had no main entry point. The convention is to separate out module definitions from files that require those modules.
Notice there's an app
folder now under assets/js
where each module that used to be define
d within your page modules is now stored. Your page modules now require
these modules in. When I re-ran r.js
(using uglify2 as the optimizer) everything seemed to work as expected.
Furthermore, I removed some redundancy from your build.js file (you only have to specify baseUrl in your mainConfigFile if that's the one you're using for your build configuration as well). Finally, you may want to look into using the shim config if you want to attach jQuery and Bootstrap globally to every page. Otherwise you should just explicitly list them as dependencies when you need them.
Finally as one last piece of advice you may want to look at cutting down on the number of require
within each file. For most of those pages you could wrap everything in one require call and then just separate out different logic into functions to save some space on the event queue and also some cycles of having to redundantly call the require
function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With