Modules using RequireJS is not exported properly - javascript

I am currently developing a local JavaScript app that will help me to dynamically generate some managerial documents such as invoices and vouchers for unpaid services for a specific client.
I'll be using node_modules, and so far I am using (["jsonfile", "uniqid", "mkdirp"]) these modules need require to be stored in a variable.
The problem is that I am calling jsonfile as mention in its documentation
var jsonfile = require("jsonfile");
When console.log(jsonfile) from javascript file it returns function localRequire() unlike if i wrote that command inside browsers console .. for that it will return
>> console.log(jsonfile)
Object { spaces: null, readFile: readFile(), readFileSync: readFileSync(), writeFile: writeFile(), writeFileSync: writeFileSync() }
undefined
and to make the problem more complicated, when calling readFile() from console or from the script it returns that readFile() is not a defined function rather for jsonfile or fs which is a node module that is required for jsonfile
>>function readFile()
jsonfile.readFile()
TypeError: fs.readFile is not a function
I don't really know what is the difference and how to use that variable from console than the variable of script. Especially that I don't redefine it in console after running the app.
Some code snippets you may need:
I am calling two scripts in index.html:
<!--requirejs -->
<script data-main="app" src="node_modules/requirejs/require.js"></script>
<!-- a script which will use $ which is not defined -->
<script src="services/specifyDocType.js"></script>
<!--the script the call require and have the jsonfile variable -->
<script src="jsonfile-test.js"></script>
app.js code:
requirejs.config({
//"baseUrl": "node_modules",
"paths": {
"app": "app",
"jsonfile": "jsonfile/index",
"graceful-fs": "jsonfile/node_modules/graceful-fs/graceful-fs",
"fs": "/node_modules/jsonfile/node_modules/graceful-fs/fs",
"jquery": "node_modules/jquery/dist/jquery.min"
}
});
requirejs(["dist/js/main"]);
main.js :
define("jquery", function($) {
$('body');
});
For the local script that will create jsonfile variable, here is the initial code I had to do the working test:
var data = 'DOCS/voucher/voucher.json';
var jsonfile = require(["node_modules/jsonfile/index"]);
console.log(jsonfile);
//this console that returns the function localRequire() mentioned above.
jsonfile.readFile(data, function(err, obj) {
console.dir(obj);
});
For this app, I don't need to use a framework such as Angularjs, and I need to use require for each module I am using so far to create unique ids and directories in the root directory.
One more thing, this is my console on the first run:
function localRequire() jsonfile-test.js:4:1
TypeError: jsonfile.readFile is not a function[Learn More] jsonfile-test.js:6:1
ReferenceError: module is not defined[Learn More] index.js:133:1
Error: Module name "fs" has not been loaded yet for context: _. Use require([]) http://requirejs.org/docs/errors.html#notloaded require.js:168:17
Use of getPreventDefault() is deprecated. Use defaultPrevented instead.

You seem to think that RequireJS is a drop-in replacement for Node's require call. It isn't.
Node supports the CommonJS module system. RequireJS supports the Asynchronous Module Definition (AMD) system. (See here for a question about the difference between the two.) It also provides support to facilitate consuming CommonJS modules, but it does not support consuming CommonJS modules as-is. At the very least, the CommonJS module must be wrapped in a define call. If you start with this CommonJS module, for instance:
function foo() {}
exports.foo = foo;
then you need at a minimum to convert it to this:
define(function (require, exports) {
function foo() {}
exports.foo = foo;
});
In addition, while RequireJS can consume CommonJS modules, it is not able to provide support for those modules that depend on the node VM. fs is one such module. It depends on the Node VM. It cannot be run in the browser. The DOM does not expose an API that the fs module could use to access the filesystem. jsonfile depends on fs so you cannot just load it with RequireJS in the browser. You could possibly find a module made to run in browsers that present an API compatible with fs and present a fake filesystem to the client code and this may work, but you have to do the job of finding the replacement module. RequireJS won't do this for you.

Related

Using Webpack to require revealing modules

I've just started looking into all the fancy stuff Javascript has to offer mainly Webkit. I've got a decent sized application which uses the revealing module pattern. These modules make calls to public functions of other modules to make calculations and return results.
Using this pattern was working great until I started to contemplate having dozens of script includes in my html pages. So, here we are...
For the purposes of the question, I have made a much simpler application to demonstrate what is going wrong for me.
I have two javascript modules contained within their own files:
// one.js
require("babel-loader?two!./two.js");
var one = (function(){
two.sayHello();
})()
// two.js
var two = (function(){
var sayHello = function(){
console.log('Hello World');
}
return {
sayHello: sayHello
}
})()
What I'm trying to do is use sayHello function from two.js within one.js.
So, firstly, I installed Webpack and exports-loader and created the following configuration file:
module.exports = {
entry: './index.js',
output: {
path: __dirname,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx$/,
loader: "babel-loader",
query: {
presets: ['es2015']
}
}
]
}
}
index.js is my entry file and simply includes the following single line:
require('./one.js');
Now, when trying to run this code, I'm getting the following error in the console:
Uncaught ReferenceError: two is not defined
With a little more digging, I found that my compiled bundle.js file was throwing the following Error when trying to import two.js:
throw new Error("Module parse failed: \testing_env\webpack\two.js
'import' and 'export' may only appear at the top level (2:2)\nYou may
need an appropriate loader to handle this file type.
Obviously i'm doing something wrong, I'm just not sure what. I've tried both exports-loader and babel-loader but with no joy.
Which loader should I be using to parse module dependencies?
Any help would be greatly appreciated.
Out of the box webpack has support for CommonJS (which is the same module system that Nodejs implements). This means that you need to use the require/export syntax to make use of the modules.
To export something in a module you simply do:
// a.js
function a() { console.log("I'm a module '); }
module.exports = a;
and in your other module you do:
// b.js
const a = require('./a.js');
a(); // I'm a module
require() will simply returns the exports object. Whatever you put on it you will be able to retrieve in another module.
This is why webpack is a module bundler, it comes with a built in module system. The revelaing module pattern is more practical if you load your JS files directly in the browser without a module bundler, and you want to incapsulate your data (in "modules").
The Revelaing module pattern is useful when you don't have a module system and you simply load up your JS files in the browser. Till recenlty when ES Modules were introduced in the browser, JavaScript didn't have a module system of it's own. This is why people came up with the module pattern, to have a way to incapsulate logic in the browser. But now because of tools like webpack and now we have natively the ES Modules system, we can have a more better way to incapsulate our logic.
Does this make sense?

ReferenceError: Can't find variable: require - JQuery error

I use this code in my .js file which is part of web site that is used via npm global http-server:
function getParsedStorage() {
let fs = require('fs');
return JSON.parse(fs.readFileSync('./../manager-data.json', 'utf8'));
}
and get errors:
jQuery.Deferred exception: Can't find variable: require (2) (exceptionHook — jquery.min.js:2:31584)
ReferenceError: Can't find variable: require (jquery.min.js:2:31697)
I've installed file-system package with npm install file-system --save but that didn't change anything.
It looks to me like you're attempting to make use of Node.js's require function from within a web browser without using a module system that provides a compatible require method.
Without additional information I can't be certain, however my advice would be to investigate a module loader like Require.js, SystemJS or Browserify which should all enable you to make use of this syntax in your module.
That being said, for the use case you're describing (accessing a JSON file from a website) you may be better served using a simple XHRHttpRequest or the fetch API.
The following is an example which makes use of the fetch API to return the parsed JSON file content.
// Returns a Promise that resolves to the parsed storage data
// NOTE: Lacks any error handling
function getParsedStorage() {
return fetch("../manager-data.json").then(response => response.json())
}

When using requirejs, which approach to pulling in dependencies for a defined module is better? [duplicate]

I was wondering what the difference between these snippets is.
var $ = require('jquery');
var _ = require('underscore');
var BackBone = require('backbone');
and
require(['jquery','underscore','backbone'],function ($, _, BackBone){
//code goes here
})
Both work fine for me, but not sure is their any purpose behind the above two.
Consider the first snippet, which is in the CommonJS style:
var $ = require('jquery');
var _ = require('underscore');
var BackBone = require('backbone');
These calls are synchronous calls: when require returns, it returns the module you requested. CommonJS require calls are synchronous. There is a proposal for supporting asynchronous forms of require but as far as I can tell it has not progressed beyond the proposal level. Node.js used to have require.async which has been removed. There's a package that implements it though. Using this package looks at lot like using AMD style modules.
Now, consider the second snippet, which is in the AMD style:
require(['jquery','underscore','backbone'],function ($, _, BackBone){
//code goes here
})
Since RequireJS implements the AMD type of module system, the above code works with RequireJS. This require call is --- as suggested by the name Asynchronous Module Definition (AMD) --- asynchronous. You can't rely on the return value of require to get a module value. You have to use a callback instead. The define call works in a similar way but defines a module in addition to requiring modules.
Now, if you use RequireJS, it provides facilities that allow to use either style when you define modules so that you can define a module like this:
define(['jquery','underscore','backbone'],function ($, _, BackBone){
//code goes here
});
Or use something that looks more like the CommonJS idiom like this:
define(function (require) {
var $ = require('jquery');
var _ = require('underscore');
var BackBone = require('backbone');
//code goes here
});
It makes it really easy to convert a CommonJS style module to use with RequireJS: just wrap it with a define call as above. There's a tool to help the conversion.
Behind the scenes, RequireJS reads the code of the callback in the 2nd form and creates a list of dependencies so that in the end it is interpreted like:
define(['require', 'jquery','underscore','backbone'], function (require) {
var $ = require('jquery');
var _ = require('underscore');
var BackBone = require('backbone');
//code goes here
})
It may be surprising (given that AMD is asynchronous) that the require calls in the callback are synchronous. This is part of RequireJS's support for the CommonJS style. RequireJS supports a kind of synchronous require call but with the following caveat: if the module is already defined before the call to the synchronous require, then the synchronous require returns the module's value, but otherwise it fails immediately. That is, it does not try to load a module. Because RequireJS interprets a module definition that uses the CommonJS style as I've shown above --- as if the dependencies were actually listed in the define arguments --- then these modules are guaranteed to be loaded by the time the synchronous calls to require are made.
Besides being able to use CommonJS modules in RequireJS (provided a wrapper is added), it is also possible to use modules designed for RequireJS in a CommonJS environment like Node.js. For instance, I've used node-amd-loader to load modules I've designed as AMD modules in Node.js.
The former snippet adheres to the CommonJS spec, which outlines how modules are to be exported/transported to be used in other modules.
So, you could write code which could look like this
src/ExpressModule.js
var express = require('express');
// do initialization
exports.express = express;
And then you can use it like this
src/UserExpressModule.js
var express = require('./ExpressModule');
// do something else
CommonJS spec was built primarily for server side environments, and by extension, is used in Node.js
On the other hand of the spectrum is AMD, most notably implemented by RequireJS. AMD was built for browser environments, or client-side code, and here you can use and define modules like the latter snippet in your code
A sample use could be like this
src/main.js
requirejs.config({
baseUrl: '../vendor'
path: '../src'
});
require(['jquery', 'underscore', 'backbone'], function($, _, Backbone) {
// do some client side computation here
});
You can then include this main.js file in your index.html like so
<script data-main="src/main.js" src="vendor/require.js"></script>
Essentially, CommonJS and AMD are at their core specifications for modularizing Javascript, but are aimed at different execution environments.

Am I using requireJS wrong, or is the library I downloaded severely bugged?

I'm trying to use a JS library (this) which makes use of the require function. To use it, I understand I have some options, as elaborated on here. So I go with requireJS and I link to it and the library I want to use as such in my html file.
<script src="requirejs/reqjs.js"></script>
<script src="LIBRARY_I_WANT_TO_USE/index.js"></script>
the first line of index.js looks like this
var foo = require('PATH')
For that line, the console outputs this error:
Uncaught Error: Module name "PATH" has not been loaded yet for
context: _. Use require([])
So I find this at requirejs.org:
This occurs when there is a require('name') call, but the 'name' module has not been loaded yet.
It goes on to suggest ways to resolve the problem. But I hesitate to start modifying the code of the library I just downloaded. Now my question is,
Is the library I downloaded bugged, or am I doing something wrong?
That library is written using CommonJS modules, not AMD modules (which is what RequireJS implements).
You need to use browserify to bundle it into a single file that can load in the browser.

Where are the CommonJS modules?

From time to time I hear that CommonJS http://www.commonjs.org/ is an effort to create a set of modular javascript components but frankly I have never understood anything of it.
Where are the these modular components I can use? I don't see much on their homepage.
CommonJS is only a standard that specifies a way to modularize JavaScript, so CommonJS itself does not provide any JavaScript libraries.
CommonJS specifies a require() function which lets one import the modules and then use them, the modules have a special global variable named exports which is an object which holds the things that will get exported.
// foo.js ---------------- Example Foo module
function Foo() {
this.bla = function() {
console.log('Hello World');
}
}
exports.foo = Foo;
// myawesomeprogram.js ----------------------
var foo = require('./foo'); // './' will require the module relative
// in this case foo.js is in the same directory as this .js file
var test = new foo.Foo();
test.bla(); // logs 'Hello World'
The Node.js standard library and all 3rd party libraries use CommonJS to modularize their code.
One more example:
// require the http module from the standard library
var http = require('http'); // no './' will look up the require paths to find the module
var express = require('express'); // require the express.js framework (needs to be installed)
The idea, it seems (I wasn't aware of this), is to provide javascript to more than just web browsers. For example, CouchDB supports javascript for querying.

Categories