How to skip a define getting included at the end of the bundle, When combining non-amd script files using requirejs optimizer r.js? - requirejs

I'm trying to optimize my javascript project with r.js optimizer from requirejs. I use both amd and non-amd modules in my project. There will be two environments, one with requirejs environment and the other with no requirejs environment.The files at the non-requirejs environment should not have on require or define calls. While combining amd-modules into bundles using r.js it is fine to have a define call with bundle name at the end of the file. But for the non-requirejs environment after the files have been optimized, they are also getting a define insertion at the end of the file with the module name.
Let's take I have four files A and B which are AMD-modules and C and D are non-AMD modules.
my build.js is like this
({
appDir: "../",
baseUrl: "./",
dir : "../../../output",
paths: {
A : '../somepath/to/A',
B : '../somepath/to/B'
},
modules : [
{
name : 'bundle1',
create : true,
include : ['A', 'B']
},
{
name : 'bundle2',
create : true,
include : ['C', 'D']
}
],
// removeCombined : true,
cjsTranslate: false,
optimizeCss : "none",
skipModuleInsertion: true,
optimize: "uglify",
fileExclusionRegExp: /^(((r|app.build)\.js)|(v0))$/,
keepBuildDir: false,
bundlesConfigOutFile: "bundles.js",
onModuleBundleComplete : function(data) {
console.log(data)
}
})
This is the bundles amd-file looks like.
define('A', function(){
//some stuff of A
});
define('B', function(){
//some stuff of B
});
define('bundle1',function(){});
The bundled non-amd file looks like
//some stuff of C
});
//some stuff of D
define('bundle2',function(){});
How to resolve this situation. I have gone through the optimization docs and example.build.js. still couldn't figure out the way. Am I missing something ? Is there a way to exclude that define call at the end of the non-amd-modules. If yes, How ?

I see you have used skipModuleInsertion option which based on the documentation should have helped you. I am not sure why it didn't.
Another option you can use is after the build is complete before writing to file, you can remove that particular define call using onBuildWrite

Related

RequireJS not loading a file or module named "module.js"

I just started using RequireJS. I tried a simple code but one way works but the other doesn't.
folder "script" has "main.js", "module.js", "require.js"
<script data-main="script/main.js" src="script/require.js"></script>
in main.js
requirejs( ['module'], function( mod ) {
mod.sayHello();
} );
in module.js:
define( {
name : "value",
sayHello : function() {
alert( "Hello" );
},
sayBye : function() {
alert( "Bye" );
}
} );
I expect baseUrl to be "script" as mentioned in here:
http://requirejs.org/docs/api.html#jsfiles
The baseUrl is normally set to the same directory as the script used in a data-main attribute for the top level script to load for a page.
So, I thought there would be no problem, but doesn't mod.sayHello() nor sayBye() and console.log( mod.name ) = undefined.
I tried console.log( mod ) and it prints something like this:
Object {id: "_#r6", uri: "script/_#r6.js", exports: Object}
When I use ["script/module.js"] instead of ["module"], console.log( mod ) prints like the following:
Object {name: "value"}
name: "value"
sayBye: ()
sayHello: ()
__proto__: Object
and mod.sayHello(), mod.sayBye(), mod.name all works.
including the following in the beginning of main.js is the same:
requirejs.config( {
baseUrl: "script"
} );
What am I doing wrong... Please help.
Use a different name than module for your module. For one thing, it is a terribly uninformative name, but the module named module is a special module for RequireJS. It is a module that gives information about the module you are currently in. For instance if foo.js contains this code:
define(['module'], function (module) {
console.log(module.id);
});
and this file is loaded when you request the module named foo, then console.log will show "foo" on the console.
The documentation does not highlight the existence of module but it talks about it when explaining what the configuration option config does. Because you get to access the config of your module through module.config().
The reason requiring "script/module.js" works is because when you do this you require a module named script/module.js rather than module.
I continued reading the documentation:
http://requirejs.org/docs/api.html
and it led to a github that has information about this:
https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#magic
It turns out that "module" is a kind of "magic modules" along as "require", "export".
And "module" ... :
gives you information about the module ID and location of the current module
https://github.com/jrburke/requirejs/wiki/Differences-between-the-simplified-CommonJS-wrapper-and-standard-AMD-define#module

browserify without sourcemaps

I'm using Browserify programmatically, through node, like so:
var options = {
debug: true,
cache: {},
packageCache: {},
fullPaths: true,
noParse: []
};
var b = browserify( 'index.js', options );
b.on('data', customFunction);
b.bundle();
My customFunction doesn't modify the data anyhow, just reads it.
It runs a regex on the first line, to detect the file name of the code that comes on the following lines.
The thing is, when i set options.debug to false, to get rid of the sourcemaps, the customFunction behaves in a very different way (the regex doesn't get half the file names) and i can't seem to figure out the pattern for that difference. I assume that turning debug to false, does more than turning off the sourcemaps.
I just want to turn off the sourcemaps on browserify, with no other side-effects, is this possible?
You could try to extract the source maps with a separate tool like exorcist https://github.com/thlorenz/exorcist

Is there a more concise way of including dependencies in RequireJS

Suppose I have a module that starts like the following:
define(['jquery', 'actions', 'util', 'text!../templates/dialog.html!strip', 'text!../templates/requestRow.html!strip', 'text!../templates/respondForm.html!strip'], function($, actions, util, tDialog, tRequestRow, tRespondForm) {
This module contains most of the code for writing to my client UI. It also loads a couple other modules I've written as well as 3 HTML templates using the text.js plugin. I'm wondering if there's a more concise way of doing this? As the application grows, I may have additional templates to load, or modules and it just seems like my define statement could grow to be a bit ugly. Should I just add my template paths to require.config in my main.js like this:
require.config({
baseUrl: '/webrequests/resources/scripts/',
paths: {
'modernizr': '../js/vendor/modernizr-2.6.2-respond-1.1.0.min',
'bootstrap' : '../js/vendor/bootstrap.min',
'dialog' : 'text!../templates/dialog.html!strip',
'requestRow' : 'test!../templates/requestRow.html!strip',
'respondForm' : 'text!../templates/respondForm.html!strip'
}});
Is there perhaps some way to load all templates within a directory and just have 1 dependency to include in the define statement?
Thanks in advance.
You could make a module for loading in the templates you frequently use. So group the templates to be loaded in one module, that way you can just load this template module instead of the individual templates:
// generalTemplates.js
define([
'text!../templates/dialog.html!strip',
'text!../templates/requestRow.html!strip',
'text!../templates/respondForm.html!strip'
], function (tDialog, tRequestRow, tRespondForm) {
return {
dialog: tDialog,
requestRow: tRequestRow,
respondForm: tRespondForm
};
});
So that in your module, you can simply include the templates like any other module:
define([
'jquery',
'actions',
'util',
'generalTemplates'
], function($, actions, util, templates) {
var tDialog = templates.dialog,
tRequestRow = templates.requestRow,
tRespondForm = templates.respondForm;
/* You can do stuff with the templates here */
});

How to make Backbone-Relational (0.8.5) work with RequireJS?

After another long research, sth comes out :-) It seems the problem is about the function "getObjectByName". It can not work well with requireJS(ADM). Currently, I have to setup a globel var to fix the problem. I am sure there must be have better solution.
Here is my temp soluton:
(1) setup a global var and setup the search model scope to the global ("APP")
var APP = {};
define(['backbone-relational'], function(){
Backbone.Relational.store.addModelScope(APP);
})
(2) export your relation model to the global
APP.YourRelationalModel = YourRelationModel;
It works, not good though... I'm really looking forward to a better answer. Thanks.
//------------
test versions:
1.Backbone-Relational 0.8.5
2.Backbone 1.0.0 and Underscore 1.4.4
3.JQuery 1.8.3
4.RequireJS 2.1.5
Code is very simple: (or see https://github.com/bighammer/test_relational_amd.git)
require.config({
paths : {
js : 'js',
jquery : 'js/jquery-1.8.3',
underscore : 'js/underscore',
backbone : 'js/backbone',
'backbone-relational' : 'js/backbone-relational'
},
shim : {
underscore : {
exports : '_'
},
backbone : {
deps : ['underscore', 'jquery'],
exports : 'Backbone'
},
'backbone-relational' : {
deps: ['backbone']
}
}
});
define(['backbone', 'backbone-relational'], function (Backbone) {
var Child = Backbone.RelationalModel.extend();
var Parent = Backbone.RelationalModel.extend({
relations : [
{
key : 'child',
type : Backbone.HasOne,
relatedModel : 'Child'
}
]
});
var test = new Parent();
});
save above code in main.js and included in index.html as follows:
It doesn't work. There is warning message:
Relation=child: missing model, key or relatedModel (function (){ return parent.apply(this, arguments); }, "child", undefined).
I read the source code of backbone-relational and know there is something wrong with the namespace. Relational-Backbone cannot find the relatedModel defined in "Parent" (i.e. cannot find releatedMode:"Child"). I failed to find the solution to fix this due to my limited knowledge of javascript :-)
Can anyone help me with this?
Before I asked my question, I studied the following solutions:
Backbone.RelationalModel using requireJs
Can't get Backbone-relational to work with AMD (RequireJS)
Loading Backbone.Relational using Use! plugin
None of them worked in this case.
You don't have to reference relatedModel by string, you can reference it directly, so instead of relatedModel: 'Child', just use: relatedModel: Child.
And since you are using requireJS, you can reference model from other file easily.
define(['backbone', 'models/child', 'backbone-relational'], function (Backbone, Child) {
var Parent = Backbone.RelationalModel.extend({
relations : [{
key : 'child',
type : Backbone.HasOne,
relatedModel : Child
}]
});
var test = new Parent();
});
The above solution didn't apply to me. I am gradually moving code out of Rails Asset Pipeline (not RequireJS/AMD/CommonJS/anything) into Webpack, starting with dependencies. When I moved requiring backbone-relational into Webpack bundle preparation by my models and relation definitions were still in Rails Asset Pipeline, I started getting a lot of unexplained Relation=child: missing model, key or relatedModel (function (){ return parent.apply(this, arguments); }, "child", undefined).
In my case, the solution ended up being quite simple, despite taking a long time to discover on my part:
// In a Webpack module, later included into Rails Asset Pipeline
// temporarily to facilitate migration
require('expose?Backbone!backbone') // Exposing just for migration
require('backbone-relational')
Backbone.Relational.store.addModelScope(window)
backbone-relational by default uses its global scope to resolve string-based relatedModels but since it was required without a real global scope, the solution is simply to pass that in using addModelScope so it can search that scope for the specified models.

Having trouble defining global var in require.js

I'm trying to define a global object that i can reference across all of my modules. however, in the modules, i am unable to reference my path, and it's saying that "g" does not exist.
In main1.js, i have this:
requirejs.config({
paths: {
Underscore: 'lib/underscore/1.3.3/underscore.min',
Backbone: 'lib/backbone/0.9.2/backbone.min',
Globals: 'lib/backbone/ globalVars'
}
});
require([ 'views/pages', 'views/filters'], function(allPages, filters) {
filters.render();
allPages.render();
});
inside globalVars.js, i have this:
(function() {
var Globals = {
isDemo: false
}
console.log('in globalvars') // this shows in my console
}).call(this);
and finally, inside of view/pages.js, i have this:
define([
'Globals',
'Underscore',
'Backbone'
], function(g, _, Backbone){
console.log(g.isDemo) //<-- returns "TypeError: g is undefined"
If i use a define inside my main1.js like this:
define( 'Globals', function() {
return {
isDemo: true
}
})
it works just fine. I haven't had much luck with trying to figure out why this is not working. I'd like to be able to just include a path to the globalVars rather than boilerplate pasting a define block in each and every module that needs it, since changing isDemo to false would require updating many other module pages (main2.js, main3.js, etc) as well. thanks!
Well, to start with, your globalVars.js is not in the module pattern, so requirejs doesn't know what you're trying to register as the module. If you change that file to use the pattern, like the define you added to main1.js, you should be all set. Is there a reason you aren't defining it as a module?

Resources