Variable in require path not working with r.js - javascript

I am new to r.js optimization but a fan of requirejs
build-config.js
({
appDir: "./src/main/webapp/webresources/javascript/",
baseUrl: "./",
dir: "./target/webresources/js",
optimizeCss: "none",
mainConfigFile: "./src/main/webapp/webresources/javascrip/app.js",
inlineText: true,
removeCombined: true,
modules: [
{
name: "app",
}
]
})
app.js looks something like
if (typeof _JSHome=== "undefined") {
_JSHome = "/webresources/javascript/edulastic";
}
if (typeof EditorValue === "undefined") {
EditorValue = "";
}
require.config({
baseUrl: '/webresources/javascript',
waitSeconds: 180,
paths: {
tpl : _JSHome+'/js/tpl',
underscore : 'underscore-min',
backbone : 'backbone-min',
text : 'text/text',
jquery : 'jquery',
jqueryuitouchpunch : "jquery.ui.touch-punch",
modernizr : 'modernizr',
hammer : 'hammer.min',
detectizr : 'detectizr',
bootstrap : _edulasticJSHome+'/bootstrap/js/bootstrap.min',
fastClick : "mobileutils/fastclick/fastclick.min",
asMetaData : _JSHome+'/js/app/metaData',
highCharts : '/webresources/javascript/highcharts/highcharts-min',
},
});
When I run
r.js -o build-config.js in my project root directory, I'm getting the following error :
Try only using a config that is also valid JSON, or do not use mainConfigFile and instead copy the config values needed into a build file or command line arguments given to the optimizer.
Source error from parsing: e:/mongrel_mpq/src/main/webapp/webresources/javascript/app.js: > ReferenceError: _JSHome is not defined
Duplicate but without solution - Require.js optimizer and variables in paths

The configuration you have in app.js is a computed configuration. For instance, you set _JSHome to a value and then use it in the configuration. At runtime, there is no problem with this. However, r.js is not designed to execute what you pass to mainConfigFile. What it does is look for a JSON object that is passed to require.config (or requirejs.config) and uses the JSON object. It is as if r.js were to go into your app.js file and copy all the text inside require.config(...) and then paste it into its own execution context. When it tries to use what it captured from your app.js file, you get the error that _JSHome is not defined because in the context where r.js interprets your configuration, _JSHome is not defined.
The simple solution would be to have a configuration which is not computed. However, if you need to have a computed configuration, then to get r.js to work with it, it needs to be computed before r.js sees it. This could be done as part of a build system (with Grunt, Gulp, make, etc.).

Related

Issues with require.js and sourcemaps when compiling typescript with grunt-ts

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.

Systemjs builder remove file extension

I have couple of es6 modules. add.js, sub.js and calc.js.
calc.js imports add.js and sub.js.
I am building them with grunt and SystemJS builder. My grunt configuration for this looks like -
systemjs: {
es6: {
options: {
baseURL: "/",
configFile: "config.js",
},
files: [{
"src": ["src/main/calc.js"],
"dest": "dist/calc.js"
}]
}
}
Once the grunt build is done, it creates the resultant calc.js and in that file I can see this :
System.register("src/main/calc.js", [..
..................
I don't want the .js in that name. I want it something like :
System.register("src/main/calc", [..
What should I do? Am I missing some configuration ?
This naming behavior is by design. bundle() creates a bundle for SystemJs to use in the browser, so the names must match the file names that SystemJs will be attempting to load. If you are trying to avoid SystemJs in the browser, buildStatic() is what you are looking for.
There is paths option for the builder.
paths: {
"src/main/calc": "src/main/calc.js"
}
FYI, there is map option. I thought map would be the option for the purpose but it never worked for me.

How do I tell RequireJS to look in a subdir for certain modules?

I am not sure if this is possible, I've tried with a wildcard * in the paths config.
I want to load requested modules named jquery/* from subdir libs/jquery/src, but other files should be loaded in relation to baseUrl. This is what I've tried:
({
baseUrl: ".",
name: "main",
out: "main.build.js",
paths: {
"jquery/*": "libs/jquery/src"
}
})
Is this possible, one way or another?
Example:
require([
"jquery/ajax.js",
"view/table.js"
], function(tableView){
var t = new tableView;
return {
tableView: tableView
};
});
Would load jquery/ajax.js from ./libs/jquery/src/ajax.js and view/table.js from ./view/table.js.
Edit
I have also tried with this paths config:
paths: {
"jquery": "libs/jquery/src"
}
In both cases I get this error: Error: Error: ENOENT, no such file or directory 'Development/rjs/jquery/ajax.js' while the expected path to look at is Development/rjs/libs/jquery/src/ajax.js
There is no actual pattern matching. However, RequireJS can match the start of a path to replace it with something else so you could do:
paths: {
"jquery": "libs/jquery/src"
}
With this, then if you do:
require(["jquery/foo"], ...);
RequireJS will seek libs/jquery/src/foo.js. Of course this will be problematic if you happen to want to load the whole of jQuery as jquery.
This won't work if you put extensions in your dependencies. You have to remove the .js from your module names, otherwise RequireJS treats the name as a literal path and won't go through paths.

How to exclude urlArgs from build using r.js

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

How to add a plugin to the requirejs r.js optimizer, that only runs during build?

I'm trying to write a custom script/plugin to be included in the requireJS r.js optimizer (for fingerprinting static files and one for bundling JSON resources).
What I have not figured out is how to trigger my custom-optimizer during the build process. I can write the scripts allright, but how would I trigger a bundle-build.js module during optimization.
Thanks for hints!
EDIT:
I know I can use 'onBuildRead/Write', but this is not the place to add a optimizer plugin. Something like require-css is closer, but a file prefix, which triggers the plugin, which has a pluginBuilder specified to use during build. Not quite what I'm looking for.
Optimizer should pickup all files that are specified as dependencies. If you need to include something extra then you can add extra logic using onBuildRead or onBuildWrite callback, where you can add/remove extra stuff:
({
name: 'main',
baseUrl: '../',
// optimize: 'none',
optimize: 'uglify2',
exclude: ['jquery'],
mainConfigFile: '../main.js',
out: '../main.min.js',
// A function that if defined will be called for every file read in the
// build that is done to trace JS dependencies.
// Remove references to console.log(...)
onBuildRead: function (moduleName, path, contents) {
return contents;
// return contents.replace(/console.log(.*);/g, '');
},
onBuildWrite: function (moduleName, path, contents) {
// Add extra stufff;
return contents;
}
})

Categories

Resources