<img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 https://www.facebook.com/tr?id=1063935717132479&amp;ev=PageView&amp;noscript=1 "> Bitovi Blog - UX and UI design, JavaScript and Frontend development
Loading

Using CanJS 2.2 with StealJS and NPM

Using CanJS 2.2 with StealJS and NPM

The Bitovi Team

The Bitovi Team

Twitter Reddit

CanJS has always been fully modular and can be used with different module formats like AMD or CommonJS and installed via Bower or NPM or the direct download. When using a module loader - unlike many other frameworks that simply provide a UMD wrapper for the entire library - CanJS will only load the dependencies it really needs.

This is the beginning of a series of posts that go over different combinations of package managers and module loaders and how to set them up with CanJS.

In this post we will talk about using CanJS with the new StealJS and NPM which provides a seamless, zero-configuration development experience.

NPM and Steal setup

In a new folder initialize a package.json by answering the prompts from

npm init

The only important prompt here is to set the entry point to app which will be our main application file:

npm init prompt

Then install and save the steal and can packages:

npm install can steal --save

jQuery will be installed and loaded automatically since it is a peer dependency of CanJS. Then create an index.html like this:

<!DOCTYPE html>
<html>
  <head>
    <title>CanJS + Steal + NPM demo</title>
  </head>
  <body>
    <script type="text/javascript" src="node_modules/steal/steal.js"></script>
  </body>
</html>

Steal will now automatically load its configuration from the package.json we initialized. Because it supports different module formats we can choose to use ES6 modules (and any other ES6 features provided by the Traceur or Babel transpilers), CommonJS or AMD. In ES6 an app.js that loads jQuery and Stache and renders a simple template when the document is ready can look like this:

import $ from 'jquery';
import stache from 'can/view/stache/stache';

const template = stache('Hello !');

$(() => {
  $('body').append(template({ message: 'David' }));
});

The same file in CommonJS would look like:

var $ = require('jquery');
var stache = require('can/view/stache/stache');

var template = stache('Hello !');

$(function() {
  $('body').append(template({ message: 'David' }));
});

And using AMD like this:

define(['jquery', 'can/view/stache/stache'], function($, stache) {
  var template = stache('Hello !');

  $(function() {
    $('body').append(template({ message: 'David' }));
  });
});

If you now open index.html you will see that all dependencies are being loaded and the view is rendered.

Configuring StealJS

This zero configuration approach already works with many client-side JavaScript libraries that are available on NPM like jQuery, Lodash, MomentJS or ChartJS. Additional configuration, like mappings and shims to libraries that do not support a module loader can be put into a system property in the package.json.

For example, if you downloaded the Tooltipster jQuery plugin and put it into a lib/tooltipster folder in your project, the configuration to make it available as the tooltipster module and load its CSS file automatically would look like this:

{
  "name": "steal-can",
  "version": "0.0.1",
  "description": "A StealJS + CanJS example",
  "main": "app",
  "author": "Bitovi",
  "license": "MIT",
  "dependencies": {
    "can": "^2.2.5",
    "jquery": "^2.1.3",
    "steal": "^0.9.3"
  },
  "system": {
    "paths": {
      "tooltipster": "lib/tooltipster/js/jquery.tooltipster.js"
    },
    "meta": {
      "tooltipster": {
        "deps": ["lib/tooltipster/css/tooltipster.css!"]
      }
    }
  }
}

Then we can load and initialize the plugin in app.js:

import $ from 'jquery';
import 'tooltipster';
import stache from 'can/view/stache/stache';

const template = stache('<div title="Hello {{message}}!">Hover me for a tooltip</div>');

$(() => {
  $('body').append(template({ message: 'David' }));
  $('div').tooltipster();
});

When you now reload the page you will see the tooltip when hovering over the element.

Production build

To build the project for production we will use the steal-tools NPM package that we can install as a development dependency:

npm install steal-tools --save-dev

Running steal-tools without any parameters will build using our package.json as the configuration. Lets add a build NPM script that simply runs the steal-tools binary we just installed:

{
  "name": "steal-can",
  "version": "0.0.1",
  "description": "A StealJS + CanJS example",
  "main": "app",
  "scripts": {
    "build": "steal-tools"
  },
  "author": "Bitovi",
  "license": "MIT",
  "dependencies": {
    "can": "^2.2.5",
    "jquery": "^2.1.3",
    "steal": "^0.9.3"
  },
  "devDependencies": {
    "steal-tools": "^0.9.4"
  },
  "system": {
    "paths": {
      "tooltipster": "lib/tooltipster/js/jquery.tooltipster.js"
    },
    "meta": {
      "tooltipster": {
        "deps": ["lib/tooltipster/css/tooltipster.css!"]
      }
    }
  }
}

The production build can now be kicked off with:

npm run build

The build files will end up in dist/bundles/app.css and dist/bundles/app.js. To load those files instead of the individual modules we need to add a main="app" and env="production" to the Steal script tag in index.html:

<!DOCTYPE html>
<html>
  <head>
    <title>CanJS + Steal + NPM demo</title>
  </head>
  <body>
    <script type="text/javascript" src="node_modules/steal/steal.js" env="production" main="app"></script>
  </body>
</html>

Now the application is ready to ship.

Conclusion

In this post we went over a simple application that uses StealJS, NPM and CanJS and also configured Steal to load a third party jQuery plugin and use it in a CanJS Stache template. We were able to make a production build for both, JavaScript and CSS with no other configuration than a package.json. You can download the demo application in this Gist.