I have a C++ Node.js add-on. I can run use v8's RunScript to run execute javascript in the context of the native module.
Now, I also would like to execute a JS statement that contains require.
Unfortunately, the native module is setup in such a way that the context does not include require. I get the error:
ReferenceError: require is not defined
Is there a way prepare the native module's context such that it behaves like a standard node.js module ? i.e. it provides the require method?
I have met the same issue, what I have done was adding this be code below, prior loading my addon.
global.require = require;
Related
I'm learning how to use Flux and I encountered the following line in the documentation: "We can use Node's EventEmitter to get started with a store."
I understand that you can use things like Browserify to do the bundling and minifying, grabbing all the dependencies that Node code has to make the bundled browser-compatible JS file. But what's bugging me right now is how you know what you can do this with. How do we know what Node code we're allowed to use in the browser?
So, first of all let's consider that when in node you have
JavaScript modules that are the 3rdParty modules written in JavaScript (ECMA5, ECMA6 and even TypeScript or CoffeScript) etc;
Node built-in module. Those are node Core modules like fs, path, util, etc.
native compiled module called Addons that are are
dynamically-linked shared objects, written in C or C++;
Then you have the packager / module bundlers
Browserify
Webpack
the transpilers i.e. source to source compilers that typicall will handle syntax tranforms like
Babel.js that shims modern JavaScript to legacy engines
and the techniques
ECMA5 Shim to support legacy JavaScript engines
HTML5 Cross-Browser Polyfills
Because you need to do polyfills if you want to transform not only syntax but even globals (like the Promise), so you combine transpiler to polyfill having like babel-polyfill
Finally we have different kind of modules design patterns (modules format) to be handled for the bundling process:
AMD modules format
CommonJS modules format
and formats that are not in those ones that must be bundled/shimmed - where possible - through custom loaders.
That said, native modules will not run in the browser: you cannot bundle a native module through Webpack. Ordinary modules will, but not all. This is due to several reasons. There are some specific methods that cannot be "browserified" or "webpacked". Let's take as example fs. Can you put this built-in module in the browser? There are some abstraction for that called brfs, that are transforms for built-in node apis fs.readFileSync() and fs.readFile(), so you will do
$ browserify -t brfs example/main.js > bundle.js
to get
var fs = require('fs');
var html = fs.readFileSync(__dirname + '/robot.html', 'utf8');
console.log(html);
This will not work for every non built-in modules, in the npm modules jungle, so WebPack has a module.noParse option to exclude Addons modules, non supported modules, etc. - see here about that.
So you have to look at the list of the transforms that means you can apply this transform to browserify to obtain like the fs transform mentioned above.
So that said, how do you know that a certain module will run in the browser? When you design your web application and Node backend you have to do opportunistic design choises to design shared modules/library that will run in both the environment, so being shimmed/packed at some point, like object models, application logic, etc., other modules that will deal with the File System I/O or will use native addons, so that will work in the server only, packing through wrappers it's possibile, but the behavior will look differently, as we have seen in the fs example above, and web specific modules, so it's a design matter.
A note can be added about networking modules i.e. node http, https that thanks to library abstractions like node request will run everywhere or using specific transforms like http-browserify.
I'm writing an application using NW.js and TypeScript. I would like to use one class per file.
To access node.js modules, I need to use require(). However, the document context within a require()d module is no longer the browser's document context.
It seems to me that I need to stick to namespaces to be able to access the browser DOM from my application.
How can I combine those two module styles in one TypeScript application? When trying to use namespace together with require, my types suddenly lose visibility across files (because the compiler goes into external module mode.)
It seems to me that I need to stick to namespaces to be able to access the browser DOM from my application
No. You can use a module loader like webpack to bundle the portions that the browser needs into a single bundle.js while still keeping all your code base in commonjs mode.
More
A quickstart is available : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html
More More
I am actually creating an OSS editor that demonstrates this : http://alm.tools/. The whole project (backend + server) has a single tsconfig.json file.
I setup a website with regular client side RequireJS today. Than I did some research on node, got that installed and setup my first module in node. When I setup the first require, I loaded the Require.JS file and I get all that. The thing that is confusing me is, I created a file called test.js and within that I am including:
var require = require("requirejs");
which is actually including the node require, not the original require library I was using right?
So like are they completely different? Can they used together?
Doesn't Node already have a module loader?
Yes Node does.
That loader uses the CommonJS module format. The
CommonJS module format is non-optimal for the browser, and I do not
agree with some of the trade-offs made in the CommonJS module format.
By using RequireJS on the server, you can use one format for all your
modules, whether they are running server side or in the browser. That
way you can preserve the speed benefits and easy debugging you get
with RequireJS in the browser, and not have to worry about extra
translation costs for moving between two formats. If you want to use
define() for your modules but still run them in Node without needing
to run RequireJS on the server, see the section below about using
amdefine.
Source: http://requirejs.org/docs/node.html#1
I have a question around the dependency injection based on AngularJS and NodeJS.
There's any difference between $injector from AngularJS and the require module from NodeJS?
Would be nice use require module with a MEAN STACK architecture instead $injector for the Angular app? And for whar propose?
They're quite different.
Angular's $injector is a classic example of Inversion of contorl. Instead of each module fetching their dependencies, you have an $injector whose job it is to provide dependencies to the modules that are asking for them at run-time. This makes it really to easy switch out the dependencies in tests for example, since nothing is forcing you to pass in the expected dependency -- you could pass in a mock version.
NodeJS's require methods just allow you to require other javascript files and have access to any properties they set on module.exports.
They're not mutually exclusive. You could use browserify (nodejs like require for the front-end) to load the different Angular modules if they are in separate files. It would essentially be equivalent to concatenating them, however. If you wanted to dynamically load the angular modules as needed, you would have to use something like RequireJs.
Conversely, you can use inversion of control in node by passing stuff into a module rather than trying to fetch it from the module. It's actually good practice in many cases.
Installing TypeScript requires node.js. And I assume that TypeScript uses Node.js to compile the .ts to a .js file.
My question is, does that created .js file require node.js? The ones I've seen so far appear not to. I don't want to load node.js into my html pages if it's not used.
thanks - dave
No, TypeScript just emits regular JavaScript.
If you use the "external modules" feature of the language (import x = require('foo');) you'll need to compile for either CommonJS (node) or AMD (require.js) and have those available, but that's opt-in.