Adventures in the front-end wonderlandwebdevangularjs
Hello, I am a back-end engineer and happily shuffle the bits in the server side. In the last couple weeks, I’ve been wearing the front-end engineer hat and I’d like to share my experience and rants.
- The state transition is seamless, no more redirect or reload.
- The back-end is less stateful, easier to scale.
- The API may also be consumed by the mobile app, a true “mobile first” paradigm.
- Timing. The personal computing power and network performance have significantly improved over the last two decades. It is feasible to shift the complex logic to the front-end.
- The deployment and upgrade process are much smoother for the end-users and IT department.
Down the Rabbit Hole
The cool kids in the block are using the trio, yeoman, bower, and grunt:
bower install angularjs bootstrap font-awesome --save
The assets and their dependencies are pulled and copied into local
bower_components folder for later use. With
--save option, the meta data is
bower.json for bookkeeping.
The real magic comes from grunt:
grunt-bower-installplugin, the bower dependencies are automatically injected into the html page.
grunt-asset-injectorplugin, the individual assets are bundled to minify the HTTP requests.
grunt-rev, the minified assets are revisioned to be cache-friendly.
grunt-contrib-watch, you modification will be trigger the build action and reload the server.
gulp-swig, the static marketing pages are rendered from the template.
Yeoman is a scaffolding tool to glue them together. There are hundreds generators to bootstrap a project. I can get a working MEAN(MongoDB, ExpressJS, AngularJS, NodeJS) stack in less than 5 minutes thanks to the trio.
There are some other technical decisions you have to make, here are mine with some notes:
- CSS Framework: Bootstrap.
- Template engine: swig. Both swig and jade support template inheritance, I prefer swig as it looks similar to Jinja2.
I believe the best way to learn a new thing is to just get your hands dirty. The web application I’ve been working on is a tiny but full-fledged Software-as-a-Service:
- It has a home landing page with all the marketing bells and whistles. They are plain old static html pages for the SEO juice.
- The AngularJS application requires the authentication, provided by the 3rd party via OAuth.
- The data is provided by another service, which is temporarily out of the scope. I will use some canned content for the development.
This seems a reasonable and realistic project, isn’t it? But the problems I encountered slowed down the progress so much that I would have been fired if I were paid to do so. Here are some lessons I have learned:
Less is more
The first mistake I have made is taking a bigger bite than I can digest. I bootstrapped the project via angular-fullstack with all the shining add-ons, then tried to trim it down to fit my needs. It didn’t work very well due to the lack of knowledge of the conventions of the grunt plugins. I ended up switching to gulp.js for its explicit pipeline approach, and bootstrapped the project with minimum boilerplate code, then add component gradually. I think this approach make the project more manageable.
We all know the DRY(Don’t Repeat Yourself) principle, but sometimes we just have
to bend for the reality. For example, the server views and the home landing page
could share the common boilerplate template, but it is tedious to configure the
search path for
gulp-useref plugin correctly. I eventually separated the two
base templates for each use.
Always use absolute path
The front-end engineers tend to use the relative path to reference the assets, so the html page can be opened locally without a web server. It is OK if you are building an one page application without backend; otherwise explicit is always better than implicit If you use Mac, you might checkout the cool Anvil app.
The back-end is almost inevitable
The back-end is almost inevitable unless you stick to the old school username/passport approach which can be done in purely asynchronous fashion:
- The web application is loaded from the web server
- The authentication is issued in the AJAX POST request to the Auth server
- The Auth server verify the password, and sign the meta data with JSON Web Token.
- The web application then save the token in the browser session and talk to the API server.
If you use OAuth, the authentication is initiated in the server side and finished with the server side callback. The back-end then set cookie or render a page with signed JWT; and the client continue with step 4 as specified above.
Be aware of template conflict
There may coexist three templates in your web application:
- the server side template, swig in my case
- the angular template
- the legacy mustache template
They all pretty much look the same! If the client side template goes through the server render pipeline mistakenly, you may see weird rendering bug in the client side. My suggestion are:
- use a dedicated web server, such as nginx to server the static content in the production.
- use a restrictive glob pattern in you gulp.js or Gruntfile.js to avoid such mistake.
This post is more about the tools and build system, it barely scratches the surface of the front-end engineering. I struggled for the best practice for several nights to understand what I have in the toolbox and I hope it is valuable to you as well.