RequireJS: Reading configuration from app.js - javascript

In app.js, I am writing configurations for my project.I want to pick the version number of jquery from some external file config.js instead of hard coding it in app.js. How can I achieve this?
I have pasted code for app.js, config.js and index.html below:
config.js
define(function() {
var Config = {
jquery: "3.1.0"
};
return Config;
});
Index.html:
<script src="require.js" data-main="js/app"></script>
app.js
requirejs.config({
paths: {
jquery: serverUrl + "/jquery-3.1.0.min",
}
});
I cannot move requirejs.config() to config.js file as serverUrl is the variable used which I can't retrieve from config.js according to my project structure.

The easiest way to do what you want would just be to load a configuration file before your app.js and refer to it.
<script src="config.js"></script>
<script src="require.js" data-main="js/app"></script>
config.js could contain:
window.fooConfig = {
serverUrl: 'some appropriate URL',
}
I use window explicitly to make it clear I'm putting something in the global space on purpose. fooConfig for the name is just an example of what could be used for an application named foo. You can select something as unique as you need to avoid a clash with other code.
Then your app.js would do:
requirejs.config({
paths: {
jquery: fooConfig.serverUrl + "/jquery-3.1.0.min",
}
});

Related

How to properly configure requireJS

Hi I'm trying to make starting template for SPA project mainly using:
RequireJS, KnockoutJS, TypeScript, etc.
I'm having hard time figuring out how to configure paths and folder structure for RequireJS to work properly...
here is my folder structure:
Scripts
app
components
main.js
lib
knockout.js
jquery.js
here is my RequireJS config file:
var config = {
waitSeconds: 15,
paths: {
app: '../app',
'knockout': '/lib/knockout-3.4.2.',
sammy: '/lib/sammy-0.7.5.',
jquery: '../scripts/lib/jquery-1.10.2.'
}
};
This is my attempt for main.js:
define(['jquery', 'PageOne', 'PageTwo'], function ($, pageOne, pageTwo) {
$(document).ready(function () {
var app = Sammy('#main', function () {
this.get('#/pageOne', function () {
pageOne.activate();
});
this.get('#/pageTwo', function () {
pageTwo.activate();
});
});
app.run();
});
});
Here is my Index.cshtml script tag:
<script src="~/Scripts/lib/require.js" data-main="scripts/app/components/main"></script>
I saw in different project that config is called in header so this is in html header:
<script src="~/Scripts/app/config/require.config.js"></script>
My problem is that in main.js it looks for jquery under path defined in data-main (scripts/app/components/), but my jquery is in scripts/lib folder.
I'm trying to figure out by reading online the whole day but it's too much time for me I need someone to give me some hints how is this supposed to work?
Seriously having hard time figuring this out and RequireJS website just isn't helping me atm.
Note: I am beginner in JavaScript based projects, first SPA attempt,
never used RequireJS...
Your configuration file does not do anything. I'm assuming from your description that the script element that loads it is located before the script element that loads RequireJS. That's one valid way to configure RequireJS, but if you want RequireJS to pick up the configuration, you need to set the global variable require before you load RequireJS, and RequireJS will use the value of require as its configuration. Right now you are setting config, which is ignored by RequireJS. So:
var require = {
waitSeconds: 15,
// etc...
And once the configuration is in effect, you should be able to reduce your data-main to data-main="components/main".
I see some of your paths in the paths configuration end with a dot. That's most likely a mistake on your part, or you have some very strange file names.

RequireJS is not loading modules relative to the baseUrl

In the <head> tag
<script>
var require = {
baseUrl: '/dist/js',
paths: {
jquery: 'jquery-1.11.3'
}
};
</script>
<script data-main="main.js" src="/dist/js/require.js></script>
And in main.js:
define(["exports", "jquery", "order.js", "search.js"], function (exports, _jquery, _orderJs, _searchJs) {
"use strict";
console.log("Hello");
});
Now, main.js loads just fine, same with jquery. But order.js and search.js is being loaded from the root (http://example.com/order.js).
Why is it not loading from the baseUrl?
Remove the .js extension from the module names you give to define or require. If you put the extension yourself, then RequireJS assumes the module name is a literal path and will skip your configuration.

Getting started with browserify: import local files?

I have been prototyping a JavaScript application and now I want to move to a more robust setup using browserify and managing dependencies with require.
Currently I have the following files in my application:
chart.js
form.js
highcharts-options.js
vendor/
highcharts.js
jquery.js
highcharts-options.js is basically a list of constants, while chart.js looks like this...
var myChart = {
setup: function(data) { ... this.render(data); },
render: function(data) { ... }
},
and form.js looks like this:
var myForm = {
setup: function() { button.onclick(_this.getData(); },
getData: function() { // on ajax complete, callChart },
callChart: function() { myChart.setup(data); }
};
myForm.setup();
And then I have an index.html page that imports everything as follows:
<script src="/js/vendor/highcharts.js"></script>
<script src="/js/vendor/jquery.js"></script>
<script src="/js/highcharts-options.js"></script>
<script src="/js/chart.js"></script>
<script src="/js/form.js"></script>
So now I want to move this to a more modern setup with browserify.
I have deleted the vendor directory and instead created an index.js file and a package.json file, so now my directory structure looks like this:
index.js
package.json
chart.js
form.js
highcharts-options.js
node_modules/
I have run npm i --save highcharts-browserify and npm i --save jquery and that has saved these modules to package.json and installed them in node_modules. I've also added a build task in package.json: browserify index.js -o bundle.js. And in my front-end template I know just have:
<script src="/js/bundle.js"></script>
So far so good.
My question is what to put into my index.js file, because I'm not sure how to import the files that I already have. So far I've got this:
var $ = require('jquery');
var HighCharts = require('highcharts-browserify');
var options = require('highcharts-options');
var myChart = require('chart');
var myForm = require('form');
myForm.setup();
But when I try to build this, I get:
Error: Cannot find module 'chart' from '/mypath/static/js/app'
It looks like require doesn't know how to find this file, or how to import it, which is not surprising given that this is all total guesswork on my part.
How should I adapt these files to work in a more modular way? Am I on the right lines, or is this completely the wrong approach? I'm not even sure what I should be Googling for.
(NB: Eventually I want to refactor chart.js and form.js to use Backbone, but I need to work one step at a time.)
You are very close!
First, the way to reference a module in the same directory is to say:
var myChart = require('./chart');
Without the leading path component, require will look in your npm package directory.
Second, you need to export the variables in the modules so that they can be used elsewhere. So your form module needs to look something like this:
var myForm = {
setup: function() { button.onclick(_this.getData(); },
getData: function() { // on ajax complete, callChart },
callChart: function() { myChart.setup(data); }
};
myForm.setup();
module.exports = myForm;
I just finished struggling with this error for a while, I'll post my solution in case anyone else runs into the same issue I did. It seems that Browserify sometimes can't find local modules depending on where the require goes. This code didn't work:
window.Namespace = {
foo: new require('./foo.js')()
};
but this worked fine:
var Foo = require('./foo.js');
window.Namespace = {
foo: new Foo()
};

RequireJS seems to be ignoring my path definitions ( I'm not calling require() in the html). Why?

I've been researching this question a lot. I know a common issue is caused with asynchronous loading before require has been defined. I dont think that's the issue that I'm experiencing. I'm declaring baseURL and paths in a config file, but I always get an error that the scripts can't be found because it seems to ignore my paths and just look from the baseURL.
This is my folder structure
index.html
js/
app/
jsonLoader.js
notionalAddGraph.js
lib/
config.js
require.js
There's nothing in lib, but I'm mimicking the structure of a project that I'm working on. Here is the html for the page.
HTML:
<html>
<head>
<title>Blah Blah Blah</title>
<script data-main="js/config.js" src="js/require.js"></script>
<script id="graphData" type="application/json">
{
"json": "Is better than",
"global": "but it requires a change to the authoring",
"environment": "also, because of the JSON.parse",
"required": "it is probably slower too"
}
</script>
</head>
Here is the code for config.js
config.js:
require({
baseUrl: 'js/lib',
paths: {
app: '../app'
},
urlArgs: 'bust=' + (new Date()).getTime()
});
require(['app/jsonLoader','app/notionalAddGraph'],
function(require) {
'use strict';
});
and here is the code for jsonLoader.js
jsonLoader.js:
define(function() {
var jsonString = document.getElementById('graphData').textContent;
return JSON.parse(jsonString);
})
annnd here is the code for notionalAddGraph.js
notionalAddGraph.js:
define([
'jsonLoader'
], function(json) {
console.log(json.required);
});
so every time that I try this, require tries to load js/lib/jsonloader.js and fails because it should be looking under app, not lib. Oddly enough, if I intentionally specify the incorrect path when I define app, requireJS will at least look for jsonLoader where I told it to. Obviously though, its not there, because I specified the wrong path. When I specify the correct path, it doesn't work and tries to load from baseURL. I've tried changing everything I can imagine for config.js, but nothing seems to work. I've copied the format directly from requireJS API, but still nothing. Does anyone have an idea as to what I might be doing wrong?
In notionalAddGraph.js you have define with 'jsonLoader' so its looking in the correct path as expected, add ../ to your define and should work correctly
Here's what i'd try
First, call the scripts using an absolute path (you can rollback this change later, but it's just to be on the safe side)
<script data-main="/js/config.js" src="/js/require.js"></script>
Second, declare the config parameters using requirejs.config. I guess that the way you're doing now they are just variables.
requirejs.config({
baseUrl: 'js/lib',
paths: {
app: '../app'
},
urlArgs: 'bust=' + (new Date()).getTime()
});
Third, the return of the jsonLoader isn't the require object, but the object that comes from parsing the jsonString. The way you're doing now is replacing the require object.
require(['app/jsonLoader','app/notionalAddGraph'], function(jsonObject) {
'use strict';
console.log('require is still', require, 'and jsonobject is ',jsonObject);
});

Using and injecting Angular $templateCache with RequireJS

I do a grunt serve:dist and within I build with grunt-contrib-requirejs an all.js file based on my RequireJS main.js file which have require.config and a require section.
I think all.js should be in my distribution that file which I have to include on startup in my index.html, because everything is in there. Is this right?
<script src="require.js" data-main="all.js"></script>
I also create based on all my template HTML files a template JavaScript file with ngTemplates and bootstrap it so the template file named templates.js looks like this:
define([
'angular'
], function(angular) {
angular.module('MyApp.templates', []).run(['$templateCache', function($templateCache) {
'use strict';
$templateCache.put('templates/MyTest.html',
"<h1>Title</h1>\r" +
// ...
// other put on $templateCache
}]);
});
So I have a $templateCache which I want to use. But I do not how this can be done. I think I have to load the templates.js because it is not included in all.js and therefore I should inject it in some way.
I had similar issue and I found a way to solve it.
Basically, I have templates.js to return just a function to inject to run block.
For example: templates.js
define([], function()){
return ['$templateCache", function($templateCache){
'use strict';
$templateCache.put('templates/MyTest.html',
"<h1>Title</h1>\r" +
// ...
// other put on $templateCache
}];
}
and then, in your app.js file, you can inject this function into run block
define(['templates'], function(templates){
angular.module('app')
.run(templates);
})
I hope this helped, please let me know if you are not clear with something.

Categories

Resources