We already have a AMD implementation with require.js which is being used for a long time and now team has decided to use r.js optimizer to optimize the build. I am following the steps but I think I am missing something:
We have require.config which looks like the following:
require.config({
waitSeconds : 15,
baseUrl: window.rootPath + 'scripts',
paths: {
jquery: 'empty:',
jqueryui: 'empty:',
recaptcha: '//www.google.com/recaptcha/api/js/recaptcha_ajax',
maxmind: '//j.maxmind.com/app/geoip',
enduser: '/enduser/scripts/system',
cookies: '/enduser/scripts/system/cookies',
errorhandler: '/enduser/scripts/system/errorhandler',
underscore: '/enduser/scripts/underscore',
blockui: '/enduser/scripts/jquery.blockui',
messaging: '/enduser/scripts/system/messaging',
jgrowl: '/enduser/scripts/jquery.jgrowl',
knockout: 'knockout-latest.debug',
kobindings: '/enduser/scripts/system/bindings',
async: 'plugins/require/async',
depend: 'plugins/require/depend',
font: 'plugins/require/font',
goog: 'plugins/require/goog',
image: 'plugins/require/image',
json: 'plugins/require/json',
noext: 'plugins/require/noext',
mdown: 'plugins/require/mdown',
propertyParser: 'plugins/require/propertyParser',
markdownConverter: 'lib/Markdown.Converter'
},
priority: ['jquery']
});
require(["main"]);
Please note that it has CDN paths instead of "empty". But I replaced empty there after reading some threads online. I am running following command on that:
node -o name="filepath" output="output file path"
It's saying tracing dependencies and then it throws an error saying it did not find jquery.js. Any suggestions?
Well basically the solution to this was to include paths.jquery=empty: at the end of the command. so my command looks like node -o name="filepath" output="output file path" paths.jquery=empty:. This also applies to any CDN that you are using including Jquery.
Related
When using grunt-ts and specifying and out file my app runs as expected, but since that option has no support for fast compilation, i tried using a regular compilation where all my .ts files live on the dist folder
There are two issues, first, it will fail to load any imported file, since it will try to look for it without extension. As a quick fix i edited the load fn on the require.js file and all my dependencies load correctly, but then the sourcemaps stopped working, all i get is a blank file on the chrome inspector (and of course i don't want to rely on a dirty hack) .
Please note that i'm not very familiar with requirejs so I'm not quite sure if this is a misconfiguration on my side, a bug, or something that is missing.
My grunt config, related to ts
ts: {
options: {
module: 'amd',
target: 'es5',
experimentalDecorators: true
},
dev: {
src: ['client-app/**/*.ts'],
outDir: "dist",
watch: '.'
}
},
My bootstrap.js which is just the entry point and require.js config file
requirejs.config({
baseUrl: '.',
waitSeconds: 20
});
requirejs(['/init'], function(module) {
module.main()
});
A simplified version of the compiled init file
define(["require", "exports", './section-manager.view'], function (require, exports, section_manager_view_1,) {
"use strict";
function main() {
///
}
exports.main = main;
});
//# sourceMappingURL=init.js.map
And the html
<script src="/js/lib/require.js" data-main="/bootstrap"></script>
Any help is appreciated, thanks
Edit:
Using System.js or #Luis answer solves the loading issue.
The sourcemap issue is solved by using sourceRoot or
inlineSourceMap: true,
inlineSources: true
To the ts options
Don't use an absolute module name. If you do use an absolute name, RequireJS assumes that you do not want any alteration when it generates a path from the module name and will not add the .js extension. You should use a relative path, or you could do this:
requirejs.config({
baseUrl: '/'
});
requirejs(['init'], function(module) {
module.main()
});
By doing this, RequireJS will automatically add the .js extension.
This code uses the requirejs.shimConfig to load the jQuery.mCustomScrollbar plugin:
requirejs.config({
baseUrl:'scripts',
paths:{
async:'lib/plugins/async',
domReady:'lib/plugins/domReady',
jquery:"http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min",
"jquery.mCustomScrollbar":"lib/plugins/jquery.mCustomScrollbar.concat.min"
},
shim:{
"jquery.mCustomScrollbar":{
deps:['jquery'],
exports:'jQuery.fn.mCustomScrollbar'
}
}
});
However the Chrome console shows that requirejs tries to load the file from the baseUrl:
GET http://localhost:8180/GoogleMapErpProject/scripts/jQuery.mCustomScrollbar.js 404 (Not Found) require.js:34
Uncaught Error: Script error for: jQuery.mCustomScrollbar
http://requirejs.org/docs/errors.html#scripterror
EDIT:
I have found an unsatisfactory solution to the issue:
requirejs.config({
baseUrl:'scripts',
paths:{
async:'lib/plugins/async',
domReady:'lib/plugins/domReady',
jquery:"http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min",
plugins:"lib/plugins"
},
shim:{
"jquery":{
exports:"jQuery"
},
"plugins/jquery.mCustomScrollbar.concat.min":{
deps:['jquery'],
exports:'jQuery.fn.mCustomScrollbar'
}
}
});
Why would it not work when I specified a path in the paths and used that path in the shimConfig?
from require.js documentation,
baseUrl: the root path to use for all module lookups. So in the above
example, "my/module"'s script tag will have a
src="/another/path/my/module.js". baseUrl is not used when loading
plain .js files (indicated by a dependency string starting with a
slash, has a protocol, or ends in .js), those strings are used as-is,
so a.js and b.js will be loaded from the same directory as the HTML
page that contains the above snippet.
Hence paths should/can be like this:
paths:{
async:'lib/plugins/async',
domReady:'lib/plugins/domReady',
jquery:"http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min",
"jquery.mCustomScrollbar":"/lib/plugins/jquery.mCustomScrollbar.concat.min"
},
or
paths:{
...
"jquery.mCustomScrollbar":"./lib/plugins/jquery.mCustomScrollbar.concat.min"
},
or
paths:{
...
"jquery.mCustomScrollbar":"lib/plugins/jquery.mCustomScrollbar.concat.min.js"
},
if you dont want it to get loaded from baseUrl.
I was under the impression that the RequireJS Optimizer would look through the defined dependencies and gather up all of the referenced js files in an application and bundle them up into a single, large js file.
You'd then be able to reference that single file in your html script include.
But this doesn't seem to be the case. When I run this, I get a large file, but it includes the original main.js file that includes paths to files in a directory structure.
What is the point of that? Why does the new large file contain paths outside of itself if everything needed is contained within? It seems like the optimizer would rewrite the paths to point to "./" or something.
When I bundle up the entire app and reference that in the page, I'm getting errors about missing files that ARE included in the large js file:
Uncaught object require.js:70
GET http://localhost/ui/js/modules/mod_limeLight.js 404 (Not Found) require.js:729
Uncaught Error: Script error for: mod_limelight
http://requirejs.org/docs/errors.html#scripterror
build.js:
({
baseUrl: "./src/ui/scripts",
name: "main",
mainConfigFile : "src/ui/scripts/main.js",
out: "dist/ui/scripts/main-built.js"
})
main.js
'use strict';
require.config({
"paths": {
"jquery": "libs/jquery-1.11.0.min",
"twitter_bootstrap": "../bower_components/bootstrap/dist/js/bootstrap.min",
"respondjs": "../bower_components/respond/dest/respond.min",
"debouncejs": "libs/dw-debounce",
"carousel": "libs/jquery.carouFredSel-6.2.1-packed",
"swipe": "libs/jquery.touchSwipe.min",
"app": "app",
"OOo_config": 'libs/oo_conf_entry-ck', // Opinion Lab pop-up
//modules
"addthis": "//s7.addthis.com/js/300/addthis_widget",
"mod_addThis": "modules/mod_AddThis",
"limelight": "//assets.delvenetworks.com/player/embed",
"mod_limelight": "modules/mod_limeLight"
},
"shim": {
"twitter_bootstrap": ["jquery"],
"carousel": ["jquery"],
"swipe": ["jquery"],
"packeryjs": ["jquery"]
}
});
require([
"jquery",
"app",
"OOo_config",
"respondjs",
"mod_addThis",
"mod_limelight"
], function ($, app) {
app.init();
});
example module starts off like:
define([
"jquery", "debouncejs", "limelight"
],
function ($) {
'use strict';
var playerElement = ...
});
Then running:
node r.js -o build.js
What am I missing? Why is it trying to fetch files that are contained in that large js file?
Thanks,
Scott
It identifies the included modules using their usual paths, because that’s simple and unambiguous, and it works. The files aren’t fetched, of course.
I use r.js optimizer to combine js files based on build profile as it's suggested in documentation. Here's my build-config.js:
({
baseUrl: ".",
paths: {
jquery: '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
},
name: "main",
out: "main-built.2013-07-30.js"
})
As you can see it's based upon main.js file, here's a code of it:
requirejs.config({
baseUrl: 'scripts',
urlArgs: "bust=" + (new Date()).getTime(),
paths: {
jquery: [
'//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min',
'lib/jquery-1.9.1.min',
],
},
});
require([
'layout',
'cue',
], function() {
});
If I preserve urlArgs: "bust=" + (new Date()).getTime() in main.js all external files (here jquery which is loaded from CDN) look like .../jquery.js?bust=1377412213
So it's PITA to comment out this line every time I make a build. I've read through all the documentation and googled for a solution but everything in vain. Maybe I do it wrong?
Way late to the party on this, but here the solution I used: append the urlArgs param to the config with a subsequent call.
HTML:
<script src="js/libs/require.js"></script>
<script src="js/config.js"></script>
<script>require(['main-app']);</script>
Config File:
requirejs.config({
paths: {...},
shim: {...}
});
// Apply the cache bust only for the browser.
if (window) {
requirejs.config({
urlArgs: REQUIRE_NOCACHE ? "bust="+(new Date()).getTime() : null
});
}
The optimizer only takes the first requirejs.config declaration and it ignores the subsequent code. The second requirejs.config declaration extends rather than overrides the first, so urlArgs is still successfully applied to modules in the browser. Hope that helps.
The following solution would work in your case, where you're renaming the main.js file in the r.js build:
urlArgs: require.specified('main') ? "bust="+(new Date()).getTime() : null
The above snippet will check for the module named 'main', which will match in development, but not in production, where the module is named 'main-built.2013-07-30'.
I've tested in development and production builds and it works! :-)
On the require.specified() function:
With requirejs is it possible to check if a module is defined without attempting to load it?
As of version 2.2.0, urlArgs now accepts functions.
It sends the moduleId and the url, so you can segment depending on the path if it should have extra args or not. See https://requirejs.org/docs/api.html#config-urlArgs
I'm having pretty simple directory structure for scripts:
/js/ <-- located in site root
libs/
jquery-1.10.1.min.js
knockout-2.2.1.js
knockout.mapping.js
models/
model-one.js
model-two.js
...
require.js
config.js
Since the site engine uses clean URLs I'm using absolute paths in <script>:
<script type="text/javascript" data-main="/js/config.js" src="/js/require.js"></script>
RequireJS config:
requirejs.config({
baseUrl: "/js/libs",
paths: {
"jquery": "jquery-1.10.1.min",
"knockout": "knockout-2.2.1",
"komapping": "knockout.mapping"
}
});
Somewhere in HTML:
require(["jquery", "knockout", "komapping"], function($, ko, mapping){
// ...
});
So the problem is that RequireJS completely ignores baseUrl and paths defined in config file. I get 404 error for every module required in the code below. I see in browser console that RequireJS tries to load these modules from /js/ without any path translations:
404: http://localhost/js/jquery.js
404: http://localhost/js/knockout.js
404: http://localhost/js/komapping.js
However after the page is loaded and the errors are shown I type in console and...
> require.toUrl("jquery")
"/js/libs/jquery-1.10.1.min"
Why so? How to solve this problem?
It's my first experience using RequireJS, so I'm feeling like I've skipped something very simple and obvious. Help, please.
Update
Just discovered this question: Require.js ignoring baseUrl
It's definitely my case. I see in my Network panel that config.js is not completely loaded before require(...) fires own dependency loading.
But I don't want to place my require(...) in config because it is very specific for the page that calls it. I've never noticed such problem with asynchronicity in any example seen before. How do authors of these examples keep them working?
Solved.
The problem was that config file defined in data-main attribute is loaded asynchronously just like other dependencies. So my config.js accidentally was never completely loaded and executed before require call.
The solution is described in official RequireJS API: http://requirejs.org/docs/api.html#config
... Also, you can define the config object as the global variable require before require.js is loaded, and have the values applied automatically.
So I've just changed my config.js to define global require hash with proper configuration:
var require = {
baseUrl: "/js/libs",
paths: {
"jquery": "jquery-1.10.1.min",
"knockout": "knockout-2.2.1",
"komapping": "knockout.mapping"
}
};
and included it just BEFORE require.js:
<script type="text/javascript" src="/js/config.js"></script>
<script type="text/javascript" src="/js/require.js"></script>
This approach allows to control script execution order, so config.js will always be loaded before next require calls.
All works perfectly now.
Fixed the issue.
My config was being loaded asynchronously, and therefore the config paths weren't set before my require statement was being called.
As per the RequireJS docs Link here, I added a script call to my config before the require.js call. And removed the data-main attribute.
var require = {
baseUrl: '/js',
paths: {
'jquery': 'vendor/jquery/jquery-2.0.3.min',
'picker': 'vendor/pickadate/picker.min',
'pickadate': 'vendor/pickadate/picker.date.min'
},
shim: {
'jquery': {
exports: '$'
},
'picker': ['jquery'],
'pickadate': {
deps: ['jquery', 'picker'],
exports: 'DatePicker'
}
}
}
All is now working