Then, from the prompt, run the following commands, in sequence, and accepting any intermediate prompts presented, to install Node.js, Nginx and curl, set-up Vagrant synced folders and start the web server.
sudo apt-get update sudo apt-get install python-software-properties python g++ make sudo add-apt-repository ppa:chris-lea/node.js sudo apt-get update sudo apt-get install nodejs sudo apt-get install nginx sudo apt-get install curl sudo mv /usr/share/nginx/www /vagrant sudo ln -fs /vagrant/www /usr/share/nginx/www sudo /usr/sbin/nginx
Once complete, execute
curl localhost at the bash prompt to verify the web server started and is sending an expected HTTP response, as shown below.
<html> <head> <title>Welcome to nginx!</title> </head> <body bgcolor="white" text="black"> <center><h1>Welcome to nginx!</h1></center> </body> </html>
If the response is successful, network the VM with Windows–the host machine–by editing the
Vagrantfile (a text file created when the VM was created), uncommenting the following line and saving the file.
# config.vm.network :forwarded_port, guest: 80, host: 8080
vagrant reload from Git Shell. (Note: Open a new Git Shell to do this, or
exit the Ubuntu bash shell first.) Doing so will restart the VM with the updated config and begin forwarding traffic to it, from port 8080 on the host machine to port 80 on the VM.
Try it out by opening a browser and navigating to localhost:8080. If the port forwarding is working properly, the page will contain a Nginx welcome message.
Pretty cool, huh? Just wait…
In case it went unnoticed, the Vagrantfile parent directory now contains a www folder. Drag that folder from Windows Explorer and drop it into an open Sublime Text window.
From Sublime, press
Ctrl+P to open the Goto Anything feature, type
ix and press
Enter to open
index.html. Look familiar? That’s because it’s the same output from the curl statement issued earlier in bash.
Make some changes and save the file, then reload the browser window and watch the changes automagically appear.
Now that is cool! Vagrant is not only port forwarding to the guest VM, it’s also syncing file systems. And with that confirmation, the configuration is complete. Time to do something interesting.
To create a modern web application, often times referred to as a Rich Internet Application, or RIA, this article will leverage an HTML5 application assembler called Brunch.io and one of the many available application skeletons called Brunch with Chaplin, which builds on Backbone and can be used to create a SPA.
It’s worth mentioning that Brunch has skeletons available for a number of other frameworks, including Ember, AngularJS and Spine. Not sure which one to pick? Check out TodoMVC for an understanding of the differences.
Back in Ubuntu (you may need to SSH in again), from the bash prompt,
cd to /vagrant/www and enter the following at the prompt to install the Brunch application assembler, create a new application using the default Brunch skeleton, install dependencies and build the app:
sudo npm install -g brunch brunch new todomvc && cd todomvc sudo npm install --no-bin-links # Skip soft links to avoid symlink errors brunch b
With the last command, a
public directory will be created with the compiled source files. And because Vagrant sync is doing its thing, the application will immediately become available within Chrome at the following location: localhost:8080/todomvc/public/index.html.
But opening the page shows nothing, and there are few errors on the page. Let’s take a look at the page source and debug in the browser.
At first when the page is pulled up, errors are preventing the content from loading. The errors can be confirmed by opening the console in Chrome using Chrome Dev Tools (
Uncaught SyntaxError: Unexpected token < vendor.js:1 Uncaught SyntaxError: Unexpected token < app.js:1 Uncaught ReferenceError: require is not defined
Debugging will show that Nginx is responding with HTML for the external CSS and JS files, instead of the expected style and script resources. Why is that? Let’s take a look at the
index.html page source and find out. It should look something like the following:
It’s a fairly vanilla HTML5 document with some conditional comments for IE, Unicode character encoding, a couple of other
meta tags, an empty
body element and three root-relative external resources.
The errors themselves are occurring because the external resources cannot be located relative to the web root and so Nginx has decided instead to return the default index.html file–the one modified earlier. There are a few ways to fix this:
Though any of these options would work, we’re going to go with configuring brunch to deploy files to the web root. And, in the process, we’re going to move the web root back to its original location outside the reach of Vagrant synced folders. (Note: Storing generated files under synced folders is not recommended, and may lead to errors in the browser after running multiple builds.)
Earlier, the web root was modified by moving the Nginx www folder to /vagrant/www and creating a symlink pointing to the new location. Remove that symlink and create a new www folder in its place, so generated application files can be deployed to a location outside of Vagrant synced folders.
sudo rm /usr/share/nginx/www && sudo mkdir /usr/share/nginx/www
To configure the Brunch app to deploy files to the new location, modify the configuration file in the application root directory, add the following paths directive, save the file, and rebuild the application with sudo privileges:
paths: public: '/usr/share/nginx/www'
cd /vagrant/www/todomvc && sudo brunch b
If done correctly, the Brunch app will now be available at the web root, or localhost:8080, free of errors and displaying an example application (as pictured below).
Before going any further, now is a good time to get acquainted with the application stack.
Once you have the sample app up-and-running, pull up the
index.html page source once more and notice the following two external scripts:
These files contain script generated via Node.js, by way of the Brunch build system. To see where their contents come from, expand the app and vendor folders under todomvc in Sublime Text as shown.
Each of the two JS files in the page source represent all of the individual script files in each of the two directories, concatenated together as specified in
config.coffee. Of the items under vendor, notice that Backbone and Underscore are included: two libraries that work well alongside jQuery (or Zepto, depending on when you read this) to produce the application structure necessary for developing modern web applications.
The stylesheets for the application are created in a similar manner, except that, unlike the script files, both the vendor and app stylesheets are combined into a single file. The behavior for CSS is determined by the following files statement in
Glance over the Brunch documentation for a better understanding of the application structure and file concatenation before making any file modifications if none of this looks familiar.
Modern web applications aren’t all dynamic. Just like the webpages developed with Dreamweaver back in the early 2000’s, RIAs are made of the same great stuff: HTML, CSS, JS and media like images.
To add some content to the document, start Sublime’s Goto Anything feature (
ix and select the
index.html file under the assets directory, as pictured, to open the file.
The contents of this file are the exact same as the corresponding file in the
public directory (now deployed to the web root). But because this file is a pre-generated, static asset, it will actually overwrite the the same file in the
public directory whenever a change is saved and the application is compiled.
Go ahead and change the
title element of
index.html, and then save the file. Then tell brunch to compile the application again using
sudo brunch b from the application root.
Once rebuilt, reload the page on the localhost and notice the page title has changed.
To summarize what happened here:
index.htmlfrom Windows with the corresponding file on the VM
And that’s just the beginning.
There’s a lot more to learn about Vagrant, Backbone, Chaplin and Brunch, not to mention the libraries they rely on and plug-ins available for them. As an exercise, consider reviewing the Brunch documentation and learn how to build the application sources with file minification enabled. Simple, right? Now try installing Bootstrap… (Hint: Take a look at how Chapless Brunch does it.) What about once Bower is used for dependency management, scaffolt generators for rapid prototyping and build processes and unit testing are streamlined with tools like Grunt, Travis-CI, PhantomJS and testem? What then. How might the application grow?
Knowing what an application framework is capable of, and how to use it properly, can easily save many hours reinventing the wheel or digging out of coding anti-patterns, and can prove to be an enjoyable learning experience. In my personal experience, difficult problems can often be simplified by expanding one’s knowledge and finding a better way to do things. And I encourage others to do the same.
This article covered a series of steps which can be used for developing modern web applications on Windows. It started with a development environment configuration using Vagrant, progressed thru the steps needed for developing modern applications, and ended with some learning exercises and personal suggestions. Developing modern web applications no longer requires a Linux box or Mac OS X. So boot up that Windows machine, go forth and code.