Separate configuration from main execution in RequireJS - javascript

I have included requirejs with the data-main entry point as described here in the docs.
<script data-main="js/app-main" src="js/lib/require.js"></script>
The app-main.js file looks like this:
requirejs.config({
baseUrl: 'js/myapp/',
...
});
requirejs(['main']);
I want to separate the require configuration from the main execution (to share the config between production and testing environments for example).
So basically I need an app.js file (with configuration only):
requirejs.config({
baseUrl: 'js/myapp/',
...
});
and the main.js file which starts the app execution (not included in testing environment).
How can I include those two files (in the correct order) with the single data-main entry point?
I have tried with an app-main.js file containing require(['app','main']); but it doesn't works.

You could ditch the data-main convenience method, and include them manually.
<script src="js/lib/require.js"></script>
<script>
// Optionally set base url depending on environment.
// Otherwise could just include in app.js
require.config({baseUrl : <% baseUrl %>})
//require app config file first
require(['app'], function() {
require(['main'])
});
</script>
Although this creates an extra HTTP request, if you are using the r.js optimizer, this shouldn't be a problem, as you can bundle require.js into the main config module.

Related

How to import remote js file(which has attributes) in another js file [duplicate]

I have an angular application with below index.html file
Consider in my index.html page I have the following code for SRI (SubResource Integrity)
<html>
<head>
<meta http-equiv="Content-Security-Policy"
content="script-src 'self' scripts/alert.js 'unsafe-inline' 'unsafe-eval' 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='">
<script src="scripts/alert.js"
integrity="sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng="
crossorigin="anonymous"></script>
</head>
</html>
In case, if I am using require JS, then I have to move the script inclusion of 'alert.js' to 'main.js' file as below
require.config({
// alias libraries paths
paths: {
'jquery': '/scripts/alert'
},
// kick start application
deps: ['../app/require.bootstrap']
})
Can someone help me how to include the integrity attribute to the main.js file while referring the alert.js script in the paths.
If I understand your question correctly, you want to use Sub Resource Integrity for scripts referenced via require js. Note, that in order to do this you need RequireJS version 2.1.19 or later (see http://requirejs.org/docs/download.html).
For a working example (referencing jQuery), see this plunker: http://plnkr.co/edit/kzqLjUThJRtoEruCCtMt?p=preview. Hopefully you should be able to copy this method to your project.
My example uses integrity/crossorigin attributes for:
RequireJS itself (through the index.html file)
jQuery (via the config file main.js and the interesting thing for you)
This is built on the RequireJS hook onNodeCreated and code like
onNodeCreated: function(node, config, module, path) {
node.setAttribute('integrity', integrityForModule);
node.setAttribute('crossorigin', 'anonymous');
}
Please note that this example does NOT use SRI for the config file main.js file. In order to accomplish that, either
include the RequireJS config inline in the index.html page
...or reference main.js (the config file) through an extra script tag (with integrity/crossover), and not via the data-main attribute

Initialising requirejs app in both optimised and non-optimised build

I'm confused about my r.js optimised script. I imagine the answer to my question is in the documentation but I think I'm going doc-blind from staring at it too long.
My application has a directory structure like this
-index.htm
-js/app.js
-js/init.js
-js/appname/*.js
When in non-optimised mode index.htm contains the following line:
<script type="text/javascript" data-main="js/app" src="js/lib/require-2.1.11.js"></script>
and everything works fine. My abridged js/app.js script looks like this:
requirejs.config({
baseUrl: 'js',
paths: {
...
}
});
require(['init']);
When I build the optimised script I specify js/app.js as the mainConfigFile and everything builds as expected. However when I update my script tag's data-main attribute to the build product my application doesn't initialise.
If I manually execute require(['init']) in the console it starts up as expected. Because r.js is using js/app.js as its config file that doesn't get included in the optimised script, which means my require(['init']) also doesn't get included.
I thought I could fix this by moving require(['init']) to the end of js/init.js and this does fix the optimised build (it initialised as expected), but now that the call isn't in js/app.js the non-optimised version never initialises. If I include the call in both files I get an error.
How can I ensure my first module is required after either the optimised or non-optimised file(s) are loaded? I don't understand how I'm supposed to make that first call after my first module's dependencies have fully loaded.
Because r.js is using js/app.js as its config file that doesn't get included in the optimised script
Well, then modify the build config you pass to r.js so that js/app.js is included in the final optimized bundle. There's nothing that forbids you from including the file you point to with mainConfigFile in the final bundle.

How do I Change the Order Scripts / css get inserted During Compile with NG Boilerplate

I'm using NG Boilerplate to create an angularJs application and I'm running into an issue where the JS file containing my login controller gets written to index.html before the loginModule.js file does and this is causing a bunch of errors.
Is there a way to control the order in which JS (and CSS) files get added to the compiled page?
Had this problem too.
The JS files are added alphabetically per module to your index.html. I solved this problem by defining submodules in files that start with an underscore (like _submodule.js) to ensure that it gets added to index.html before the other files that use this module.
More info here: https://github.com/ngbp/ngbp/issues/152
From this thread:
[...] I needed a solution for multi-file modules and came up with something that seems to be working. In a multi-file module folder, I create an _init.js which declares the module:
angular.module( 'ngBoilerplate.about', [
'ui.state',
'placeholders',
'ui.bootstrap'
])
;
And then my other .js files can do this:
angular.module('ngBoilerplate.about')
.controller ...
;

Javascript requirejs in development but compiled in production

I'm beginning to evaluate javascript module tools like RequireJS for javascript modularization. This seems useful, especially during development, so I don't need to recompile all of the js files into mylib-<version>.js whenever I change one of the dependent files.
My app is distributed with both html and javascript files, and in production, I would like to use the compiled version of the javascript file.
So in development, my html file might look something like
<html>
<head>
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
</html>
But in production, I would expect it to look more like
<html>
<head>
<script src="mylib-1.0.js"></script>
</head>
</html>
I wouldn't think it production that there should be any need to reference requirejs if I am distributing a compiled file.
Is there a way to do this without having to manually change my html files before I distribute the app?
RequireJs has an optimization tool, which can help you to minify and concatenate your modules. It has a lot of options, and can be difficult to use, but it gets easier with a build tool like GruntJs or (especially) Yeoman, which uses GruntJs to build.
In both you can use the rjs task (which optimizes modules), but again Yeoman is a bit easier since it has generators which will configure it already for you:
// usemin handler should point to the file containing
// the usemin blocks to be parsed
'usemin-handler': {
html: 'index.html'
},
// rjs configuration. You don't necessarily need to specify the typical
// `path` configuration, the rjs task will parse these values from your
// main module, using http://requirejs.org/docs/optimization.html#mainConfigFile
//
// name / out / mainConfig file should be used. You can let it blank if
// you're using usemin-handler to parse rjs config from markup (default
// setup)
rjs: {
// no minification, is done by the min task
optimize: 'none',
baseUrl: './scripts',
wrap: true,
name: 'main'
},
In the index.html you just use a comment line to specify which js files should be minified/concatenated to which output file:
<!-- build:js scripts/amd-app.js -->
<script data-main="scripts/main" src="scripts/vendor/require.js"></script>
<!-- endbuild -->
In the example above, the modules will be concatenated to ONE file, named amd-app.js.
Edit:
This will be done by executing grunt from the command line. This will start a lot of useful tasks, which will build the project in a dist folder, but again this is highly adaptable.
The resulting index.html file (in dist) has only (if you want) one javascript file:
<script src="scripts/15964141.amd-app.js"></script>
My advice: use Yeoman to make life easier (at least for handling minification/concatenation).
First you have to compile your depency tree into one file using the r compiler. After that you can a striped down AMD loader like almond. At least you have to find a way to change the url in your index html.
Take a look at gruntjs which can automatize the whole thing, there a bunch task to like usemin that helps you with the process.

understanding requirejs paths

Using requirejs my main.js looks like this
requirejs.config({
baseUrl: '/javascript/',
paths: {
jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min',
async: 'requirePlugins/async',
hbs: 'hbs'
},
waitSeconds: 7
});
define(['common'], function () {
loadFonts();
});
The main.js is included in the page with a script call
<script data-main="/javascript/main.js" src="/javascript/require-2.0.1.js"></script>
Common is the basic function for the website, jquery doc ready function etc. wrapped in a define call:
define(['jquery'], function() {
//jQuery dependant common code
});
This works fine, jQuery is loaded from the google CDN and the code is executed. But when i add a require call after the load of main.js
<script data-main="/javascript/main.js" src="/javascript/require-2.0.1.js"></script>
require(['jquery'], function ($) {
//code
});
jquery is requested from /javascript/jquery.js instead of the defined path to the google cdn. I'm still a rookie at requirejs but it would seem to me that the path should be defined before any of the other requests are fired, can somebody please help me understand what I'm doing wrong?
I think this could be due to using the data-main attribute on the RequireJS script tag; for that to be parsed, RequireJS itself has to load and parse. In my testing (specifically for IE9), the browser would download and execute any script tags directly following the RequireJS script tag before parsing the RequireJS config file (the one specified by the data-main attribute).
To get around this, I simply quit using the data-main attribute and instead placed the config file as a normal script tag directly after the RequireJS script tag, and everything seems to be happy now.
Specifically, this is what it looks like (using your sample):
<script src="/javascript/require-2.0.1.js"></script>
<script src="/javascript/main.js"></script>
Maybe you put the config statement before require js being loaded.
You should load require.js first, put your config code after, then call require(['jquery'], ...);
The reason it searches /javascript/ is because your require.js file is located there and it is the default base url.
Your config may never be used by require.js.
See this tutorial about require config.
You have to rename define to require
require(['common'], function () {
loadFonts();
});
I'd recommend using map instead of paths to configure specific module locations.
paths is intended more for shortcuts/prefixs to simplify/configure includes, rather than full module paths.
Bear in mind: you'll need to place mappings you want to apply globally under an asterisk (*) key in the map object.
The reason is you put require(['jquery']... immediately after loading require.js module. As the result, it tries to load ['jquery'] before reading your config settings.
And why it tries to find jquery in /javascript/jquery.js? that is because of your data-main attribute.
RequireJS loads all code relative to a baseUrl. 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.
This link clarifies require.js module loading procedure:
http://requirejs.org/docs/api.html#jsfiles
i think you can embed the full url in the require block. like:
require(['http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min'], function ($) {
//code
});
btw, your jquery link is invalid.

Categories