AngularJS / ES6 / Webpack
I first started using ES6 and Webpack a few months ago whilst working with React on Soapee and ever since I’ve been finding myself missing using ES6 and Webpack when writing code for Node.js and AngularJS.
This posts presents my research on existing ES6/AngularJS seed projects and my own attempts of using ES6 and Webpack on an AngularJS single page application.
Googling for angular webpack yields several resources and blog posts that document experiments with Webpack and AngularJS. Notable resources include:
Kent Dodds put together an interesting series of videos on Egghead called Angular with Webpack which goes through initial Webpack configuration, ES6 and Babel, pre-processors, production and testing. Please note that the first of these videos is free to view while the rest require premium Egghead membership.
Jesus authored a comprehensive article titled Using Angular 1.x With ES6 and Webpack which covers the basics and outlines project folder structures, authoring directives, services, testing and so on.
Other notable blog posts includes:
- Angular, Webpack and ES6 by Danny Fenstermaker
- Creating an application with AngularJS 1.4, ECMAScript 6, Material Design and Webpack by Julien Renaux
- Angular, webpack and gulp for an SPA by Luwen-huang
Yet Another NG6 Seed Project
My motivation for angular-es6-webpack-seed was to build a seed project based on my previous experience on building a large AngularJS single page application. I also wanted to exploit the productivity gains introduced by Webpack and the following tools and libraries:
- Nested layouts via ui-router, which is the closest I could get to React’s react-router. More on this later
- Bootstrap 3.3.5 with angular-strap
- css hot loading. Not as awesome as react-hot-loader wit React but great nonetheless
- support for AMD/CommonJS module types - namely ES6’s
import from xyz 'xyz'and fat-arrow syntax
- ngTemplate bundling into $templateCache for all HTML templates
- ng-annotate annotations
- adoption of component based folder structures for controller views and directives that group files by functionality in the same folder. More on this later
- ES6 goodness via Babel
- painless project provisioning for developers via Vagrant and a single source of dependencies via
- Gulp based tasks for building, testing and deployment
The Vagrant configuration file sets up a host only private network on address 192.168.30.25 through which all ports are accessible (i.e. port 22 for SSH logins and port 8080 for the development web server). I’ve disabled the default Vagrant configuration which maps VM ports to the local port (i.e. VM:8080 to local:80 and VM:22 to local: 2222) as this could become an issue that prevents multiple Vagrant VMs from running.
Once setup, start the development server using
gulp and browse to http://192.168.30.25:8080 to view a very basic Bootstap layout application.
Files and Folders
- /src - this is the application’s root folder. If using WebStorm, set this folder as the Resource Root (under settings -> Project -> Directories)
- /src/app - the Angular application folder which defines the boot
and ui-routes based route files
- /src/controllers - contains all project controllers
- /src/directives - contains all project directives
- /src/services - contains all project services
This is the application boot file; it defines the project’s dependencies ( such as external modules, directives, controllers and services ) and routes.
This is the ui-router configuration file and defines the following nested routes:
- app - defines the application root and is linked to the ApplicationController and ApplicationTemplate and defines the application layout.
- app.home - defines the application home page and is linked to the HomeController and HomeTemplate. This is the landing page.
- app.page1 - an example page1
- app.page2 - an example page2
- app.login - the login page
- app.my - defines the privileged state root and is linked to the AuthenticationController, which performs a basic authentication check. Un-authenticated
users will be redirected to app.login. This is where ui-router shines as we can define nested app.my views that all inherit the authentication check
- app.my.profile - a logged in user’s profile page. Only accessible for logged in users. Inherits the authentication check from app.my
Controllers define views - i.e. page1, page2, login. Each controller is contained in its own folder and includes:
- index.js - style and asset imports and exports the controller function
- Style definitions
- HTML template
The myProfile controller best demonstrates the above where the controller’s index.js is:
index.js is responsible for importing the controller’s style and any images. The controller’s template, defined in the routes.js file is:
Note the namespaced view:
<div id="my-profile">. The controller’s style file uses the same
namespace for this controller’s styles. All controllers define their own CSS namespaces.
The image is imported via
import ngImg from './images/angular.png'. Angular requires that the image path be placed in a reference,
unlike JSX where the
require(./images/angular.png) could be placed directly in the template. This, I think, is a minor issue.
Each defined controller is then added to the application’s module via src/app/controllers/index.js:
I like the above method of defining controllers as it separates controller names from their definitions, something that should make controller modules easier to re-use.
Employs the exact same folder structure and logic as controllers.
Services and Factories are simpler to define as they should not have any dependant assets; these can be defined using the ES6 Class syntax.
Development Web Server
Webpack provides the webpack-dev-server HTTP server, which is configured using the following base and development configuration files. webpack.config.js is the base configuration which is overridden by both webpack.dev.js and webpack.prod.js. The same logic can be used to define a test configuration file.
This configuration includes:
- hot reloading for CSS style and image file changes - these updates do not require a page refresh
The development server is started by issuing the
gulp command in the project’s root folder.
Building and Deploying
The base webpack configuration is overridden by the production specific file to concatenate, minify, uglify and gzip all project assets, which includes css, image and font files into the build folder which can then be deployed via rsync or shipit.
The build process can be initiated by issuing the
gulp build command in the project’s root folder.
The opinions expressed here represent my own and may or may not have any basis in reality or truth. These opinions are completely my own and not those of my friends, colleagues, acquaintances, pets, employers, etc...