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

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.

Related

Using npm with vanilla js

Due to the governance constraints on my day-job project, I'm unable to use a lot of the nice new JS libraries and frameworks. So, for the MVP we're using vanilla JS loaded directly (non-minified) to the client (gross). While this is a great way to show management that's not the best approach, I still have to get it out of the door. However, we do have NPM and Node installed on our dev machines, and I'd like to use this to optimize our JS into a combined bundle, with a hash to break caching.
My question is how do I go about gathering a bunch of disjoint JS files and adding them to a new NPM project to be minified while avoiding having the expected variables, objects, and functions being mangled by webpack/prettify?
I tried just copying the js files into the src directory, and adding the normal import/export lines, but I was getting a bunch of "identifier not found" messages in the console, so I think a lot of stuff was getting mangled.
I have some experience using create-react-app for React side projects, but unfortunately that insulates me from the pain of getting a project setup the hard way, and now I'm paying for my inexperience.
EDIT: To be more succinct, I'm trying to package a bunch of existing js files into a single bundle, while maintaining the same interface. If this isn't possible, please let me know. Otherwise, a place to start would be ideal.
In the days before browserify, babel, webpack, grunt, gulp... we would just concatenate the files and minify them. Since the files expose their API as global objects everything keeps working as if the files where included with different script tags.
On Linux you can simply do this
cat a.js b.js c.js | uglifyjs -cm > bundle.js
The files would often start with a semicolon to make sure nothing breaks when concatenating them.
Once babel is configured integration is as easy as
cat a.js b.js c.js | babel | uglifyjs -cm > bundle.js
https://babeljs.io/docs/usage/cli/

CoffeeScript appending code to single .js file

I would like to append new .coffee files to a single .js file.
Right now my project structure is
coffee /
--controllers /
----Ajax.coffee
--views /
----Login.coffee
--app.coffee
The file app.coffee was created first, but when I created Ajax.coffee the code got prepended to the app.js file, because it is higher in the structure. Is there a way to append the code instead? I really want to use a compile-to-single file rather than loading loads of files with requires, but the code prepending makes it a pain in the ass.
I am using PHPStorm and it's watchers.
You can use grunt as a build tool to structure a project like yours. Grunt can be configured to watch, compile, minify, uglify, test and even run your code automatically on change. The initial learning curve might be a bit steep, but you will never look back.
http://gruntjs.com/
You should give 'cake' a shot. It is a comprehensive build system for coffee.
You can create build tasks that do different things, for instance, a build:dev task that leaves comments in the generated JS and a build:release task that minifies, removes comments etc from the generated JS.
Here's the official documentation

Bundler for javascript, or how to source control external javascript files

I am in the process of converting an existing Rails 3.1 app I made for a client into a Backbone.js app with the Rails app only as a backend server extension. This is only a personal project of mine, to learn more about Backbone.js.
While setting up Backbone.js (using Backbone-on-Rails), I noticed I have some dependencies (like backbone-forms) that come from external sources and are frequently updated.
I've grown accustomed to using Bundler to manage my Ruby gems, but I haven't found anything similar for JavaScript files. I'm wondering if there is any way to do the same for Javascript (and possibly css) files.
Basically I can see three possibilities to solve this issue:
Simply write down all the sources for each JS file and check these sources from time to time to see what has changed.
Use some kind of existing "Bundler for Javascript" type of tool, I've been looking for something like this but have yet to find anything (good).
Since most of these JS files will be coming from Git anyway, use Git to get the files directly and use checkout to get the latest version from time to time.
I prefer the last option, but was hoping on some more input from other people who have gone this route or preferred some other way to tackle this issue (or is this even an issue?).
I figure the Git way seems easy, but I am not quite sure yet how I could make this work nicely with Rails 3.1 and Sprockets. I guess I'd try to checkout a single file using Git and have it be cloned in a directory that is accessible to Sprockets, but I haven't tried this yet.
Any thoughts?
You don't mention it in your alternatives, but ideally you should use something like Maven to manage your dependencies. Unfortunately, there are no public repositories for javascript files. This discussion lists some other options which might be of help to you: JQuery Availability on Maven Repositories
For now I've settled on using the Git solution combined with some guard-shell magic.
The steps I follow:
Create a dependencies directory somewhere on your local drive
Clone the repositories with javascript (or css) files you want to use in the app
Set up a custom guard-shell command to do the following:
group 'dependencies' do
guard 'shell' do
dependencies = '~/path/to/dependencies/'
watch(%r{backbone-forms/src/(backbone\-forms\.js)}) {|m| `cp #{dependencies + m[0]} vendor/assets/javascripts/#{m[1]}` }
end
end
Place the Guardfile at the root of the app directory
It takes some time to set things up, but after that, when you have the Guard running, and you pull changes into your dependencies, the required files are automatically copied to your application directory, which are then part of your repository.
It seems to work great, you need to do some work for each new file you want to include in the asset pipeline, but all that is required is cloning the repository in your dependencies directory and adding a single line to your Guardfile, for example for the backbone-form css:
watch(%r{backbone-forms/src/(backbone\-forms\.css)}) {|m| `cp #{dependencies + m[0]} vendor/assets/stylesheets/#{m[1]}` }
Also, the reason I added this Guard to a group is because I keep my dependencies outside the main application directory, which means guard normally doesn't check my dependencies directory. To make this work, I start up my main Guard processes using bundle exec guard -g main and use bundle exec guard -w ~/path/to/dependencies -g dependencies in a new terminal window/tab to specify the -w(atchdir).

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

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"

How can I convert a multi-file node.js app to a single file?

If I have a node.js application that is filled with many require statements, how can I compile this into a single .js file? I'd have to manually resolve the require statements and ensure that the classes are loaded in the correct order. Is there some tool that does this?
Let me clarify.
The code that is being run on node.js is not node specific. The only thing I'm doing that doesn't have a direct browser equivalent is using require, which is why I'm asking. It is not using any of the node libraries.
You can use webpack with target: 'node', it will inline all required modules and export everything as a single, standalone, one file, nodejs module
https://webpack.js.org/configuration/target/#root
2021 edit: There are now other solutions you could investigate, examples.
Namely:
https://esbuild.github.io
https://github.com/huozhi/bunchee
Try below:
npm i -g #vercel/ncc
ncc build app.ts -o dist
see detail here https://stackoverflow.com/a/65317389/1979406
If you want to send common code to the browser I would personally recommend something like brequire or requireJS which can "compile" your nodeJS source into asynchronously loading code whilst maintaining the order.
For an actual compiler into a single file you might get away with one for requireJS but I would not trust it with large projects with high complexity and edge-cases.
It shouldn't be too hard to write a file like package.json that npm uses to state in which order the files should occur in your packaging. This way it's your responsibility to make sure everything is compacted in the correct order, you can then write a simplistic node application to reads your package.json file and uses file IO to create your compiled script.
Automatically generating the order in which files should be packaged requires building up a dependency tree and doing lots of file parsing. It should be possible but it will probably crash on circular dependencies. I don't know of any libraries out there to do this for you.
Do NOT use requireJS if you value your sanity. I've seen it used in a largish project and it was an absolute disaster ... maybe the worst technical choice made at that company. RequireJS is designed to run in-browser and to asynchronously and recursively load JS dependencies. That is a TERRIBLE idea. Browsers suck at loading lots and lots of little files over the network; every single doc on web performance will tell you this. So you'll very very quickly end up needing a solution to smash your JS files together ... at which point, what's the point of having an in-browser dependency resolution mechanism? And even though your production site will be smashed into a single JS file, with requireJS, your code must constantly assume that any dependency might or might not be loaded yet; in a complex project, this leads to thousands of async load barriers wrapping every interaction point between modules. At my last company, we had some places where the closure stack was 12+ levels deep. All that "if loaded yet" logic makes your code more complex and harder to work with. It also bloats the code increasing the number of bytes sent to the client. Plus, the client has to load the requireJS library itself, which burns another 14.4k. The size alone should tell you something about the level of feature creep in the requireJS project. For comparison, the entire underscore.js toolkit is only 4k.
What you want is a compile-time step for smashing JS together, not a heavyweight framework that will run in the browser....
You should check out https://github.com/substack/node-browserify
Browserify does exactly what you are asking for .... combines multiple NPM modules into a single JS file for distribution to the browser. The consolidated code is functionally identical to the original code, and the overhead is low (approx 4k + 140 bytes per additional file, including the "require('file')" line). If you are picky, you can cut out most of that 4k, which provides wrappers to emulate common node.js globals in the browser (eg "process.nextTick()").

Categories

Resources