Standard NodeJS app utilising module.exports to make the code modular. We'd like to combine all of those files together into a single file a la RequireJS on the client side (which is what we use there). Does anyone know an easy way to do this server-side without wrapping everything in more module wrappers (e.g. RequireJS) e.g. command-line tool ?
Ta
N
If you want to use node.js modules on the client side without additional wrappers (like RequireJS), you'll want to look into using browserify:
https://github.com/substack/node-browserify
It's a very useful build tool that allows you to use node-style require() statements and native node.js modules on the client side. Or, to quote from the github page itself:
Make node-style require() work in the browser with a server-side build step, as if by magic!
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 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'm building an app that will contain many js (jquery) modules (files) using the following setup;
The build is run using Grunt task runner.
I use handlebars templates, then generate the html from *.hbs files.
During the build, I uglify all the js files into one minified file.
I call the minified file in my application <script src="assets/js/app.min.js"></script>
Now, I want to use requirejs to organize my code and adhere to the AMD specifications..
But I got 3 problems with this approach:
I need to have 1 single minified file for all the js; this keeps my code harder to "decode" thus to copy (since it is mixed with other dependencies; jquery, modernizer..) and also helps avoid extra http requests if scripts are called individually.. However, requirejs needs a main file to initialize the app and inside that main file It calls the other required files.. I don't have such configuration.
Many of the dependencies I'm using are in a bower package (that I don't include in the distribution); this makes it not possible to call those files using the suggested requirejs method.
I'm using jquery on this with some 3rd party plugins that don't call define(); to make them work I have to use shim config which again rises the problem #2!
So how am I supposed to take advantage of requirejs while keeping my code in modules and well organized?
Sorry for the long question and thanks for reading :)
ps: Feel free to change the title of the question as I couldn't find a better one!
I finally opted for AngularJS as it adheres to my setup above and allows me to split my app into manageable small modules.
I have also the possibility to use the ease of jQuery (even though it is not a best practice among angular community) and much more.
So I started coding a chess engine in typescript as a side project. I initially intended it to be a CLI like most other chess engines that interact through stdin and stdout. This so I could plug it to a GUI like Arena and test it against other engines. For that I decided to do it as a node project.
I set it across several files with 1 being the UCI (universal chess interface) implementation and the remaining ones chess logic and AI logic. After banging my head a few times trying to understand modules in typescript I finally got it to work.
Now I decided it would be interesting to write a simple GUI myself as a webpage with html+typescript+jquery. Now, I would like to use all the logic modules I wrote but I'm finding it impossible. From what I understand you can't use CommonJS in browsers so the only way I could get it to work was using instead internal modules for which I need to modify the .ts files to wrap the code in module X{ } blocks and recompile them just for the GUI every time I change something. This situation seems far from ideal and I was wondering if there is a way around it...
Use http://browserify.org/ to add CommonJS-like support on the front-end.
But also read this (slightly outdated) question and answer: How should I go about writing a node.js web application with both server and client side code?
Use external modules for both the server and the browser.
When compiling for the browser, use the switch to specify the AMD module pattern:
tsc --module amd app.ts
And use RequireJS to load modules for you.
<script src="require.js" data-main="app.js"></script>
You will need to compile for the different targets, but the source code in TypeScript can be identical.
I created a demo project to share code between the client and the server : https://github.com/basarat/demo-fullstack/blob/master/src/Gruntfile.js
It compiles the common files for both amd/commonjs and server files only as commonjs with the client only files as only amd. It uses grunt-ts to manage this : https://github.com/grunt-ts/grunt-ts
I'm looking for a javascript library that attempts to provide the same simple utilities in both the browser environment AND nodejs (iteration, mapping, maybe control-flow) so that code can more easily be re-used across server and client. I know you can hack out parts of any JS library (YUI, jQuery, ...) and get them to work in both environments, I'm just wondering if it's already been done or standardized.
The closest I've seen is this: https://github.com/kof/sharedjs
But it's incomplete and has some odd stuff. I'm wondering if there is something more polished before I fork and hack.
The underscore library was built to add more functional programming to jquery, things like mapping, and also templating.
Because it doesn't rely on the DOM (it leaves that to jquery) it functions well in node.
The RightJS link library has a server build link that has node.js in mind.
From the download page:
RightJS is also available as a server-side library. In this case it contains only the native JavaScript unit extensions and the Class, Observer, Options units along with all the non-DOM utility functions from the Util module.
Our server-side build follows the CommonJS principles and is ready for use with the node.js framework.
Node's GitHub wiki has a list of CommonJS-compatible modules which will run in Node and browsers.
Some of the other modules on that page may also run in a browser environment. For example, the excellent DateJS works fine in Node. (It is available as a NPM.)
Btw, RightJS is also available on NPM