nodemon (restart the server automatically when your backend scripts change) + node-inspector (debug Node apps from Chrome Dev Tools)(yes, it's as awesome as it sounds) + concurrent (start multiple servers from a single Grunt task) is also a slice of heaven for Node developers, but I don't seem them mentioned often.
One thing I learned recently was that dependencies can be locked with npm shrinkwrap [1]. In the event that you don't want a deployment to be impacted by a newer version of a dependency.
npm-shrinkwrap covers one of the main strengths of checking code into source control, without actually needing to check in to version control. It locks versions down for your direct dependencies AND their dependencies, same as checking into your own repo would.
Does it protect against the hosting site going down and the project disappearing from the web? That's the main concern people have when they check library dependencies into source control.
Nope, but hosting an NPM mirror does do that, or mirroring the packages that you use in your projects if you want to skip the full mirror. So you can combine that + shrinkwrapping to get the same benefits.
Is using git submodules also frowned upon? (I'm aware that gitmodules UI is horrible but let's pretend it wasn't)
It seems natural to me to handle "lock in precise deps" on the version control level. Of course there is value in tools like npm & bower intelligently resolving deps with "soft lock in" like "~1.2.3" but it makes sense to me that I'd have to commit the resulting precise versions as a new submodules state.
- I now discovered "npm submodule" command but once checked out "npm will stubbornly refuse to update" them. Why?
- I tried to google for bower submodules and nobody seems to even voice the idea, although bower is more git-centric.
What am I missing?
P.S. I should admit that I'm biased by not wanting to give up the convenience of Github Pages for pure html/js (without any build/minify steps) — Pages supports submodules (one level deep) so I can just push. I should graduate to Heroku which can do arbitrary build on push I guess...
Still, there will always be reasons why some people DO check in deps and advise others to do so. Why not natively support submodules as the less harmful way to do that?
Using grunt watch for things like automatically linting my files, and running unit tests based on what source / test files are changing was a revolutionary jump for me and my development with Node. Having a near-0 feedback loop to indicate your impact to code quality and tests is priceless!
Grunt also makes it super simple to do add tasks which are wrappers for things like Vagrant etc. For example, you can bootstrap a vagrant vm with a mongo service provisioned inside the VM and have that auto-deploy before you start you development workflow.
For those who are interested (in filing bugs, seeking inspiration, providing feedback), feel free to check out my NodeJS starter project here: https://github.com/sabhiram/nodejs-scaffolding
One thing I absolutely disagree with is keeping the dependencies out of source control. I have always argued that the best way to ensure that the code running in your dev environment is the same code that makes it to production is to check in node_modules to source control.
In addition this also eliminates the possibility of you being unable to deploy your application because npm decides to make a breaking change without bothering to inform anybody, or if npm goes down for any reason.
I find this over reliance on npm in the node community a bit discomfiting. npm is a package manager and an excellent one at that. But using it for everything from running tests to application deployment is not a very good idea.
As someone new to Node I appreciated this list of tips. The article also led me to some great additional resources that I'll be looking at tonight including Browserify. Time for a serious upgrade to my front-end app development workflow. Thanks!
Good article. I think one area where it could be improved slightly is to specify which type of use case the recommendation is appropriate for:
1. Node as a scripting language
2. Node + Express or Hapi or whatever as a web development framework
The recommendations in this article work well if you're targeting Node as a scripting language.
However, if you are developing using a web framework, then some of the recommendations are too lean (IMO).
1. npm init
When I'm developing for the web, I use a more robust application skeleton. There are a ton to choose from. However, I do use npm init when developing scripts. My guess is the author's point is something like, "good Node devs include a package.json".
2. Declare all dependencies
Absolutely. Works for both web and scripts.
3. Specify a start script
Yes, for scripts.
However for the web task runners such as Grunt / Gulp / etc. work better. For web dev starting the server is just one task of many. For example, if you need to start the server after checking the environment, watch for file changes, run jslint/jshint, and so on then a task runner makes web development easier.
4. Specify a test script
Yes!
5. Keep dependencies out of source control
Yes, but use npm-shrinkwrap because the code you deploy (your code + deps) should be the exact same code that you ran during testing.
6. Use environment variables to configure npm
Absolutely. Config files are another option, but this is a matter of personal preference. The authors point is totally valid.
7. Bring your own npm registry
This is an interesting one and one where there is no clear "best choice" yet. It'll be interesting to see how npm (public and private) evolve.
8. Keep track of outdated dependencies
Yup
9. Use npm scripts to run custom build steps
This is now being debated. There are some in the community who specifically prevent pre/post scripts from running automatically when installing via npm.
10. Try new things
Debatable (at this time). These new features can also go onto the todo list in the near future. If someone is new to node, they may be better served by focusing on what node / JS does now.
11. Browserify
Depends. If you're using Angular, then it has its own module system. I think Ember has its own module system as well.
require.js is another option. But the author's point about having client-side modules is totally valid.
I have question as someone that is still fairly new to node. The article recommends using npm for running tasks (for instance starting the application), but others recommend an external tool like grunt. Is it more idiomatic to use grunt or npm for these tasks?
Personally, I think using NPM is more idiomatic; Both Grunt and NPM are third-party tools, however NPM is FAR more pervasive with Node than grunt is. Essentially, if you write Node, you use NPM. Not so with grunt.
To be honest, I didn't realize that npm could be used as a task runner, but now that I do, I'm wondering what all the fuss about Grunt is. Why bring in yet another meta-tool into the chain if npm (which is basically a requirement) can handle task execution already?
I'm not entirely sure about this, but it seemed like Grunt was more for front-end developers that haven't quite jumped into Node.js yet (or had no intention to).
I've noticed some culture differences between front-end and back-end javascripters.
> it seemed like Grunt was more for front-end developers
Grunt is a task runner. It's a general purpose utility, that happens to work well with JavaScript (client and server).
Our team first started using Grunt to concat Scala templates prior to compilation (in an old version of Play with an old JVM). Back then, we noticed that concatenating the Scala files reduced the amount of heap used during compilation. Never did figure out why.
Later, we started to use Grunt to minify and concat our Backbone code.
Currently, we use Grunt for both our server-side Node and client-side Angular.
Server-side we use Grunt to: 1.) Restart Node on file change, 2.) Run JSHint against both server-side and client-side JavaScript, 3.) Set some environment vars prior to starting Node, plus a few other small tasks.
Client-side we use Grunt to: 1.) Create a production build by minifying and concatenating JS, 2.) Minifying and concatenating CSS, Minifying HTML, plus some other minor tasks.
We also use Grunt to run the client and server test suite.
Basically, it's common practice to use Grunt (or Gulp, or another task runner) to assist with both client and server-side JS.
Another way to think about it is if you were to deliver the application to someone else. They shouldn't need Grunt to run your app. Providing an easy way to run the app with npm start is nice to have. Maybe add the npm install part to the process so they can just run one command to do two things. Going further you could set environment variables so production and development variables can be enabled easily. Just like you I'm still fairly new to the node way of doing things and just do whatever makes sense to me.
I haven't used npm tasks yet, so take this with a grain of salt. Grunt has two main advantages: a rich plugin ecosystem, with easy-to-configure/use tasks for pretty much anything I can think of (preprocessing, concatenating, minifying, linting, live reloading etc.) and a standardized "language" to configure Grunt plugins (third party or your custom tasks).
Once you familiarize yourself with the Grunt way of setting up tasks, it becomes trivially simple to obtain and run plugins for your tasks.
Exactly! I actually have grunt tasks pointing to npm "scripts" to run. Here is a sample Gruntfile that does the following:
1. Runs unit tests any time source or test files change
2. Runs JsHint on the source any time it changes
3. Generates a static documentation site based on any edits I make to my markdown files
4. Brings up, tears down vagrant VMs which host a MongoDB (or whatever) instance
This makes development workflow really awesome. Just do "grunt watch" in a terminal, and you will always be able to see your tests go from fail to pass as you develop your (linty clean) code.
I have seen many others use (and mention the use of) Grunt to reboot the server on file change, this is one of those programing austerities I have not given up (yet).
[1]: https://www.npmjs.org/package/grunt-nodemon
[2]: https://www.npmjs.org/package/node-inspector
[3]: https://www.npmjs.org/package/grunt-concurrent
Edit: here is an example configuration: https://github.com/ChrisWren/grunt-nodemon#advanced-usage