March 8, 2015

Twitter: @mattdesl

In this post I’ll outline a simple workflow for quick prototyping and creative development with JavaScript. It’s the workflow I’ve been using for some years now, and it is how I build most of my libraries, demos and client projects. Some examples of libraries/projects using this workflow:

The goals of this workflow:

Fast development experience – when I save my code, my browser should reload

– when I save my code, my browser should reload Minimal configuration – I don’t want to spend time with configuration each time I create a new project

– I don’t want to spend time with configuration each time I create a new project Modular – I want to be able to split my application into many files and depend on third-party libraries from npm

– I want to be able to split my application into many files and depend on third-party libraries from npm Easy Deployment – Deploying online should be simple and require no server management

– Deploying online should be simple and require no server management Modern and Extensible – The workflow should be able to easily scale up to larger projects, e.g. with modern ES2015 syntax and continuous deployment

The first step in this workflow is to install latest Node.js (which includes npm) so that you can run node and npm from your terminal:

https://nodejs.org/en/

I suggest using node 8+ and npm 5+.

Next, you need to create a folder and add a package.json file. This will define what third-party libraries our project depends on, so that we can re-install and re-run the project many years later.

In terminal, it looks like this:

# create a folder mkdir my-cool-app # go into that folder cd my-cool-app # create a package.json npm init

If you follow the steps (you can just hit enter a bunch of times and use the default values), you will get a new package.json file.

folder structure #

When creating new modules and projects, I typically lay it out like so:

my-module .gitignore LICENSE.md README.md test.js index.js demo.js package.json

Where test.js is the unit test (where possible), and demo.js is the runnable mock which will be published on gh-pages . In some cases, the module will have its own test or demo folder.

There’s a few tools out there for stubbing out module folders and package.json , like module-generator and npm init .

In order to use npm modules in the browser, we will need to use a bundler like browserify or webpack. Both are great tools and serve different needs; but in my experience browserify is better suited for maintaining many dozen small and framework-agnostic modules.

However, browserify by itself is a relatively thin and low-level tool, and does not provide a smooth developer experience. Here we will explore some tools built on browserify that aim to improve the developer experience across many modules.

An easy way to get a demo up and running is to serve your demo.js source with budo. This tool creates a local server on port 9966 , and bundles your source code on the fly. Under the hood, this is using browserify.

First, install it as a devDependency . Development dependencies are only necessary to build/configure your project, but not required directly by your source code.

npm install budo --save-dev

Once it’s installed, create a "scripts" field in your package.json that looks like this:

... "scripts": { "start": "budo demo.js" } ...

Now when you run npm run start from terminal, it will launch budo on your source demo.js file and serve a local development server. You can open http://localhost:9966/ in your browser to see your demo in action. Any require() statements in your code will be bundled by budo and browserify, so that you can work with Node.js-style modules in the browser.

live reload #

If you specify --live in your budo script, it will reload the browser page when you save your JavaScript file.

"scripts": { "start": "budo demo.js --live" }

CSS & HTML #

Eventually you will need an index.html to publish. You might also want CSS styles, HTML content, and fonts. If you have an index.html file in the base directory, budo will use that by default. For example:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>my-module</title> <link href='http://fonts.googleapis.com/css?family=Roboto+Slab' rel='stylesheet' type='text/css'> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <script src="bundle.js"></script> </body> </html>

For this to work, we will need to use entry mapping to serve bundle.js instead of demo.js . We do this by changing the entry point, like so:

"scripts": { "start": "budo demo.js:bundle.js --live" }

creating a repo #

Once you’re happy with your demo, you can publish it to a new GitHub repository.

To speed this process up, I use a command-line tool ghrepo, which you can install like so:

npm install ghrepo -g

And then, simply run the command in your directory:

ghrepo

Update Jan 2017: Nowadays I often use surge.sh for static sites, as it’s much easier than gh-pages! See here for an example.

This step is optional, but often it’s nice to deliver a runnable demo to the user so they don’t have to git clone your repo to try it out.

Make sure you have browserify installed, and uglify-js if you plan to compress the source (optional).

npm install browserify uglify-js --save-dev

Now add your final bundle task:

"scripts": { ... "build": "browserify demo.js | uglifyjs -cm > bundle.js" }

Once you’ve committed your changes to master, we can set up the gh-pages branch.

git checkout -b gh-pages

In this branch, you will need to remove bundle.js from the gitignores. When publishing new content, it will look like this:

npm run build git add . git commit -m 'updating build' git push origin gh-pages

Now if you visit your site, you should see the demo:

http://your-username.github.io/your-module/index.html

To automate this, see my ghpages shell script.

Much of this workflow has evolved from beefy and wzrd.

293 Kudos