I am trying to combine files using the grunt plugin for requirejs:
https://www.npmjs.org/package/grunt-contrib-requirejs
Here is the configuration:
requirejs:
compile:
options:
#appDir: './'
baseUrl: "client"
mainConfigFile: "client/test1.js"
name: "test1"
out: "build/test.js"
onModuleBundleComplete: (data) ->
outputFile = data.path
fs.writeFileSync(outputFile, amdclean.clean(
'filePath': outputFile
))
wrap:
start: ""
end: ""
Here are the input and output javascript
Input:
test1.js
var x = console;
require(['test2'], function() {
return console.log('Hello');
});
test2.js
x.log('this is test2');
test.js
var test2, test1;
x.log("this is test2"), null, test2 = undefined;
var x;
x = console, function () {
return console.log("Hello")
}(), test1 = undefined;
The program works fine when loaded in browser with requirejs. But after the build is done, it does not work. This is because the definition x=console is provided before the code in test2.js is loaded when the modules are loaded using requirejs.
However, after the build, the definition x=console appears after the code from test2.js is loaded - which creates an error - because test2.js makes a call to x which is a global variable between the two js files.
I need to ensure requirejs builds the project into a single .js file while ensuring that no amd code is present (require/define) and the code is executed in the EXACT same order as with requirejs loaded in the browser.
I think you may need a better understanding of the Asynchronous Module Definition (AMD) API specification. In either case I've modified your code a little bit to better adhere to AMD's syntax and I've created a a third file to define x like this:
test1.js
// Require the 'test2' module (which is passing x; which is equal to console)
require(['test2'], function(x){
x.log('this is test1');
});
test2.js
// Define the 'test2' module which depends on the 'x' module
define(['x'], function(x){
x.log('this is test2');
return x; // Return x; which is equal to console
});
x.js
// Define the 'x' module which has no dependencies
define(function(){
console.log('this is x');
return console; // Return console
});
Related
Getting a module is not defined error attempting to import a module from the local project. Using node and requirejs -
Error: Evaluating /Users/Projects/stash/NODE/project_js/src/foo.js as module "foo" failed with error: ReferenceError: module is not defined
Code looks like -
(function() {
const requirejs = require('requirejs')
requirejs.config({
baseUrl: __dirname,
nodeRequire:require
});
//var foo = requirejs('foo.js');
requirejs(['foo'], function() {
foo().then(data => {
data.foreach(function(item, index, data) {
console.log(JSON.stringify(item))
})
});
})
})();
The module has the following export -
module.exports = function foo() {
.
.
.
return results
}
I've tried loading the module synchronously as well.
Check this part of their doc: if the module to be loaded (foo here) is found by RequireJS (i.e. its configuration allows it to find the module), then this module has to be declared using define instead of Node's exports.
I just tried this, which works:
directory structure
test/
index.js
foo.js
index.js
(function() {
const requirejs = require('requirejs');
requirejs.config({
baseUrl: __dirname,
nodeRequire:require
});
requirejs(['foo'], (foo) => {
console.log('loaded!', foo, foo());
});
})();
foo.js (that's the interesting part)
define(function() {
return function foo() {
return 'fooResult';
}
});
Using module.exports = ... gave me the error you have.
However this RequireJS API is not "loadable" by Node's built-in require, hence the need for a precise configuration that reflects a clear separation between Node-required modules (CommonJS API) and RequireJS-defined modules (AMD API). (Actually you can check the whole "Why AMD?" page, that should help a lot for your work with RequireJS.)
My problem is the following:
I use gulp+browserify to compile my TypeScript to JavaScript that you can use on normal HTML pages, the problem is that my class is never available on the browser:
VM633:1 Uncaught ReferenceError: Test is not defined
at <anonymous>:1:13
This is my TypeScript File:
class Test {
public test(): void {
console.log("aa");
}
}
This is my gulpfile
var gulp = require("gulp");
var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");
gulp.task("default", function () {
return browserify({
//basedir: '.',
debug: true,
entries: ['app/Resources/typescript/Test.ts'],
cache: {},
packageCache: {}
})
.plugin(tsify)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest("web/bundles/framework/js"));
});
The file compiles without problem, and is included in my index.html (the compiled js file).
But when i try:
var t = new Test();
I get the following error:
VM633:1 Uncaught ReferenceError: Test is not defined
at <anonymous>:1:13
I can't resolve it, I have read a lot and I haven't found anything clear, I tried all and nothing worked.
There are a few things missing here:
If you want your class to be accessible outside of your module, you have to export it:
export class Test {
// ...
}
Browserify creates functions on top of the classes you define. So it won't be accessible globally (which is a good thing). Normally you would import it in another file and use it:
// in any TS file that wants to use `Test` class. Make sure this is included in the gulp entries as well
import {Test} from "test";
var t = new Test();
console.log(t);
Or if really want it to be accessible globally, you can attach it to window object:
// In Test.ts file:
(window as any).Test = Test; // This can be useful when debuging. But don't do this in production code.
Currently I am working in custom html reporter for intern.js. The Templating engine that i am using is marko.js.
marko.js have extension file with ".marko" for me to input my html syntax
The file is generated correctly in normal node.js (common.js)
The issue occurred when i integrate the same code to intern.js. The requirejs(AMD) that use by internjs is adding the .js file extension automatically to my marko extension when i do
var template = require('./hello-world.marko');
which make the file become hello-world.marko.js and this caused the code broke in markojs
the custom html reporter code is below
define(function (require) {
// require('intern/dojo/node!marko/node-require').install();
var fs = require('intern/dojo/node!fs');
var template = require('./hello-world.marko');
console.log(template);
function JsonReporter(config) {
config = config || {};
this.output = config.output;
}
JsonReporter.prototype = {
runEnd(executor) {
// console.log("toJson: " + JSON.stringify(executor.suites))
data = JSON.stringify(executor.suites);
template.renderToString(data,
function (err, output) {
console.log(output);
fs.writeFile('result.html', output, function (err) {
if (err) return console.log(err);
console.log('Save done');
});
});
},
}
return JsonReporter;
})
The require function isn't really meant for loading arbitrary text resources in either Node's loader or an AMD loader. In Node, whether you're running Intern or not, you can use fs.readFile or fs.readFileSync. In Intern's Dojo-based AMD environment you can also use the dojo/text loader plugin, like this:
var template = require('dojo/text!./hello-world.marko');
Just started using node with requirejs last night.
I want to substitute a module depending on a configuration parameter (say, passed in from the command line).
Right now, moduleA requires moduleB. How can I overwrite moduleB, or substitute moduleC for it?
EDIT
I'm using RequireJS.
I really want a third party module, say moduleMaster to specify the update. The goal is to allow multiple possible behaviors (ie multiple Database Access Objects, 1 per module) and then allow a master module to choose which one the other modules use. Something like:
// module A
define(['B'], function(B) {
console.log(B.msg);
});
// module B
define({
msg: "I am B"
});
// module C
define({
msg: "I am C"
});
// module D
define([], function() {
// TODO: overwrite moduleA so that it uses moduleC instead
});
There is no such thing as overwriting a module. What you can do is have RequireJS change what it loads depending on a configuration option. For instance,
var requirejs = require('requirejs');
var define = requirejs.define;
define('A', ['Adep'], function(Adep) {
console.log(Adep.msg);
});
define('B', {
msg: "I am B"
});
define('C', {
msg: "I am C"
});
var make_A_depend_on = 'C';
requirejs.config({
map: {
'*': {
'Adep': make_A_depend_on
}
}
});
requirejs(['A']);
If you change make_A_depend_on so that the value is "B" then A will load B rather than C. The configuration is set so that when the madule named Adep is required, RequireJS actually loads what is specified in make_A_depend_on.
is it easy/possible to run a node js file from another node js file?
For instance, i'm having two files test1.js and test2.js. i want to execute the test1.js file from test2.js.
I think the better way to accomplish what you're trying to do would be to do what my other answer suggests. But to execute commands on the command line as your questions suggests, you want to use child_process.exec. For example:
var exec = require('child_process').exec,
child;
child = exec('node test2.js {{args}}',
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
You simply run require('test2.js'), and then call a function on the exported object. From the documentation on modules:
Node has a simple module loading system. In Node, files and modules are in one-to-one correspondence. As an example, foo.js loads the module circle.js in the same directory.
The contents of foo.js:
var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is ' + circle.area(4));
The contents of circle.js:
var PI = Math.PI;
exports.area = function (r) {
return PI * r * r;
};
exports.circumference = function (r) {
return 2 * PI * r;
};
The module circle.js has exported the functions area() and circumference(). To export an object, add to the special exports object.
Note that exports is a reference to module.exports making it suitable for augmentation only. If you are exporting a single item such as a constructor you will want to use module.exports directly instead.
function MyConstructor (opts) {
//...
}
// BROKEN: Does not modify exports
exports = MyConstructor;
// exports the constructor properly
module.exports = MyConstructor;
Variables local to the module will be private. In this example the variable PI is private to circle.js.
The module system is implemented in the require("module") module.
There are different scenarios here - using modules, loading them "the right way" - it's the way to go when writing your own code.
What about "random" .js files, e.g. downloaded via web scraping? (If this is a good idea to execute them is beyond the scope of this answer...)
Well - you can just require them, if you're only interested in the side effects:
test2.js:
console.log('hello')
test1.js:
console.log('about to execute')
require('./test2.js')
console.log('done')
Note the ./ in require(). But, if you want to run it twice, this won't work:
test3.js:
console.log('about to execute twice?')
require('./test2.js')
require('./test2.js')
console.log('surprise')
This shows, that require works like a Python import - only executing the file if it hasn't been loaded yet. But - it's possible to circumvent it and force a reload: How to remove module after "require" in node.js?
test4.js:
console.log('about to execute twice!')
require('./test2.js')
delete require.cache[require.resolve('./test2.js')]
require('./test2.js')
console.log('NO surprise this time around')
The difference from a Python import is that you can't import anything unless it's exported. So you would have to change the required file and do something with module.exports.
If you're working with the node shell, there is an alternative:
test5.js:
console.log('the const below is private?')
const x = 5
And then:
$ node
> .load test5.js
console.log('the const below is private?')
const x = 5
the const below is private?
undefined
> x
5
Note that there are no quotes around filename in .load, and also no ./. This is somewhat verbose when used (echoing the loaded script). But it is at least some way of playing with the values the script creates.
Final warning: always be careful about what you're about to execute!