My app has been working fine but today I decided to give r.js a swirl.
Right now my tree(part of it) looks like
index.html
assets
js
require.js
r.js
main.js
components
underscore.js
jquery.js
backbone.js
jqueryuijs
models
election.js
collections
elections.js
views
app.js
election.js
in my index.html file I have
<script data-main="assets/js/main" src="assets/js/require.js"></script>
and this is main.js
require.config({
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
underscore: 'components/underscore/underscore-min',
backbone: 'components/backbone/backbone-min',
jqueryui: 'components/jqueryui/jquery-ui-1.10.1.custom.min'
},
shim: {
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'jqueryui': ['jquery']
}
});
require(['views/app'], function(App) {
var router = Backbone.Router.extend({
routes: {
'': 'root',
'year(/:year)': 'year'
},
root: function() {
new App();
},
year: function(year) {
new App({
year: year
});
}
});
r = new router();
Backbone.history.start({
// pushState: true
});
});
and in my modules I refer to my files like assets/js/views/election.js or assets/js/models/election.js
but when I run r.js with this build.js
({
// baseUrl: "assets/",
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
underscore: 'components/underscore/underscore-min',
backbone: "components/backbone/backbone-min",
jqueryui: 'components/jqueryui/jquery-ui-1.10.1.custom.min'
},
name: "main",
out: "main-built.js"
})
I get Error: ENOENT, no such file or directory '/Users/alex/Dropbox/www/animated-elections/assets/js/assets/js/collections/elections.js'. I get what it means by I don't understand why it is adding another assets/js to my paths.
I believe require.js is supposed to go in the same folder as the main file, ie. next to the assets folder instead of inside it.
r.js is inside your app directory, instead of being a sibling to it, as specified in the example setup.
I haven't tested this but r.js is probably assuming that any module calls should be relative to where it's located.
Add in the build.js file this codes.
baseUrl: ".",
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
underscore: 'components/underscore/underscore-min',
backbone: "components/backbone/backbone-min",
jqueryui: 'components/jqueryui/jquery-ui-1.10.1.custom.min',
'views/app': 'empty:',
'views/election': 'empty:',
//and so with others
},
name: "main",
out: "main-built.js"
Regards.-
Related
I've designed this application to have a main.js file, which is executed on all pages. Where applicable, I am creating JavaScript files per page. The per-page JS is executing fine, but I notice main.js often only loads on a hard refresh which included with a per-page javascript file. I'll illustrate the setup below:
<script src="/admin/js/require.config.js"></script>
<script src="/admin/js/lib/require.js" data-main="./app/user/form"></script>
require.config.js
var require = {
baseUrl: '/admin/js',
paths: {
main: 'app/main',
bootstrap: 'lib/bootstrap',
"datatables.net": 'lib/jquery.datatables',
datepicker: 'lib/bootstrap-datetimepicker',
dropzone: 'lib/dropzone',
moment: 'lib/moment',
notify: 'lib/bootstrap-notify',
paper: 'lib/paper-dashboard',
jquery: 'lib/jquery',
select: 'lib/bootstrap-select',
sortable: 'lib/Sortable.min',
swal: 'lib/sweetalert2',
switchTags: 'lib/bootstrap-switch-tags',
wizard: 'lib/jquery.bootstrap.wizard.min',
validate: 'lib/jquery.validate.min',
yummySearch: '/yummy/js/yummy-search',
zxcvbn: 'lib/zxcvbn'
},
shim:{
bootstrap:{
deps: ['jquery']
},
validate: {
deps: ['jquery']
},
wizard:{
deps: ['bootstrap']
},
select:{
deps: ['bootstrap']
},
datepicker:{
deps: ['bootstrap','moment']
},
switchTags:{
deps: ['bootstrap']
},
paper: {
deps: ['bootstrap','switchTags']
},
notify: {
deps: ['jquery','bootstrap']
},
"datatables.net": {
deps: ['jquery']
},
main: {
deps: ['paper','notify','moment','datepicker','swal']
}
},
deps: ['main']
};
main.js
require(['jquery','swal','yummySearch','notify'], function($, swal) {
console.log('does not always execute');
});
app/user/form.js
define(['jquery','swal','validate','datatables.net'], function($,swal) {
console.log('will always run when loaded via data-main');
})
I am open to redoing this architecture if there are better ways, but would like to at least figure out this problem I am experiencing.
As far as I know, deps property in the requirejs config is an array of dependencies to load. Useful when require is defined as a config object before require.js is loaded, and you want to specify dependencies to load as soon as require() is defined. Saying that, it only happens once, exactly when the require.js is loaded and is the reason your main.js only execute once.
Note that using deps is just like doing a require([]) call to any other module, but done as soon as require.js is loaded and the loader has processed the configuration.
If you want your main.js to run on every page, then you will need to manually required
app/user/form.js
define(['main','jquery','.... other deps'], function(main, $, others) {
console.log('main will always run');
})
I recently worked on a web app, and i wanted to separate it into modules.
I searched and found out that RequireJs is the best for this. I read the doc, and some tutorials about it and came up with this
requirejs.config({
baseUrl: "js/lib",
shim: {
'jquery-1.12.1.min': ['jquery-1.12.1.min'],
'materialize.min': ['materialize.min'],
'knockout-3.4.0': ['knockout-3.4.0'],
'pouchdb-5.3.0.min': ['pouchdb-5.3.0.min']
},
waitSeconds: 0,
paths: {
'jquery-1.12.1.min': 'jquery-1.12.1.min',
'materialize.min': 'materialize.min',
'knockout-3.4.0': 'knockout-3.4.0',
'pouchdb-5.3.0.min': 'pouchdb-5.3.0.min',
}
});
require(["jquery-1.12.1.min", "knockout-3.4.0", "materialize.min", "pouchdb-5.3.0.min"], function($, ko) { //My main functions and other stuff ... }
My index has the following:
<script data-main="js/main" src="js/lib/require.js"></script>
<script type="text/javascript" src="js/converter.js"></script>
But it seems that my Jquery, KO, materialize.css and pouchdb aren't loading as i see on my chrome dev tools in Network:
I also read about the shim config how to set up the dependences and i want them in that order. I don't really know what am i missing, any help would really be appreciated.
Folder structure is:
js:
lib:
->jquery-1.12.1.min.js
->knockout-3.4.0.js
->pouchdb-5.3.0.min.js
->materialize.min.js
->require.js
main.js
converter.js
Ok it seems require and materialze.css have a problem with hammer.js, what i recommend is you go and download Hammer.min.js and include it in your lib folder.
Then in your main.js add the following:
requirejs.config({
baseUrl: 'js/lib',
waitSeconds: 0,
paths: {
app: '../app',
jquery: 'jquery-1.12.1.min',
materialize: 'materialize.min',
knockout: 'knockout-3.4.0',
pouchdb: 'pouchdb-5.3.0.min',
hammer: 'hammer.min'
},
shim: {
hammer: {
deps: ['jquery']
},
pouchdb: {
deps: ['jquery']
},
knockout: {
deps: ['jquery'],
exports: 'ko'
},
materialize: {
deps: ['jquery', 'hammer'],
},
jquery: {
exports: '$'
}
}
});
You include you hammer and also the dependency for jquery on it. And i see that you didn't put the PouchDb object in the function:
define(["jquery", "knockout", "pouchdb", "materialize" ], function($, ko, PouchDB) {...
Hope this helps
Using path, requirejs replace module id prefixes (name in config) with the corresponding value.
Using shim you can export a global variable and configure the dependencies ( materialize depends jquery so you have to import jQuery before importing materialize.js )
requirejs.config({
baseUrl: "js/lib",
waitSeconds: 0,
paths: {
'jquery': 'jquery-1.12.1.min',
'materialize': 'materialize.min',
'knockout': 'knockout-3.4.0',
'pouchdb': 'pouchdb-5.3.0.min',
'hammer': 'hammer.min',
},
shim: {
pouchdb: {
deps: ['jquery']
},
knockout: {
exports: 'ko'
},
materialize: {
deps: ['jquery', 'hammer']
},
jquery: {
exports: '$'
}
}
});
require(["jquery", "knockout", "materialize", "pouchdb"], function ($, ko) {
console.log($);
console.log(ko);
});
I have a quite large app built with RequireJS and I'm trying optimise the modules with r.js.
But no matter what I do, I always get the same annoying error.
me: ~/WORK/LAB/require_r_js/js
→ r.js -o build.js
Optimizing (standard.keepLines.keepWhitespace) CSS file: /<path_to_my_js_folder>/js/dist/vendor/tinyscrollbar/tinyscrollbar.css
Tracing dependencies for: utils/Vendor
Error: ENOENT, no such file or directory
'/<path_to_my_js_folder>/js/dist/TweenLite.js'
In module tree:
utils/Vendor
cssplugin
It looks like my path cssplugin is been ignored, here is my build.js file:
{
mainConfigFile : "core/commom.js",
appDir: '.',
baseUrl: ".",
removeCombined: true,
findNestedDependencies: true,
dir: "./dist",
paths: {
tweenlite: "vendor/greensock/TweenLite.min",
cssplugin: "vendor/greensock/plugins/CSSPlugin.min",
easepack: "vendor/greensock/easing/EasePack.min",
jquery: "vendor/jquery/jquery-1.11.2.min",
signals: "vendor/signals/signals",
underscore: "vendor/underscore/underscore-min",
retina: "vendor/retinajs/retina-1.1.0",
tinyscrollbar: "vendor/tinyscrollbar/jquery.tinyscrollbar.min",
async: 'vendor/millermedeiros/requirejs-plugins/async',
simpleWeather: 'vendor/simpleWeather/jquery.simpleWeather.min'
},
shim: {
underscore: {
exports: "_"
},
jquery: {
exports: "jQuery"
},
simpleWeather: {
exports: "simpleWeather",
deps: ["jquery"]
}
},
modules: [
{ name: "utils/Vendor" },
{
name: "core/Main",
exclude: ['utils/Vendor']
},
{
name: "controllers/MapsHome"
},
{
name: "controllers/SuperHome"
},
{
name: "controllers/Register"
},
{
name: "controllers/hotel/HotelHome"
}
]
}
Well.. I know it looks a lot of information, but this is my commom.js file (the RequireJS config):
(function() {
requirejs.config({
baseUrl: "../",
waitSeconds: 120,
paths: {
tweenlite: "vendor/greensock/TweenLite.min",
cssplugin: "vendor/greensock/plugins/CSSPlugin.min",
easepack: "vendor/greensock/easing/EasePack.min",
jquery: "vendor/jquery/jquery-1.11.2.min",
jmask: "vendor/igorescobar/jquery-mask-plugin.min",
signals: "vendor/signals/signals",
underscore: "vendor/underscore/underscore-min",
retina: "vendor/retinajs/retina-1.1.0",
tinyscrollbar: "vendor/tinyscrollbar/jquery.tinyscrollbar.min",
async: 'vendor/millermedeiros/requirejs-plugins/async',
simpleWeather: 'vendor/simpleWeather/jquery.simpleWeather.min'
},
shim: {
underscore: {
exports: "_"
},
jquery: {
exports: "jQuery"
},
simpleWeather: {
exports: "simpleWeather",
deps: ["jquery"]
},
facebook: {
exports: 'FB'
}
}
});
}).call(this);
The files are organized in this structure:
Well, in my website the scripts are loaded as this:
<script type="text/javascript">
require([globalServerConf.requireJSConfURL], function() {
require(['core/Main'], function(Main) {
var m = new Main();
// The name of the Page Controller is set by a PHP Variable:
m.init("{{$jsController}}");
});
});
</script>
So, a global JS object (built by a PHP script) has the URL to the requirejs.config object. When commom.js is loaded, RequireJS asks for core/Main.js file. When core/Main is loaded, it will ask first for the utils/Vendor module. This module loads all third part scripts (like jQuery, TweenLite, CSSPlugin, etc etc). Only when these files are loaded, Main.js asks for the page controller file (which makes use of many other files as well).
So, I am trying to build with r.js all these modules:
All third part scripts: utils/Vendor
Main script: core/Main
All other main pages controllers:
controllers/MapsHome, controllers/SuperHome, controllers/Register, controllers/hotel/HotelHome
Every time I run r.js, tweelite or cssplugin makes that error and the optimization is killed.
Right now in my header I've got this code:
<script src="/js/libs/requirejs/requirejs.min.js"></script>
<script>
require.config({
baseUrl: "/js/libs",
paths: {
jquery: "jquery/jquery-1.11.1.min",
jqueryUi: "jquery-ui/mapa/js/jquery-ui-1.10.4.custom.min",
portal: "../dev/portal"
},
shim: {
"jqueryUi": {
export:"ui" ,
deps: ['jquery']
}
}
});
require( ["portal"], function(portal) {
portal.config={'var': 'value'};
portal.init();
}
);
</script>
I want to do it the right way using data-main attr:
<script data-main="/js/build/req-init" src="/js/libs/requirejs/requirejs.min.js"></script>
<script>
require( ["portal"], function(portal) {
portal.config={'var': 'value'};
portal.init();
}
);
</script>
and move all require.config to that file (/js/build/req-init.js).
Problem is that it searches potral.js file in root directory because data-main file isn't loaded yet and it doesn't know paths. How to delay execution of require(["portal"]) ?
I need to have portal.init() in HTML because of portal.config - variables will be defined with php.
I have apply a different pattern in our html5 application to move requireJS config to an external file.
directory structure
{webroot}/
html/
js/
apps/
conf.js
main.js
libs/
jquery-1.11.1.min.js
...
../js/app/conf.js
var require = {
baseUrl: "../js",
paths: {
app: "../js/app",
libs: "../js/libs",
jquery: "libs/jquery/jquery-1.11.1.min",
jqueryUi: "libs/jquery-ui/mapa/js/jquery-ui-1.10.4.custom.min",
portal: "../dev/portal"
},
shim: {
"jqueryUi": {
export:"ui" ,
deps: ['jquery']
}
}
});
../js/app/main.js
require( ["portal"], function(portal) {
portal.config={'var': 'value'};
portal.init();
}
);
inside html
<scrip src="/js/app/conf.js"></script>
<script data-main="app/main" src="/js/libs/requirejs/requirejs.min.js"></script>
the trick is to use your config in a little different format and load it before your main script. This is the only way which is really reliable to load an "external" config in all cases:
config.js:
var require = {
baseUrl: "/js/libs",
paths: {
jquery: "jquery/jquery-1.11.1.min",
jqueryUi: "jquery-ui/mapa/js/jquery-ui-1.10.4.custom.min",
portal: "../dev/portal"
},
shim: {
"jqueryUi": {
export:"ui" ,
deps: ['jquery']
}
}
};
req-init.js
require( ["portal"], function(portal) {
portal.config={'var': 'value'};
portal.init();
});
html:
<script type="text/javascript" src="config.js"></script>
<script data-main="/js/build/req-init" src="/js/libs/requirejs/requirejs.min.js"></script>
http://requirejs.org/docs/api.html#config
for further optimizations (because I see you have a build folder) I would concatenate the config.js with the requirejs.min.js (config before require) to lose a request
I'm going a bit crazy here. I'm trying to use Grunt to go through a large RequireJS-based project and combine and minify the results during the deployment process. Here is my grunt process (using grunt-contrib-requirejs):
requirejs: {
compile: {
options: {
baseUrl: "public/js",
mainConfigFile: "public/js/config.js",
name: 'config',
out: "public/js/optimized/script.min.js",
preserveLicenseComments: false
}
}
}
Initially, I was taking the outputted script and placing it in the HTML -- but this lead to the 'define is undefined' error that means that RequireJS wasn't evoked. So instead, I'm putting in the HTML like this:
<script data-main="js/optimized/script.min" src="js/vendor/require.js"></script>
However, now I'm only getting a blank page.
The closest thing I can find out there that sounds like this is here, but's not being super helpful right now. For reference, I was using this as a starting point of my project -- however, when I run it, everything seems to be working for them but I can't find the differences.
Here is my config.js file:
require.config({
//Define the base url where our javascript files live
baseUrl: "js",
//Increase the timeout time so if the server is insanely slow the client won't burst
waitSeconds: 200,
//Set up paths to our libraries and plugins
paths: {
'jquery': 'vendor/jquery-2.0.3.min',
'underscore': 'vendor/underscore.min',
'backbone': 'vendor/backbone.min',
'marionette': 'vendor/backbone.marionette',
'mustache': 'vendor/mustache.min',
'bootstrap': 'vendor/bootstrap.min',
'bootbox': 'vendor/bootbox.min',
'jquery-ui': 'vendor/jquery-ui-1.10.2',
'app-ajax': '../conf/app-ajax',
'common': 'common',
'moment': 'vendor/moment.min'
},
//Set up shims for non-AMD style libaries
shim: {
'underscore': {
exports: '_'
},
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'marionette': {
deps: ['backbone', 'underscore', 'jquery'],
exports: 'Marionette'
},
'mustache': {
exports: 'mustache'
},
'bootstrap': {
deps: ['jquery']
},
'bootbox': {
deps: ['jquery', 'bootstrap'],
exports: 'bootbox'
},
'jquery-ui': {
deps: ['jquery']
},
'jquery-layout': {
deps: ['jquery', 'jquery-ui']
}
}
});
//Initalize the App right after setting up the configuration
define([
'jquery',
'backbone',
'marionette',
'common',
'mustache',
'bootbox',
'controllers/GlobalController',
'routers/GlobalRouter'
],
function ($, Backbone, Marionette, Common, Mustache, bootbox) {
//Declare ECMAScript5 Strict Mode first and foremost
'use strict';
//Define the App Namespace before anything else
var App = Common.app_namespace || {};
//Create the Marionette Application
App.Application = new Marionette.Application();
//Add wrapper region, so we can easily swap all of our views in the controller in and out of this constant
App.Application.addRegions({
wrapper: '#wrapper'
});
// Set up Initalizer (this will run as soon as the app is started)
App.Application.addInitializer(function () {
//Reach into Marionette and switch out templating system to Mustache
Backbone.Marionette.TemplateCache.prototype.compileTemplate = function (rawTemplate) {
return Mustache.compile(rawTemplate);
};
var globalController = new App.Controllers.GlobalController();
var globalRouter = new App.Routers.GlobalRouter({
controller: globalController
});
//Start Backbone History
Backbone.history.start();
});
//Start Application
App.Application.start();
}
);
Okay, so this is the crazy simple fix:
In the module that's declared after the require.config, use 'require' instead of 'define' when declaring the module.
If you use 'define', it added 'config' as a dependency of that module, which broke the whole thing. Craziness!