u2i

Prologue

How do we usually create a web application? We run a bootstrapping script, which provides us with a skeleton of our application and then we just extend it with the features we need. That’s exactly what we did at the last hackathon we were attending – we started with rails new twf and spent half of the day integrating our blank app with Angular, Paperclip, creating API methods and so on. But the effort we needed to accomplish our goal (quite a simple web app) was really huge. So I decided to find the best combination of backend and frontend technologies that would cause less pain. At the project I was recently introduced to, the line between frontend and backend is distinguished very clearly: we have an API, written in Clojure and thin frontend application, made with Angular that works on a generated set of static assets – HTMLs, CSS and JS files (but under the hood we are using HAML and SCSS). The application I will be implementing throughout the whole article has the same architecture: it has RESTful API and MVVM on the frontend, made with Angular. I welcome you to the journey of research and new technologies!

Why not go with Rails?

Because Rails is often over-used. Especially if you install all the front-end libraries (like Angular, Bootstrap, some Angular plugins, etc.) as RubyGems. Front-end should stay on the front end of the application; you should not lock your application at some precise version of the JS script, provided by a gem and rely on the author’s way of  integrating it with Rails.

In our case, Rails is too heavy – when all you need is database + routing + a couple of lightweight controllers, all Rails’ features will become ballast for our app, which needs to be small, by design.

The goal

Before we start, let’s think of what we will be creating. Will it be a web shop? Or a blog? No, we need something outstanding! Something we’ve done never before…

After an hour of imaging what it might be, I decided to go with a web analytics tool. A prototype, which will be able to tell how many visitors your web application has gained recently.

It shouldn’t be too complicated, because, you know, it’s just a tutorial… So we will be tracking our users’ location and browser only. And we will be showing statistics on a chart (values like total visitors, browser usage) and in a table (the same info as on the chart).

General architecture

We will be developing our application with two layers (or two sides) – front-end and back-end:

Two sides of web application

The front-end part is the one the user sees and uses – the web page, mobile or desktop application. The back-end part is the one, which does all the magic – prepares data for the front-end side to display, performs data operations as a reaction on user’s actions, etc. Thus we could easily replace either the back-end part or the front-end one or even both and replace them with all brand-new implementation. This architecture allows us to do that really easily.

The first thing we need to think about is how we will be gathering information about the users. It’s quite easy – we just need to get a request of some sort from a visitor of some sort. Of any kind – it may be a request for an image, a file, a stylesheet or a script.

Then we will just parse the headers from that request and save the extracted data in the database. The only problem here is: how to get unique key from each request? We can use the visitor’s IP address. That’s the easiest way.

Now, let’s decide what pages our application will have and what they will look like:

Build with the right tools!

Now, since we separated the frontend part of application from the backend part, we can use different preprocessing languages to write stylesheets and views. And even controllers! So let’s take most from 2015 and use the newest tool set: Jade, ES6+ and SCSS. And put them all together with Bower and Gulp.

None of Jade, SCSS and ES6 are supported by a browser out-of-the box. They must be compiled to HTML, CSS and JS in order to be recognized by the browser. But they are here to help you write code quickly. I listed some of their key features below.

Jade

Jade is a template rendering engine with its own markup language. It is somewhat similar to Haml and Slim – it nests XHTML nodes with indentation, closes tags automatically… But it is especially good at writing complex web pages, consisting of layouts and partials.

Layouts are big templates, containing placeholders, where concrete partials will be placed. So, for example, you can create a separate layout for your web shop’s landing page, account page and shopping cart. They will be different. And all of them will use different sets of partials. But, for example, a footer and a quick shopping cart preview or user account widget (the one with a link to user’s account page) will be the same. To prevent duplicating those widgets’ code on each of the layouts, we extract them to separate files, called partials and then just make a reference (a placeholder) in our layouts, saying “place that partial’s content here”.

In the case of Jade, we can override or extend the existing partials in a layout, without touching the partial’s file itself. So, for example, if we want to a user’s avatar to be shown in the user account widget only on the product page, we just override the user widget partial on the product page, removing the part with the avatar.

SCSS

SCSS is a way to simplify writing CSS. It is so simple, yet so powerful, that you will fall in love with it after the first few stylesheets! See, in CSS when you write a long selector, specifying many parents, you may find your stylesheets ugly and huge, when describing different children of one, deeply nested parent.

So, let’s say you have a user widget. And it can be placed both on the page’s header, footer and sidebar. But the avatar image will look differently on each of those – it must be smaller in the header and footer. So you start writing selectors like .sidebar .user-widget .avatar img and .header .user-widget .avatar img. That’s painful, but not that painful, as long as you have just a couple of them. However, as your website grows, you will start getting really, really upset about it.

And here’s where SCSS is such a revelation: its great power is in its selectors, variables and mixins.

Selectors allow you to describe selector’ nesting just as if you were writing C code:

Variables allow you to get rid of all those magic values. So if you use one color many times across your styles, you just extract it into a named constant and use the pretty named value everywhere!

Mixins allow even more: you may extract the parts of the styles into a named and even parametrized function!

Related to all of those things, you may re-write your user widget as follows:

Gulp

I found Gulp to be super-easy for tasks like compiling stylesheets, views and javascripts. But before we continue with Gulp, let’s initialize an NPM project with npm init and install the plugins required:


And Gulp plugins:


I will describe how Gulp works and how we can use it in our project in a minute. For now, let’s just install the frontend dependencies.

Bower

Let’s fix our frontend to specific versions of frontend libraries, so when we update the whole project, nothing gets broken. To make our development quick, we’ll use Twitter Bootstrap. All the frontend dependencies will be managed by a tool called Bower.

Bower is a tool like npm, but used strictly with frontend libraries like jQuery, Angular, Twitter Bootstrap and many others. It’s important to keep frontend libraries separate from the backend ones, so we can keep our backend application completely separate from frontend one.

Bower comes with a command-line tool, bower, which we will use to fill out the bower.json file. It is used by Bower to specify which libraries our application requires:


These commands create a directory bower_components, containing all the dependencies installed, each in its own sub-directory. With that in mind, we will be referencing our front-end dependencies, relatively to their catalogs within the bower_components directory.

Now let’s write a build task for Gulp. Gulp is a streamed build tool. This means that each operation you perform passes its result to another operation as the input argument. So, for example, if you run gulp.src('src/styles/*.scss'), it will return an object with a list of all the SCSS files and the magic pipe() method. And when you call the gulp.src(...).pipe(scss()), Gulp will pass that list to the SCSS compiler plugin, so you will get a compiled CSS code. That is, not a CSS file itself, but compressed, merged, CSS file’ content.

And that describes the second important feature of Gulp: it does not store the intermediate operation results. It is almost like functional programming – you just have the input data. Then you call a chain of functions on it, passing the result of one function call to the next function as its input. Same happens here, but not in such a strict manner – since we are using Javascript, we can store the intermediate results in memory. But to store the results in the files, we should pass them to the gulp.dest(...) function. Depending on the function looking to store its results, gulp.dest() may point to a directory or a single file where the results will be stored.

Below is our first Gulp task. Write this code in the gulpfile.js:

This tells Gulp to define a build task, which compiles all the Jade, SCSS and ES6+ files into HTML, CSS and JS files, respectively. The compiled files are placed within the public/ directory, so we can easily render them with almost any web-server. But first things first, we need to prepare a directory structure like this for our task:

This may seem odd in a paragraph dedicated to build tools, but let’s check how our tasks work. To do this, we need to write some test files to check our build task. So let’s create one of each kind:

src/views/index.jade:

src/stylesheets/main.scss:

src/javascripts/main.js:

 

Full code of these steps

And to actually check our task, we need to run it with:


Now, you can open the HTML generated from Jade in a browser, but it will look ugly, because it is doubtful that your browser will find the stylesheets and javascripts that easily. To make the magic happen, we will use another Gulp plugin, gulp-server-livereload. Generally, the development process with different build tools looks very similar nowadays: you set up the environment, find the plugins you need, install them and configure them – and voilà!

I’ve chosen that server plugin because it comes with one handy feature: it automatically reloads the opened pages in your web-browser if any of the files you are browsing has changed. Here’s the code for our serving task:

But as you remember, we are compiling our sources from SCSS/Jade into the public/ directory. So how would the server know if anything changed in our *.scss or *.jade files? We need to reload the page in a web-browser if anything changes in those files. To do that, we will write one more task, which will re-build our source files if anything changes:

Here we used two new features of Gulp: watching for file changes and running existing tasks from another task. Simple? Yeah, that simple! So we just tell Gulp: keep an eye on those files – if anything happens – run those tasks immediately! – and the magic happens.

But why should we run two tasks? Let’s merge them into one so we just run gulp serve and get both live reload and live re-compilation:

This task first defines a watcher for our sources and then starts server, which will react to any changes in the public/ directory. To check how this awesomeness works, start gulp serve, open the localhost:3000/test.html page and then change, for example, color for the h1 tag to green. Save the SCSS file and just switch to the browser window, do not reload it manually.

Full code of these steps