Use "coffee" instead of "node" command in production - javascript

I have an app.js that is running express.js.
I wanna convert the code to coffeescript and thought about to create a app.coffee that I compile to app.js so I can run it with "node app.js".
But then it hit me that I could just write that file in app.coffee and run it with "coffee app.coffee".
Is this a better way? Can I run the server with "coffee" in production?

Yes you can use coffee command in production. I use it.
I can see two reasons why you would want to use app.js wrapper.
You want to use local installation of CoffeeScript. (different versions between apps)
You want to use the default npm start to launch your server :) See npm help scripts
Oh, and you don't need compile it. You can use a wrapper like this which compiles the coffee file transparently:
server.js:
require('coffee-script').register();
require("./yourcoffeeapp.coffee");
This wrapper technique is especially useful if you want to use CoffeeScript in some hosted environments that does not directly support the CoffeeScript command. Such as Cloud 9 IDE. No need to fiddle with compiled js-files.

I upvoted Epeli's answer, which is clear and excellent—using a .js "wrapper" rather than the coffee command saves you from potential path headaches—but since this is a subjective question, let me throw in a contrary opinion.
Many CoffeeScripters, myself included, recommend compiling non-trivial Node apps to JS before deployment. It's not hard—look at Sam Stephenson's node-coffee-project template, which includes a Cakefile that makes compiling and testing a breeze.
One major reason for doing this is that Node stack traces give line numbers that refer to the compiled JavaScript, not the original CoffeeScript. So when errors are recorded in your server logs, it's nice to be able to look at the corresponding code right on the server.
Another advantage to compiling to JS is that it lets you work with more tools on the server—many Node debuggers, testing frameworks, and amazing goodies like cluster like to operate directly on .js files.
Getting a good compilation setup for your project takes some work, but I think you'll find it worthwhile.

I prefer to create main.js like this:
require("coffee-script");
require('./yourcoffeeapp');
And yourcoffeeapp.coffee like this:
http = require 'http'
on_request = (req, res) =>
res.writeHead 200, {'Content-Type': 'text/plain'}
res.end "Hello World\n"
server = http.createServer on_request
server.listen 1337, "127.0.0.1"

Related

How to run a node script by CLI custom command?

Currently, I'm working on a personal project and I'd like to create an alias for some commands that I have to run... Similar to:
jest ...
node ...
tsc ...
I think that for my project would be so helpful and cool to have something like
foo ...
I'm working with Node, Typescript, and JS.
I took a look on the internet and read saw some people teaching how to create some alias I tried and it works :)
I already have the alias working on my local machine cause I added the alias on the .bashrc file.
alias foo = command...
However, I also tried to put it on my package.json scripts section, like:
"scripts": {
"runFoo": "foo",
But when I run npm run runFoo it says that "foo" is not recognized... Are any way to do that? How the tools like jest do that?
I would be thankful for any direction about what to study for that.
Extra:
There is any way to run all the .js from a folder by using any node command without knowing the name of the files?
Like:
node *.js
It can help while I don't figure out how to do the alias...
Edit:
What I want to do is:
https://developer.okta.com/blog/2019/06/18/command-line-app-with-nodejs
The answer helped me to find this post, and following it, it worked here.
it says that "foo" is not recognized
That is because shell aliases do not work in npm scripts (they are only valid when directly called in said shell), see e.g. How can I pipe to a bash alias from an npm script?
Aliases are meant to reduce typing, and are not automatically shared across environments, on the contrary of npm scripts which are committed with package.json. Hence if you try running that script in another environment, the latter may not know that alias (or worse, use it for something else!).
How the tools like jest do that?
They do not... Their command is not an alias, but an actual executable binary or script.
When installed as dependencies, you will find links to their executable in node_modules/.bin/ folder, see What is the purpose of .bin folder in node_modules?
You can easily create such executable scripts, even written in JavaScript to be executed by a Node.js engine, see e.g. Appropriate hashbang for Node.js scripts

Why use bin/www and not index.js?

The express-generator tool creates a file called bin/www and uses it as the application's main entry-point. I believe I've seen a couple of other modules do this as well, but the vast majority simply use index.js.
What is the rationale behind this? Of course I understand why you would split the server and the code for setting up the program into a separate modules, but why bin/www and not index.js? Why nest the main-entry point to a program two levels deeper than the stuff it calls? And remove the file-extension, making it even less descriptive?
Is there a clever, non-obvious reason behind this? Should I use this for my node-modules as well?
Thank you!
[edit]:
All good answers, thank you folks! I've accepted the one pointing out that this is standard behaviour for packages that include executables. Here's some more reading I've come across on this:
https://docs.npmjs.com/files/package.json#bin
https://blog.npmjs.org/post/118810260230/building-a-simple-command-line-tool-with-npm
You're used to running npm run, but not sysadmin. He will look for executables (attribute x) in thebin directory.
The entry point index.js is for node module. All packages that provide commands to run on the console contain the bin directory.
The extension is removed because it is not a script, but as a program. And these do not have extensions.
express-generator create a basic structure for an express application. By convention, the entry point of the app is index.js or app.js. In fact, express-generator create an app.js at the root of the application with the initial setup of express.
Also by convention, the bin/ directory is used for binary files, and by extension for the scripts you can directly launch (note the shebang at the first line of www file). This is common on Linux that binary file has no extension and it could explain the choice to keep this habit for this file.
www, by convention again, is used for naming web application (like /var/www/html in Apache server)
Anyway, as the documentation says,
The app structure created by the generator is just one of many ways to
structure Express apps. Feel free to use this structure or modify it
to best suit your needs.
See also this answer who talk about the core structure of express between version 3 & 4, with the removing of external module.

Quick way to write JavaScript that requires babel and run it?

I want to write a JavaScript example and run it to see how something works.
The sample code might require a browser but not always. I'm open to two solutions, one that works with NodeJS, and one that is used for browser based code. In browser, I'm using React with class and other ES6 syntax including import/export which is not (yet) supported directly by node or node --harmony.
In Python, Java/Groovy, C/C++, C#, others, I could just run a command to compile the file and then run the executable (or just interpret the code), so I'm looking for something similar for JavaScript.
Conceptually, I would like to say:
dotranspile --out bundle.js main.js
node bundle.js (or firefox index.html, which loads bundle.js)
The key is that I don't want to have to create a webpack configuration file in every directory. I thought I found a command like this when searching one day, but can't find it now.
How do other people run javascript sample programs when babel/transpiling is required? I would also like to be able to save them for future reference (in some cases).
Currently, each time I want to write a test I create a directory with a webpack.config file, package.json, and use npm install, and npm run to run the code or start a NodeJS express server to serve index.html.
This seems to be a lot of overhead for a quick test, and it results in dozens of node_module directories with tons of files in them.
Maybe is not answer that you want, but you can always use jsfiddle with babel + jsx. I think that jsfiddle is very good tool for quick run simple app in babel/jsx or other libs, transpilers etc.

How to automatically compile client side CoffeeScript files with Node.js / Express

As the title says I'm trying to automatically compile the public static coffeescript files on page load, rather than having to compile them myself and use the .js files, how might I achieve this, I'm trying to maintain a full CoffeeScript stack, this is the only thing I'm having trouble figuring out.
tl;dr: Read the title of the post.
There are a number of ways to accomplish what you're trying to do. Two of the easiest that I know of:
Use the connect-assets module. The idea behind this is that you have an /assets folder in the root, and you instantiate it with express.static, as you normally would with your /public folder. In there, you have two more folders: /js and /css. Your CoffeeScript goes in your /js folder. Then, from within your view template, just call js('yourfile'). It's a wonderfully simple module, but isn't the most advocated asset pipeline.
Use asset-rack. While not as simple to grasp as connect-assets, it's very flexible and is easy to extend. It would be the closest comparator to Rails' asset pipeline and is used by most of the popular JS frameworks (like Sails.js).
However, I would really advise that you refrain from on-the-fly compilation of assets, as it can really drain server performance.
It would be way better to compile on file save using a build system - CoffeeScript ships with Cake, so you can define a watch/compile/build/concatenate step right in your Cakefile and all it would take for you to compile on file save is to type $ cake watch in to the terminal before you change any code.
Alternatively you could write code, then $ cake build. Whichever you prefer. I might also add that cake-flour takes all of the pain out of writing Cake tasks.
coffee --watch --compile .
watches for files changes in . and compiles them as they change. Since you are using expressjs I think you would also like to restart the server as soon as a recompile happens:
coffee --compile --watch . &; nodemon server.js
which uses https://github.com/remy/nodemon
If you only want to have access to compiled CoffeeScript files over HTTP, you could also give connect-coffee-script middleware a try. It has worked quite well for me.
It has the advantage over using coffee --watch --compile that you don't need to have a separate program running.

How can I use a javascript library on the server side of a NodeJS app when it was designed to run on the client?

I'm diving into NodeJS and Express (it's sooo complicated to me) to build a real-time web app. At the moment, I'm trying to understand how I can use an existing javascript library on the server side. The problem is the library appears to be designed to run on the client side and, as a result, the instructions only show you how to use it on the client side. The library I'm talking about can be found here...
https://github.com/replit/jsrepl
Questions:
Since a NodeJS web app is built on javascript, is it fair to say I can run any non-gui javascript library on the server side?
Can anyone offer some guidance on how I can add that jsrepl library to my Express 3.0 app in a way that allows me to use it in the same way that I would use it on the client side in a browser? Do I have to modify the jsrepl code and add "exports." to the methods I want to use?
Meaning, on the server side, I can execute the following code...
var jsrepl = new JSREPL({
input: inputCallback,
output: outputCallback,
result: resultCallback,
error: errorCallback,
progress: progressCallback,
timeout: {
time: 30000,
callback: timeoutCallback
}
});
Thanks in advance for all your wisdom! I'm doing my best to understand all this.
So this is possible, but you need some serious hackery in order to get it working. Since this is not a node module and is written from the browser as others have noted, you need a DOM within node to execute it into. Luckily, we have the wonderful jsdom project which allows us to do just that. So let's get this thing set up.
cd into your node project (create one if there isn't one already)
clone down the jsrepl repo git clone git://github.com/replit/jsrepl.git
cd into jsrepl and initialize submodules git submodule update --init --recursive
still in the folder, run npm install coffee-script and npm install uglify-js, dependencies that are not mentioned anywhere in the repo (ugh).
make sure java is installed and run cake bake. After a lengthy process of compiling java files and such the command will finish and jsrepl will be built and ready to go.
run npm install jsdom, then we can start writing an example file
Here's a minimal example:
var jsdom = require('jsdom'),
fs = require('fs'),
jsrepl = fs.readFileSync('./jsrepl/repl.js', 'utf8');
jsdom.env({
html: "<script src='jsrepl.js' id='jsrepl-script'></script> ",
src: [jsrepl],
done: function(err, window){
if (err) return console.error(err);
run_jsrepl.call(window);
}
});
function run_jsrepl(){
console.log(this.JSREPL)
}
Here's the minimum amount of code required to get JSREPL into a place where it's working. All we're doing here is requiring jsdom and instantiating it, reading in the jsrepl source straight from the file. If you run this file with node filename it will log out your JSREPL object, which can be used just like it's in the browser : )
You can run phantomjs in Node, which is a headless webkit browser. Then run jsrepl inside of phantomjs.
No. There are things on the client side that you don't have on the server side (and vice-versa): for instance, the DOM.
I've never worked with jsrepl myself, but assuming that it's platform-agnostic, require()ing it from a node module should be OK. However, there seem to be some DOM-specific things in the scripts in question (e.g. document.getElementById) that suggest otherwise.

Categories

Resources