Difficulty Loading Modules with Require.js - javascript

I'm trying to load and use a module I defined with Require. As far as I can tell, I'm following the patterns on the official site, but I'm not getting the loaded module inside the require call.
main.js:
define(function (require) {
require(['./util'], function(util){
util.dictionary();
});
...
});
util.js:
define(function(){
"use strict";
var util = {};
...
return util;
});
With this, util.dictionary() fails because util is undefined.
Both files are on the same directory level, and I haven't defined any baseURL for Require.
Why is this failing?

After a lot of poking around, I discovered that Chrome was using a cached versions of some of my files, and clearing the cache caused the modules to load correctly.
Yes, I'm a web development noob.

Related

RequireJS: TypeError [ERR_INVALID_ARG_TYPE] when loading asynchronously

So I'm trying to use RequireJS in my project, but just putting require('fs') brings up an error about how it hasn't been loaded yet. On the RequireJS website, it says that the following code should be used instead:
require(['fs'], function (fs) {
//fs is now loaded.
});
However, when I use this code, I get the error TypeError [ERR_INVALID_ARG_TYPE] which says that I should be using a string as an argument to require, but RequireJS says that this does not work.
Would appreciate it if anybody could give me any tips on how to get this working, thanks.
According to docs, you need something like that.
const requirejs = require('requirejs');
requirejs.config({
//Pass the top-level main.js/index.js require
//function to requirejs so that node modules
//are loaded relative to the top-level JS file.
nodeRequire: require
});
requirejs(['fs'], function (fs) {
console.log('fs is now loaded.');
});
Of course, you need to install it first:
npm install requirejs

Require JS files dynamically on runtime using webpack

I am trying to port a library from grunt/requirejs to webpack and stumbled upon a problem, that might be a game-breaker for this endeavor.
The library I try to port has a function, that loads and evaluates multiple modules - based on their filenames that we get from a config file - into our app. The code looks like this (coffee):
loadModules = (arrayOfFilePaths) ->
new Promise (resolve) ->
require arrayOfFilePaths, (ms...) ->
for module in ms
module ModuleAPI
resolve()
The require here needs to be called on runtime and behave like it did with requireJS. Webpack seems to only care about what happens in the "build-process".
Is this something that webpack fundamentally doesn't care about? If so, can I still use requireJS with it? What is a good solution to load assets dynamically during runtime?
edit: loadModule can load modules, that are not present on the build-time of this library. They will be provided by the app, that implements my library.
So I found that my requirement to have some files loaded on runtime, that are only available on "app-compile-time" and not on "library-compile-time" is not easily possible with webpack.
I will change the mechanism, so that my library doesn't require the files anymore, but needs to be passed the required modules. Somewhat tells me, this is gonna be the better API anyways.
edit to clarify:
Basically, instead of:
// in my library
load = (path_to_file) ->
(require path_to_file).do_something()
// in my app (using the 'compiled' libary)
cool_library.load("file_that_exists_in_my_app")
I do this:
// in my library
load = (module) ->
module.do_something()
// in my app (using the 'compiled' libary)
module = require("file_that_exists_in_my_app")
cool_library.load(module)
The first code worked in require.js but not in webpack.
In hindsight i feel its pretty wrong to have a 3rd-party-library load files at runtime anyway.
There is concept named context (http://webpack.github.io/docs/context.html), it allows to make dynamic requires.
Also there is a possibility to define code split points: http://webpack.github.io/docs/code-splitting.html
function loadInContext(filename) {
return new Promise(function(resolve){
require(['./'+filename], resolve);
})
}
function loadModules(namesInContext){
return Promise.all(namesInContext.map(loadInContext));
}
And use it like following:
loadModules(arrayOfFiles).then(function(){
modules.forEach(function(module){
module(moduleAPI);
})
});
But likely it is not what you need - you will have a lot of chunks instead of one bundle with all required modules, and likely it would not be optimal..
It is better to define module requires in you config file, and include it to your build:
// modulesConfig.js
module.exports = [
require(...),
....
]
// run.js
require('modulesConfig').forEach(function(module){
module(moduleAPI);
})
You can also try using a library such as this: https://github.com/Venryx/webpack-runtime-require
Disclaimer: I'm its developer. I wrote it because I was also frustrated with the inability to freely access module contents at runtime. (in my case, for testing from the console)

module.exports "Module is not defined"

So, I am using RequireJS and React, trying to load a third-party component, which has been installed with:
npm install react-autocomplete
The structure is here: https://github.com/rackt/react-autocomplete/tree/master/lib
Now, I have a main.js file, initiated when requireJS is loaded, that looks like this:
require.config({
paths: {
"react" : "react/react",
"jsx-transformer" : "react/JSXTransformer",
"react-autocomplete" : "node_modules/react-autocomplete/lib/main"
}
});
require(["react"], function(react) {
console.log("React loaded OK.");
});
require(["jsx-transformer"], function(jsx) {
console.log("JSX transformer loaded OK.");
});
require(['react-autocomplete'], function (Autocomplete) {
console.log("React autocomplete component loaded OK.");
var Combobox = Autocomplete.Combobox;
var ComboboxOption = Autocomplete.Option;
console.log("Autocomplete initiated OK");
});
Now, it all loads OK, but the third require statement throws a "module is not defined", for the main.js file in the third-party component, which looks like this:
module.exports = {
Combobox: require('./combobox'),
Option: require('./option')
};
I've been reading about that this has to do with me trying to require a CommonJS-style module, but I can't figure out how to fix it on my own, as I'm new to this.
Does anyone have a clear example on how I could get around this?
RequireJS cannot load CommonJS modules as-is. However, there is a minimal modification you can make to them to load them. You have to wrap them in a define call like this:
define(function (require, exports, module) {
module.exports = {
Combobox: require('./combobox'),
Option: require('./option')
};
});
If you have a bunch of modules you need to convert, or if you are using a third-party library written in the CommonJS pattern and want to convert it as part of a build process, you can use r.js to perform the conversion for you.
The problem is that requireJS doesn't support CommonJS modules only AMD. So if the third party library doesn't support AMD then you'll have to jump through some hoops to get it to work.
If you have the option I would suggest using browserify or webpack for module loading since those are the tools that the majority of the react community have chosen and practically all third-party react components are published on npm as CommonJS modules.

Node JS fs module inside browser

I have a scenario where I want to export data to CSV from the client-side. I will have a textbox/area or whatever where the user can input data and then ideally with one click, a local CSV file will be updated with that data.
This is easily achievable with NodeJS with server interaction, and its core modules (specifically fs module), but apparently not so much from a browser.
I found out that certain node modules (for example underscore), support RequireJS's method of making a particular module work in the browser. So for underscore I did this:
methods.js
define(['underscore'],function(_) {
var Methods = {
doSomething: function() {
var x = _.size({one: 1, two: 2, three: 3, xuz: 3});
alert(x);
}
};
return Methods;
});
common.js
requirejs.config({
baseURL: 'node_modules',
paths: {
underscore: 'underscore/underscore',
}
});
require(['methods'], function(y){
y.doSomething();
});
index.html
<script data-main="common" src="require.js"></script>
<script>
require(['common'], function() {
require(['methods.js']);
});
</script>
The above works fine and will show an alert: 4.
But when I try the same with the fs module it won't work. It will show this error:
Module name "util" has not been loaded yet for context: _. Use require([])
As far as I can understand, this is because fs requires several other modules, one of them being util.
So I proceeded to add all these modules to the RequireJS config. But still no luck, so I specifically tested util module by itself as this doesn't seem to require other modules to work.
And now I am stuck on this error: Uncaught ReferenceError: exports is not defined
I tried modularizing this util module by encapsulating the whole module source code in this:
define([], function() {})
But it didn't work either... I've also tried copying underscore's model but still no luck.
So I was wondering if anyone managed to use util & fs modules (or any other core NodeJS modules) within the browser with libraries such as RequireJS or Browserify.
That's right, exports is node-specific JS (used to make part of your module available outside the module) and isn't supported by web-browsers. Even though NodeJS is technically JS, there are client specific properties (like the window property for browsers, and exports for NodeJS apps) that can't be interchanged.
That said, here's a client side JS answer to the CSV problem.
Your best bet (and probably only one) is to use HTML5 FileSystem API. I am not aware of any other browser feature that would allow to work with files on client computer except maybe Flash and similar solution.
I am bit confused by your browserify tag since you are not obviously using Browserify. That would fix your issue with "exports is not defined".

Testing Custom Modules with DOH

I'm trying to build some unit tests for an old JS file/module that is out of my control.
The JS module is built using the following pattern...
var myModule = {
myMethod:function() {
}
};
I am then trying to build a DOH test harness to test this. I tried the following...
require([
"doh/runner",
"../../myModules/myModule.js"
], function(doh) {
console.log(doh);
console.log(myModule);
});
The file seems to be getting picked up fine but I can't reference anything in it. "console.log(myModule);" just returns undefined.
Anyone know how I can correctly include an external non dojo module JS file in a DOH test harness?
Thanks
Other than you shouldn’t be using DOH because it is deprecated (use Intern), there is no reason that you shouldn’t see myModule there. You are using a script address and not a module ID, which isn’t right, and you are using a relative path with a require call, which is also not right, but if either of these things were preventing the loader from finding and loading the script you are trying to load it should be throwing an error that you could see in the console. The only other possibility is you have somehow managed to build a built layer into this myModule script, in which case the entire script ends up wrapped in a closure and so using var foo will no longer define a global variable foo.
You need to declare myModule in the function callback to your require statement:
require([
"doh/runner",
"../../myModules/myModule"
], function(doh, myModule) { // <-- include myModule
console.log(doh);
console.log(myModule);
});
Just be sure that myModule.js returns your module.

Categories

Resources