Is it possible to implement or at least simulate code hot swapping in Node.JS? If yes, how?
Hot swapping (frequently called hot plugging) is replacing or adding
components without stopping or shutting down the system. Erlang and
Lisp support hot swapping natively.
For commonjs modules (original node.js module system) you can hot-swap modules by deleting its cache and re-requiring them:
delete require.cache[require.resolve('my-module')];
require('my-module');
I'm not sure if this works with es6 modules.
Of course, this needs to be done everywhere the module is loaded because otherwise your code will be using the objects and functions returned by the previous version of the module that is still in RAM.
One way to trigger a cascading reload is to make your main code also a module that is executed by a simple script that requires it. Then reloading your main module would cause it to reload other modules that it uses.
You may not need hot-swapping
In actual practice however you may find that you don't really need hot-swapping. Most node.js servers take milliseconds to boot. Part of the reason for this is most I/O libraries in node.js connect to external services lazily. Node.js servers generally don't wait for database connection to succeed before executing the rest of the code. Instead it will try to connect to the database the first time you make a database request.
Also, javascript is a fast language to parse and compile (by necessity because you send the source to web pages)
Old trick with Webpack https://github.com/minimal-xyz/minimal-webpack-nodejs-hmr .
Webpack has support for hot module replacement and Webpack also supports compiling Node.js apps, and it works to combined these two features. Notice: it's designed for development, NOT for deployment.
While it's already a viable solution, I consider Webpack includes too many features which makes it quite heavy. I'm still in hope that we have lighter solution for that one day like how it's supporting HMR by default in ClojureScript.
Yes, you can use eval to hot-swap code in Node.
let fn = () => console.log('foo');
fn(); // foo
eval(`fn = () => console.log('bar');`); // hot swap the source of fn
fn(); // bar
Related
I have been reading multiple different articles about what Isomorphic application is, why this type of architecture is better and so forth. But I still have a bit of uncertainty as to what is meant by such term.
How would you define what "Isomorphic Application" is, without going too much into details?
They are, more recently, also called universal. I'm not sure about the whole app being called isomorphic/universal, but you can certainly have parts of the code base that is universal.
Isomorphic/universal code is code that runs on both the client (browser) and on the server (NodeJS). Since they are both JavaScript this something that is possible if:
you do not mention window, document or any other browser-only methods
you do not mention server, fs or any or any other node-only methods.
If you do need to do the above within some code that is meant to be universal, you should wrap it in a function that either mocks the required method within the alternate environment or wrap it in conditionals so that the app doesn't crash.
An example is console.log which will work both within NodeJS and any browser, along with most other es6 methods in modern browsers.
I use build tools (like webpack) to then help create / export functions within individual files so that we then have a bundle like client-app.js which is included in the HTML file and is the browser only js. The server then might start using server-app.js which is the server-only bundle. Both bundles can be created using a lot of the same universal source code.
I have a node app that uses ES6. I'm using Babel for transpiling.
As far as i understand use a build system like Gulp for example or use the require hook .
The Require Hook approach seems appealing to me since i will be able to keep my source files in ES6 but still execute them using node server.js without the use of some build system.
This seems extremely useful for develop at least, my main concerns is about the use of this approach in production.
Does it have any penalty hit every time that a user makes a request ?
How this works exactly ?
For context i'm using it with an Express app.
Does it have any penalty hit every time that a user makes a request ?
No, not in the sense that it would have to re-transpile the code on every request.
How this works exactly ?
The require hook basically hi-jacks all subsequent calls to require(), and performs the ES6->ES5 transpiling prior to that module being executed.
I've been using the babel require hook in production for awhile now (with moderate traffic levels -- peak traffic in the mid-hundreds req/sec range), and it's never been an issue.
Am I simply ignorant of the features that some browsers offer or does this library use some strange workaround to implement these features?
Actually, it's neither nor ;-)
Basically, the simple answer is: Browserify does not bring everything into the browser, only the things that actually make sense and are feasible from a technical point of view.
E.g., you can easily have
url.format(...)
in the browser, as this means only handling objects and strings in memory, but you can not have
http.createServer(...)
since this simply does not work. Additionally to this, Browserify provides shims for require and module.exports, hence you can use CommonJS modules in the browser as well, but only as long as they stick to the things that are available there. Again, e.g., any CommonJS module written in C++ will not work in the browser, with or without Browserify.
Finally, Browserify uses several modules that are basically API-compatible to Node.js, but have been rewritten for the browser, e.g. http-browserify.
So, in the end, it is a great tool for so-called "isomorphic JavaScript", or in other words: To use CommonJS modules on the server and in the browser without the need for special patterns on either side, such as AMD or UMD.
But, of course, it does not provide any magic :-)
Browserify doesn't add functionality to your browser. It compiles your Node.js code so that it is runnable inside of a browser.
In short, Browserify allows you to use Node's require in your browser-side code; it does not grant your browser access to network and filesystem abilities that it doesn't already have.
Instead, you'll need to use (or write) custom modules that simulate the server-side capabilities. For example, if you use a database module in your server-side code (e.g., Postgres or Mongo), you could write a new database module (with the same API as the server-side module) that uses browser-supported storage mechanisms like IndexedDB.
I would like to create a (require.js style) AMD module that can be used in the browser and in node. What is the best way to do this? I keep seeing references to r.js, but still not 100% sure on how to use it, or if it is necessary for my situation.
Also, when including this module in node, do I still run require('module-name'), or will this change as well?
First things first: AMD basics, What all you can do with them, How to optimize them
In extremely simple terms
AMD modules are reusable JS code. Think of them as functions kept in separate files.
AMD loaders are central functions which call all other functions (modules). Think of them as "main" method in C or Java.
RequireJS is a framework which pulls all this scattered code and stitches it in a usable form.
RequireJS works in a browser. As a result, all your code is "stitched" together in a web browser.
r.js works offline (in a web server or on your development machine) to "stitch" all the code offline so that when it reaches a web browser, it's already "stitched".
Use of RequireJS lib is a must no matter you want to "stitch" your code in browser or you want to serve your code "pre-stitched".
Use of r.js is optional. It's needed only if you want to increase performance and decrease HTTP calls.
In the process of evaluating the various approaches available to developers to use javascript modules, module loaders and build tools, i'd like some suggestions on what tools you use, and why.
I'm currently after something that is able to:
-encourage modular code
-allow features to be added based on necessity to a given module [think mixins/inheritance]
-produce a BUILD that contains a development release, and at the very minimum a production release with different layers (say, i want a layer [a script] which contains my bootstrap code, module 1, 2 and 3; and then another layer which contains modules 4,5 and 6. This way I can defer loading of code based on what's actually going on in the application.)
-Work [when built for production] in an extremely low bandwidth scenario, with xfer speeds of 1kbps and high latency (think worst case mobile connection over GPRS to get the picture).
I've seen the following:
Using prototype inheritance, as in:
myNS.thing = function(){};
myns.thing.prototype = {
something: "foo"
}
Which can be built by simply taking the contents of this script, and appending it to the next one one wants to include in a production optimized package as a single script. Loaders in this case are simple script tag injections/eval's or similar, based on a known file.
I've also seen other approaches, such as:
function(){
return function(){
something: "foo"
}
}();
Building this already gets more complex because one has to manipulate the script, removing the wrapping self executing function and combining the return values into one object. I am not aware of an "easy" way to use available build tools. The loader approach works the same as above.
Both of these approaches lack dependencies.
Then we have AMD:
define("mymodule", ["dep1"], function(dep1){
return {something: dep1}
});
Some might be nauseated by its indenting, and its "ceremony", but still its quite effective, the google closure compiler knows about it natively, it knows about dependencies, and seems to have widespread adoption across the board. There are a bunch of module loaders available for it (https://docs.google.com/spreadsheet/ccc?key=0Aqln2akPWiMIdERkY3J2OXdOUVJDTkNSQ2ZsV3hoWVE#gid=2) and quite a few build tools as well.
What other options do you know of, or have you seen used in production?
As said, i'm interested in a combination of code syntax, loader tools and build tools. These three must exist and be working together properly. The rest is an academic excercise i'm not interested in.
I personally use RequireJS, an AMD solution. If I'm whipping up quick proof-of-concepts I won't bother setting that up, but the most common source/dep-mapping solutions I know of now include:
RequireJS
CommonJS
Google Closure
YepNope (a conditional loader, can be used in combination with the others)
I have started a boilerplate that uses Require in combination with Backbone to get all the ugly setup code out of the way:
https://github.com/nick-jonas/assemblejs
So you can type assemble init to scaffold the basic project and assemble build to run the compilers and get a final production-ready build.
You might be interested in looking at Grunt a command line tool with various modules for building javascript projects. It uses npm for dependencies and it will work with amd modules, but you can just configure it to concatenate the files you need using grunt-buildconcat.