Setting up a CanJS project with the generator-canjs and Yeoman

In this blog post I'll show you how to setup a CanJS project with the help of the generator-canjs and Yeoman. I'll also show you some tricks I'm using to get everything working smoothly both in the development and production modes. We'll be setting up the project to use the Bootstrap and FontAwesome for the styles and icons.

Yeoman, Bower and Grunt

We will be using Yeoman, Bower and Grunt for various tasks in our development, so if you don't have them installed, do it now.

They are all implemented on the Node.JS platform so you'll need to install it first. After you've installed the Node.JS run:

$ npm install -g yo bower grunt

We also need the CanJS generator for Yeoman which can be installed by running:

$ npm install -g generator-canjs

With these dependencies installed, we can scaffold the app structure.

Scaffolding the app

To scaffold the app create the directory, enter it and run the generator:

$ mkdir canjs-app && cd canjs-app
$ yo canjs
                                            ####
    ######### ###########   ####  #######  ######
  ########### ############# ############### ####
 ############ ############# ###############
 ######              ###### #####    ###### ####  #######
 #####                ##### #####     ##### #### #########
 #####         ############ #####     ##### #### ####
 #####       ############## #####     ##### #### ####
 #####      #####    ###### #####     ##### ####  #####
 ######     #####     ##### #####     ##### ####    #####
 ########## ######### ##### #####     ##### ####      ####
  ########## ######## ##### #####     ##### ####      ####
    #######    #####   #### #####     ####  #### ########
                                          ######  ###### 
                                          #####
[?] What is the name of your application? canjs-app
[?] Would you like to include RequireJS (for AMD support)? Y/n Y

This generator will set up the basic structure, and we can start pulling in the dependencies.

Dependencies

Dependencies are managed with Bower, and we can immediately install the stuff we already know we'll need:

  • Bootstrap - for the grid and the basic styles
  • FontAwesome - for the icons

Run the following to install them:

$ bower install -S bootstrap fontawesome

When you ran the app generator the style folder was created. Usually I use the style/style.less as the starting point for my CSS styles.

First, let's set up Bootstrap and FontAwesome. Create the variables.less file in the style folder and copy the contents from the bower_components/bootstrap/less/variables.less in to that file.

Copy contents from the bower_components/bootstrap/less/bootstrap.less to style/style.less and adjust the paths for all the files except the variables.less file (we're loading that one from the style folder).

Your style/style.less file should look something like this:

// Core variables and mixins
@import "variables.less";
@import "../bower_components/bootstrap/less/mixins.less";

// Reset
@import "../bower_components/bootstrap/less/normalize.less";
@import "../bower_components/bootstrap/less/print.less";

// Core CSS
@import "../bower_components/bootstrap/less/scaffolding.less";
...
@import "../bower_components/bootstrap/less/responsive-utilities.less";

Bootstraping Bootstrap (yeah, I know :)) from the style/style.less file allows us to make changes to the styles in the isolation from the original Bootstrap code. This makes future upgrades of the Bootstrap library painless and simple.

We'll immediately do a change and include the FontAwesome instead of the original Bootstrap's icons.

Open style/variables.less file and remove the lines 71 - 80 (@icon-font related variables):

Remove these lines:

//-- Iconography
//
//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.

@icon-font-path:          "../fonts/";
@icon-font-name:          "glyphicons-halflings-regular";
@icon-font-svg-id:        "glyphicons_halflingsregular";

Now copy the contents from the bower_components/fontawesome/less/variables.less to the bottom of the style/variables.less file and adjust the @fa-font-path variable:

@fa-font-path:        "../bower_components/fontawesome/fonts";

We also need to load the FontAwesome library from the style/style.less file. Remove the line that loads the Glyphicons:

@import "../bower_components/bootstrap/less/glyphicons.less";

And copy contents from the ../bower_components/fontawesome/less/font-awesome.less to the bottom of that file:

/*!
 *  Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome
 *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
 */
@import "variables.less";
@import "mixins.less";
@import "path.less";
...
@import "icons.less";

Remove the @import "variables.less"; line (since we're already loading this file on the top of the style/style.less file) and adjust the paths:

/*!
 *  Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome
 *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
 */
@import "../bower_components/fontawesome/less/mixins.less";
@import "../bower_components/fontawesome/less/path.less";
@import "../bower_components/fontawesome/less/core.less";
...

Our base styles are now ready, and we have the complete control over them. Loading the Bootstrap and the FontAwesome .less files from the style/style.less file allows us to do easy customizations while keeping the original code intact.

HTML files

App generator created two .html files in the project root. The canjs-app.html file and the production.html file. canjs-app.html file will be used for the development, as it loads the dev versions of all scripts, while the production.html loads only the built file.

Let's modify the canjs-app.html file and load the CSS. Add this line to your <head> section:

<link rel="stylesheet" href="style/style.css">

Now run $ grunt watch in one terminal window and $ grunt connect:server in another one. If you see the following image when you go to localhost:9001/canjs-app.html everything is set up correctly:

Components

We set up the base app structure, and now is the time to add support for the components. When developing CanJS apps, it is a good practice to develop each component in the complete isolation from the rest of the app. All of it's styles, templates and assets should be contained in one folder, ready for reusing. There is a problem with supporting the image and font paths in the CSS.

We want our CSS to work the same in three different contexts:

  1. Component development mode (loaded from: localhost://9001/components/some_component/some_component.html)
  2. App development mode (loaded from: localhost://9001/components/app.html)
  3. App production mode (loaded from: localhost://9001/components/production.html)

App development and production mode are pretty much the same, but we have an issue with the component development mode since it will load the CSS from the different location. Thankfully, LESS compiler can rewrite urls in the build step, so we can get the correct urls in the built CSS.

To take advantage of this, I recommend you to use the following technique:

  1. Create style/components.less file and @import each component's LESS file from there
  2. Import style/components.less file from the style/style.less file
  3. Load the built 'style/style.css' file from the component's demo page (eg. components/users/users.html) as it will have the correct paths

Let's try it out! Run the following to generate the component:

$ yo canjs:component components/users
[?] Please enter the path to the component eg.: components/users: components/users
create components/users/users.js
create components/users/users.html
create components/users/users.less
create components/users/users.mustache
identical components/users/users.less

Add the following line to style/components.less file:

@import "../components/users/users.less";

and make sure you're importing the style/components.less from the style/style.less file:

@import "variables.less";
...
@import "components.less";

And let's edit the components/users/users.less file just to check that everything is loading correctly:

users {
    display: block;
    color: red;
    font-size: 100px;
}

Note that we're wrapping the styles with the name of the component tag. This ensures isolation of the component styles from the more general styles located in the style folder

If you see the following when you load http://localhost:9001/components/users/users.html everything is set up correctly:

If your changes are not visible, try to restart the grunt watch process, so it picks up the new files to watch

You can find the code for this example in the GitHub repo, and make sure that if you have any questions, you either comment below or send me an email!

Did you like this article?

If so, subscribe to Retroaktive.me mailing list and get notified when the new stuff gets posted

* indicates required
comments powered by Disqus