We have components everywhere. Our software is no exception. We have them in cutting edge stuffs like React, Bower, NPM, Web Components, Ember, and now in Angular 2. Components are like building blocks in Lego game which does one thing and does it very well. And they’re so generic/reusable that we can fit them together to build stuffs that we want.
Now think about them other way around. We can split our huge application into smaller, independent, reusable and testable components based on their functionality which can then be packaged together to build the entire application. These components can be business objects like product, user, shopping cart, etc. or even technical things like header, footer, menu, etc. These can then be reused in other applications of similar nature requiring similar business and technical components.
With ES2015 and component router in Angular 1.5 coming soon which is going to ease the transition to Angular 2, it’s worth exploring the newest way of writing Angular apps using this super awesome combo and component mindset. And then we can take it to next level by automating component making process and make it as simple as a cookie cutter.
Here are the 2 tools that we need:
1. Webpack:
- Transpiles ES2015 (ES6) to ES5 (JavaScript that current browsers know).
- Loads HTML files and dependent files as modules.
- Transpiles stylesheets and appends them to HTML.
- Bundles the entire app.
- Loads the modules on demand to keep initial load time low.
2. Gulp:
Gulp is used as orchestrator for
- Starting and calling Webpack.
- Starting a development server.
- Refreshing the browser and rebuilding on file changes.
File Organization of Angular App:
With components in mind, let’s have file organization as show below:
client
⋅⋅app/
⋅⋅⋅⋅app.js * app entry file
⋅⋅⋅⋅app.html * app template
⋅⋅⋅⋅common/ * functionality pertinent to several components
⋅⋅⋅⋅components/ * where components live
⋅⋅⋅⋅⋅⋅components.js * components entry file
⋅⋅⋅⋅⋅⋅home/ * home component
⋅⋅⋅⋅⋅⋅⋅⋅home.js * entry file (routes, configurations, declarations)
⋅⋅⋅⋅⋅⋅⋅⋅home.component.js * home "directive"
⋅⋅⋅⋅⋅⋅⋅⋅home.controller.js * home controller
⋅⋅⋅⋅⋅⋅⋅⋅home.styl * home styles
⋅⋅⋅⋅⋅⋅⋅⋅home.html * home template
⋅⋅⋅⋅⋅⋅⋅⋅home.spec.js * home specs
Let’s look at how home component can be implemented in these individual files using new features like import, export, class, object shortcut notation, arrow function from ES2015:
home.js:
This is the first file we should look at as it holds the definition of the component, what url it is reachable at and what’s its template which acts as skin cover for the component. The template (line 15) should use a custom directive, home in this case (line 19), which is imported as homeComponent from home.component.js file (line 3).
Note: Above is the only component file that has angular in it. The following files have plain JavaScript making Angular’s footprint smaller in our code base. Thanks to ES2015's import/export feature to make this possible.
home.component.js:
This is the center piece that imports and knits the component’s HTML, controller and stylesheet together. Since this custom directive is used in the template of home component, home.html gets rendered on the screen with home.styl applied to it.
home.controller.js:
Next comes the controller that makes all the JavaScript properties and methods defined on HomeController class accessible in the home.html template via controller’s alias name vm declared in above file.
home.styl:
Stylesheet written using Stylus gets converted to CSS using Webpack’s stylus loader.
home.html:
This holds the UI of the component, binding the data and methods defined in the controller class via vm object.
home.spec.js:
With spec file for individual components, we can write well focused and isolated test cases for all the features we add in our component. Also packing spec file in here ensures that it will always move along with the component if it is reused in other applications.
Webpack Config:
It’s worth mentioning about Webpack module loaders configuration that makes importing .html, .styl, .css, .js and even .png, .jpg, .jpeg possible at component level. Here is how loaders are configured:
webpack.config.js:
Automation of Component Creation:
Writing these individual files for creating components is tedious. How about automating it? Let’s take copy of all the home component files and name them as temp and parameterize name of the component in these files for automating component creation.
temp.js:
temp.component.js:
temp.controller.js:
temp.styl:
temp.html:
temp.spec.js:
Command To Cut A Component:
gulp component --name componentName
And you get a brand new component cut out with the given name. Isn’t this as simple as a cookie cutter? This is all it takes to setup this command as a gulp task in gulpfile.js:
We need to have all the temp files listed above inside a directory and point paths.blankTemplates variable to it to seed all these files in this task. It will take name parameter that we will enter in the command after — name and use it to replace name and upCaseName in all these files that we have parameterized between <%= and %>
That’s is it! If you want to try this out yourself, fork and play around with this tiny seed called NG6-starter.