"ReferenceError: window is not defined" when compiling with r.js - javascript

I've been using RequireJS and it works perfectly. I use a lot of "window.document" to manipulate different DOM elements, but when I try to optimize it with r.js i get a ReferenceError: window is not defined which only happens with r.js.
Here is a minimal example of code that reproduces the issue:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body >
<div id="commentbox">
</div>
<script data-main="code/main" src="code/require.js"></script>
</body>
</html>
main.js:
require(["roomManager"], function (roomManager){
return {
}
});
roomManager.js:
define(["commentManager"], function(commentManager){
var commentHand = new commentManager.commentHand();
commentHand.init();
return{
}
});
commentManager.js:
define([], function(){
function commManager(getDisplayIdVariable){
var messagebox = window.document.getElementById("commentbox");
this.init = function(){
messagebox.innerHTML = "hi!";
}
}
return{
commentHand : commManager
}
});
This version works correctly without r.js but when I try to compile it by running r.js main.js. I get this:
var messagebox = window.document.getElementById("commentbox);
ReferenceError: window is not defined
at new new commManager

You cannot just do r.js main.js.
For one thing, you have to specify -o so that r.js performs the optimization. (r.js can be used for other things.)
You also have to pass configuration to r.js, either in a file, or on the command line. One possibility for you would be:
r.js -o name=main out=built.js
I've tried this with the code you show in your question and I get no errors.
I strongly suggest going over this documentation for r.js.

if your code is optional you can use
if (typeof window !== 'undefined') {
// Inside browser
}
{
// outside browser
}

Related

Why is my global requirejs var undefined?

I have two seperate applications. Both use jQuery an RequireJS. I want to embed application A into application B, so I transfer the required HTML to application B. Application B is an instance of edx-platform (https://github.com/edx/edx-platform).
So far so good, but the second app won't load. First I had both script tags with data-main, but it doesn't work. So I searched and I found this: https://stackoverflow.com/a/10839885
I looks good so far, but my global requirejs variable is undefined. In the HTML edx-platform calls RequireJS with this code:
<script>
window.baseUrl = "/static/";
(function (require) {
require.config({
baseUrl: window.baseUrl
});
}).call(this, require || RequireJS.require);
</script>
<script type="text/javascript" src="/static/lms/js/require-config.js"></script>
<script type="text/javascript">
(function (require) {
require.config({
paths: {
'js/courseware/courseware_factory': 'js/courseware/courseware_factory',
'draggabilly': 'js/vendor/draggabilly',
'js/courseware/toggle_element_visibility': 'js/courseware/toggle_element_visibility',
'js/courseware/course_home_events': 'js/courseware/course_home_events',
'js/courseware/link_clicked_events': 'js/courseware/link_clicked_events',
'moment': 'common/js/vendor/moment-with-locales',
'moment-timezone': 'common/js/vendor/moment-timezone-with-data',
'js/student_account/logistration_factory': 'js/student_account/logistration_factory',
'js/groups/views/cohorts_dashboard_factory': 'js/groups/views/cohorts_dashboard_factory',
'js/dateutil_factory': 'js/dateutil_factory',
'js/courseware/accordion_events': 'js/courseware/accordion_events',
'js/bookmarks/views/bookmark_button': 'js/bookmarks/views/bookmark_button',
'js/views/message_banner': 'js/views/message_banner',
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory'
}
});
}).call(this, require || RequireJS.require);
</script>
My code is included later. I tried to run a simple console.log(requirejs) but it didn't work. requirejs is also undefined when calling it from the developer console.
OK I found out why it is undefined. edX also loads the file which undefined all of those variables.
Now I need to find a way to get my code running.

Using express-babelify-middleware with FeathersJS

I am trying to use express-babelify-middleware
with FeathersJS and the error shows up in the browser console:
ReferenceError: main_run is not defined
I take this to mean that babelify is not working or I am using it incorrectly as main_run is in the global namespace of the src in my html file.
Here is my setup using the structure from feathers generate:
public/index.html:
<!DOCTYPE html>
<html>
<head>
<title>babelify test</title>
<script src="main.js"></script>
<script>
main_run()
</script>
</head><body>
<p>Testing feathers with babelify</p>
</body></html>
public/main.js
const external_module = require('./test')
function main_run(){
external_module()
}
public/test.js
module.exports = function(){
console.log("Hello world for an external module")
}
among the .uses of src/app.js:
...
const babelify = require('express-babelify-middleware')
...
app.use(compress())
.options('*', cors())
.use(cors())
//the line that is not working:
.use('/main.js', babelify( path.join(app.get('public'), 'main.js') ))
.use(favicon( path.join(app.get('public'), 'favicon.ico') ))
.use('/', serveStatic( app.get('public') ))
When I visit localhost:3030/main.js I can see the file, but the functions look to be in a function of their own, so I don't know how to get into that function.
Silly problem, one can't access browserified code in the html file that calls it. So public/index.html can't access main_run unless it is attached to the window object. There is a similar question
here.
Other than that, my code works perfectly.
In main.js place the following code at the bottom:
window.main_run = main_run
Then in index.html replace the main_run() line with:
window.main_run()
This will write the contents of test.js to the console.

consume browserified modules in javascript

I am new to javascript and I am facing some issues working with npm modules on the browser side. Could someone please direct me int he right direction ?
I have a module structure which is something like
add.js
function add (a,b) {
return a+b;
}
module.exports.add = add;
multiply.js
function multiply (a,b) {
return a*b;
}
module.exports.multiply = multiply;
I have a consumer module called calculator.js which looks like:
var adder=require('./add');
var multiplier=require('./multiply');
console.log(adder.add(1,2));
console.log(multiplier.multiply(1,2));
function sum(a,b){
return adder.add (a,b);
}
function product(a,b){
return multiplier.add (a,b);
}
module.exports.sum = sum;
module.exports.product=product;
When I do a 'node calculator.js', I get 3 & respectively.
I would now like to use this Calculator module in my browser. So I did the following :
browserify calculator.js > cal.js
Created an html file
<html>
<body>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.js"></script>
<script src='cal.js'></script>
</body>
</html>
This prints out 3 and 2 on console.
However I would like to use the calculator's methods doing a require of cal like
<script>
var cal=require('cal');
</script>
This throws me an error saying
'Module name "cal" has not been loaded yet for context: _. Use
require([])'
Any idea how do I get this running ? Thanks in advance for help.
You don't need require.js for that.
Instead, you can tell Browserify to make the calculator.js module available for require(). This will also make a require function available for use in a browser:
$ browserify -r ./calculator.js:cal > cal.js
To use this in a browser:
<script src="cal.js"></script>
<script>
var cal = require('cal');
...
</script>
More information here.

How is it possible to make json query client side [duplicate]

I have the following Node.js project (which is a Minimal Working Example of my problem):
module1.js:
module.exports = function() {
return "this is module1!";
};
module2.js:
var module1 = require('./module1');
module.exports = function() {
return module1()+" and this is module2!";
};
server.js:
var module2 = require('./module2');
console.log(module2()); // prints: "this is module1! and this is module2!"
Now I want to create a client.html file that will also use module2.js. Here is what I tried (and failed):
naive version:
<script src='module2.js'></script>
<script>alert(module2());</script> // should alert: "this is module1! and this is module2!"
This obviously doesn't work - it produces two errors:
ReferenceError: require is not defined.
ReferenceError: module2 is not defined.
Using Node-Browserify: After running:
browserify module2.js > module2.browserified.js
I changed client.html to:
<script src='require.js'></script>
<script>
var module2 = require('module2');
alert(module2());
</script>
This doesn't work - it produces one error:
ReferenceError: module2 is not defined.
Using Smoothie.js by #Torben :
<script src='require.js'></script>
<script>
var module2 = require('module2');
alert(module2());
</script>
This doesn't work - it produces three errors:
syntax error on module2.js line 1.
SmoothieError: unable to load module2 (0 )
TypeError: module2 is not a function
I looked at require.js but it looks too complicated to combine with Node.js - I didn't find a simple example that just takes an existing Node.js module and loads it into a web page (like in the example).
I looked at head.js and lab.js but found no mention of Node.js's require.
So, what should I do in order to use my existing Node.js module, module2.js, from an HTML page?
The problem is that you're using CJS modules, but still try to play old way with inline scripts. That won't work, it's either this or that.
To take full advantage of CJS style, organize your client-side code exactly same way as you would for server-side, so:
Create client.js:
var module2 = require('./module2');
console.log(module2()); // prints: "this is module1! and this is module2!"
Create bundle with Browserify (or other CJS bundler of your choice):
browserify client.js > client.bundle.js
Include generated bundle in HTML:
<script src="client.bundle.js"></script>
After page is loaded you should see "this is module1! and this is module2!" in browser console
You can also try simq with which I can help you.
Your problems with Smoothie Require, were caused by a bug (https://github.com/letorbi/smoothie/issues/3). My latest commit fixed this bug, so your example should work without any changes now.

How to use javascript on nodejs and web at the same time?

i want to use a config file in nodejs and in a web javascript.
config.js:
var conf = {};
conf.name = 'testname';
conf.pass = 'abc123';
conf.ip = '0.0.0.0';
conf.port = 100;
conf.delay = 5;
exports.config = conf;
use it in nodejs with:
var conf = require('config.js');
console.log(conf.config.name);
want to use this same file inside html but how? I was thinking by this way but i don't know how to use it in web. When i try to use it in web i get Reference error: exports is not defined.
config.html:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<script src="./config.js"></script>
<script>
var cnf = conf;
function getCnf(){
alert(cnf.config.name);
}
</script>
</head>
<body>
<button onclick="getCnf();">test</button>
</body>
</html>
Anyone know how i must change config.js to use it in both systems nodejs and web?
PS: Webside is running on nodejs http npm module.
You can put a condition around that, like this
if (typeof module !== 'undefined' && module.exports) {
module.exports.config = conf;
}
This makes sure that you have module and exports are available before setting any value on exports.
Note: exports is just another variable referring module.exports. So, they both are one and the same unless you assign something else to either of them. In case, you assign something to either of them, whatever is there in module.exports will be exported in Node.js. You can read more about exports in this blog post
Thanks, that typeof was all i needed.
#Phoenix: I know that there is a way to do that but that's not necessary. The variable are only used for some ajax requests and deley timers later.
You can use browserify to bundle your CommonJS for the browser without resorting to environment switches.
Install browserify using npm i browserify -g
Bundle your config.js and export it for external use with the -r tag
browserify -r ./config.js -o bundle.js
Include the bundle in your code and use it:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<script src="./bundle.js"></script>
<script>
var cnf = require("./config.js");
function getCnf(){
alert(cnf.config.name);
}
</script>
</head>
<body>
<button onclick="getCnf();">test</button>
</body>
</html>

Categories

Resources