Updating cache "bust" variable programatically in require.js - requirejs

I am trying to update the bust variable in require.js so the browser is forced to re-fetch instead of loading resources from cache. I found here that several people have asked similar question. I am trying to try with a simple piece of code.
<html>
<head>
<title>jQuery+RequireJS Sample Page</title>
<!-- This is a special version of jQuery with RequireJS built-in -->
<script>
var require = {
urlArgs : "bust="+getRandom()
};
</script>
<script data-main="scripts/main" src="scripts/require-jquery.js"></script>
<script>
function getRandom() {
var buildNumber;
$.get("/resource/buildNumber", function(data) {
buildNumber = data;
});
return buildNumber;
}
</script>
</head>
<body>
<h1 id="heading">jQuery+RequireJS Sample Page</h1>
<p>Look at source or inspect the DOM to see how it works.</p>
</body>
I am trying to get the value of my build number from a properties file on the server. But I get the following error:
Uncaught ReferenceError: getRandom is not defined
So I tried this:
<script data-main="scripts/main" src="scripts/require-jquery.js"></script>
<script>
var require = {
urlArgs : "bust="+getRandom()
};
function getRandom() {
var buildNumber;
$.get("/resource/buildNumber", function(data) {
buildNumber = data;
});
return buildNumber;
}
</script>
But I get this error:
Uncaught TypeError: Property 'require' of object [object Object] is not a function
It looks like the bust variable has to be set even before require-jquery.js is declared but how do I access server side APIs without access to jquery libraries? I want to update the bust variable for every build.
Any pointers in the right directions would be really appreciated.
Thanks.

Related

Uncaught ReferenceError: module/require is not defined

I am learning about how to create/import/export modules in Node.js,
i have gone through these and was trying to learn by creating a sample application.
I issued the command from the root folder (Poc1) "npm install requirejs", and included the file require.js in the Start.html.
When i open Start.html in browser i get -
"Uncaught ReferenceError: require is not defined", "Uncaught ReferenceError: module is not defined".
I am not sure what mistake i am making or what other files i need to include to get it working ?
For sample application below is folder structure
Poc1 folder has these files and folders (greetings.js, main.js, Start.html, node_modules)
Poc1\node_modules has (requirejs\require.js)
grreetings.js is defined as below
module.exports.sayHelloInEnglish = function(){
return "Hello";
}
module.exports.sayHelloInSpanish = function(){
return "Hola";
}
main.js is defined as below
var greetings = require("./greetings.js");
function someFunc(){
var g1 = greetings.sayHelloInEnglish();
var g2 = greetings.sayHelloInSpanish();
alert(g1);
alert(g2);
}
Start.html is defined as below
<html>
<head>
<script type="text/javascript" src="main.js"></script>
<script type="text/javascript" src="greetings.js"></script>
<script type="text/javascript" src="node_modules\requirejs\require.js"></script>
</head>
<body>
<span>Below is button</span>
<input type="button" onclick="someFunc()" value="clickMe"/>
</body>
</html>
Ok, I think those exports aren't correct:
exports.sayHelloInEnglish = function(){
return "Hello";
}
exports.sayHelloInSpanish = function(){
return "Hola";
}

Requiring modules gives module not loaded error

I am trying to write a simple Hello world app in react.js using component based approach. So I am using requie.js. I have 4 files in the same folder namely index.html, index.js,world.js and require.js. I am having a script tag in index.html which will load index.js. But I am loading the world.js via require.js using module.exports, which would result in error. Here is my code
index.html
<head>
<script src="https://fb.me/react-0.13.3.js"></script>
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script data-main="index.js" src="require.js"></script>
</script>
</head>
<body>
<script type="text/jsx" src="index.js"></script>
</body>
index.js
var world = require('./world');
var Hello = React.createClass({
render:function(){
return (<div>
<div>Hello,</div>
<world/>
</div>)
}
})
var element = React.createElement(Hello);
React.render(element,document.body);
world.js
module.exports = React.createClass({
render: function(){
return (<div>World!</div)
}
})
I am intending to show Hello, World. But I'm getting the following errors
Uncaught SyntaxError: Unexpected token <
fbcdn-dragon-a.akamaihd.net/hphotos-ak-xtf1/t39.3284-6/11057100_835863049837306_1087123501_n.js:314 You are using the in-browser JSX transformer. Be sure to precompile your JSX for production - http://facebook.github.io/react/docs/tooling-integration.html#jsx
require.js:8 Uncaught Error: Module name "world" has not been loaded yet for context: _. Use require([])
http://requirejs.org/docs/errors.html#notloaded
:8000/index.js:5 Uncaught SyntaxError: Unexpected token <
First of all, the component "world" should start with an upper case. I went ahead and put the code in a single file so that you can see it a little more clear:
<!DOCTYPE html>
<html>
<head>
<title>Hello React!</title>
<script src="https://fb.me/react-0.13.3.js"></script>
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
var World = React.createClass({
render: function(){
return (
<div>World!</div>
);
}
});
var Hello = React.createClass({
render:function(){
return (
<div>
<div>Hello,
<World />
</div>
</div>
);
}
});
React.render(<Hello />,document.getElementById('example'));
</script>
</body>
</html>
What I would recommend is that you setup a proper environment for development with node and npm installed. I have a project in github that is a skeleton that you can use to get up and running without having to worry about how it works for now: reactjs skeleton.
I hope this helps!
There are at least three issues here. First, you are not using the correct require syntax for asynchronous loading. Your index.js should be:
define(['world'], function(world) {
var Hello = React.createClass({
render:function(){
return (<div>
<div>Hello,</div>
<world/>
</div>)
}
})
var element = React.createElement(Hello);
React.render(element,document.body);
});
Second, since index.js and world.js are jsx files, requirejs needs a plugin that will tell it that. Something like:
https://github.com/philix/jsx-requirejs-plugin
Finally, since you are loading index.js via requirejs, you don't need:
<script type="text/jsx" src="index.js"></script>

React, can't get past no method 'mountComponentIntoNode'

I have a html that looks like this:
<head>
<script src="../js/vendor/jquery-2.1.0.js"></script>
<script src="../js/vendor/react.js"></script>
<script src="../js/jsx/todo.js"></script>
</head>
<body>
<div id="ola"></div>
<script src="../js/popup.js"></script>
</body>
My todo.js is the compiled version TODO app from http://facebook.github.io/react/ minus the last line.
My last popup.js is:
$(function() {
React.renderComponent(TodoApp, document.getElementById('ola'));
})
But the page shows nothing! The console shows an error:
Uncaught TypeError: Object function (props, children) {
var instance = new Constructor();
instance.construct.apply(instance, arguments);
return instance;
} has no method 'mountComponentIntoNode' react.js:10052
I really don't know why is that, I've just tried to recreate from the example in the website. If it matters, it is in a chrome extension.
Ahhh got one line wrong on render!
popup.js should be:
React.renderComponent(TodoApp(), document.getElementById('ola'));

RequireJS does not run data-main script before loading required modules

My project includes the following files:
./index.html
./js/main.js
./js/vendor/require.js
./js/viewmodel/vm.js
The index.html has the following relevant snippet:
<script data-main="js/main.js" src="js/vendor/require.js"></script>
<script type="text/javascript">
require(['viewmodel/vm', 'ko'],
function(viewmodel, ko) {
ko.applyBindings(viewmodel);
}
);
</script>
The js/main.js file is as follows:
var root = this;
define('jquery', ['http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.js'], function () { return root.$; });
define('ko', ['http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.1.0.js'], function (ko) { return ko; });
The js/viewmodel/vm.js file...
define(['jquery', 'ko'],
function($, ko) {
return {
subject: 'world',
greeting: 'hello'
}
}
);
When you open a browser to index.html, then the browser tries to load a file called js/ko.js instead of using the module defined in main.js. It seems like the js file pointed to by the data-main attribute is not guaranteed to run before dependency resolution. This does not seem correct to me since one purpose of the data-main js file is to define require configuration (i.e. path, shim, etc). I am using require v2.1.2.
This works perfectly fine if I copy the contents of my main.js file into the script block in index.html. By "perfectly fine" I mean that it resolved ko to be a module and finds the appropriate CDN link to resolve ko instead of trying to download ./js/ko.js.
to use the data-main attribute for configuring your whole application, it is necessary that it is the single entry point for all your code.
your 2nd script block breaks this requirement by providing a 2nd entry point. since these entry points will resolve independently of each other (and asynchronously), you cannot rely on one to affect the other.
to resolve it, refactor your code in a way that provides a single entry point to your application and do your configuration via this entry point.
That's because requirejs sets the async. Attribute on the script.
The boolean async attribute on script elements allows the external
JavaScript file to run when it's available, without delaying page load
first.
This means that both scripts are loaded and evaluated parallel, so none of the two scripts can access methods or functions from the other one.
If you want to define requirejs variables in one script you mustn't load that script with require js.
For me there are three possibilities how you can solve that problem:
Add the content of main.js to your page (as you mention)
Load the main.js file without requirejs as normal script
Define the require config before loading the scripts (link to requirejs docu )
I had the same problem. The architecture of the site that i was working was components that was loading asynchronous at each part of the page.
Each component has its own html, css, and js code.
So, my solution is to keep a guard function for all the required dependency code, to protect them from running before the main javascript file:
index.html
<head>
<script type="text/javascript">
window.BeforeMainGuard = {
beforeMainLoadedFunctions: [],
hasMainLoaded: false,
guard: function( func ) {
console.assert( typeof func === 'function' );
if( this.hasMainLoaded ) {
func();
}else {
this.beforeMainLoadedFunctions.push( func );
}
},
onMainLoaded: function() {
for( var i = 0; i<this.beforeMainLoadedFunctions.length; ++i ) {
var beforeMainLoadedFunction = this.beforeMainLoadedFunctions[i];
beforeMainLoadedFunction();
}
this.beforeMainLoadedFunctions = null;
this.hasMainLoaded = true;
}
};
</script>
<script data-main="js/main.js" src="js/vendor/require.js"></script>
<script type="text/javascript">
window.BeforeMainGuard.guard( function() {
require(['viewmodel/vm', 'ko'],
function(viewmodel, ko) {
ko.applyBindings(viewmodel);
}
);
});
</script>
</head>
js/main.js
require.config({
// your config
});
require( [ 'AppLogic' ], function( AppLogic ){
AppLogic.Init();
window.BeforeMainGuard.onMainLoaded();
} );

how to run nodejs flatiron/director example

I tried to run the https://github.com/flatiron/director#client-side example to get familiar with director.js.
I am not able to setup the flatiron module on the client-side.
In my html page (say, <my_project>/page.html) I replaced the location of director.js with
a location of its counterpart from my project:
<my_project>/node_modules/flatiron/node_modules/director/lib/director.js
Upon loading the <my_project>/page.html page in the browser
I got errors: export and Router not defined.
First idea: After all, on the browser side there is no nodejs...
Ok, I thought that browserify could help me with it.
I generated a single 'browser-side' bundle (was it necessary?):
my_project> node node_modules/browserify/bin/cli.js node_modules/flatiron/node_modules/director/lib director.js -o cs_director.js
and I used it in the line: <script src="cs_director.js"></script>
The problem is that the error
Uncaught ReferenceError: Router is not defined
(anonymous function)
still appears so I guess the whole example will not work.
I am new to node/js and I am not sure if it makes sens what I have done in my case described above...
Does anybody how to solve it?
Or generally, how to use 'isomorphic' stuff on a browser-side?
The html examples on Github just refer to the same .js files
as server-side examples ...
Can you recommend any tutorials, examples?
Thanks,
-gvlax
You can find a browser-specific build of director here which has all of the server code stripped away.
Thanks DeadDEnD,
Now it works like a charm!
I have no idea how I could missed that info in readme ... I read the manual first, I swear:-)
Here is my sample code:
<!html>
<html>
<head>
<script src="director-1.0.7.min.js"></script>
<script>
var author = function () { console.log("author called.");},
books = function () { console.log("books called."); },
viewBook = function(bookId) { console.log("viewBook called."); };
var routes = {
'/author': author,
'/books': [books, function() { console.log("anonymous fun called."); }],
'/books/view/:bookId': viewBook
};
var router = Router(routes);
router.init();
</script>
</head>
<body>
Click me to call two functions at a time.
</body>
</html>
--gvlax

Resources