Front-end project assets 
management

SCALE OF MODERN FRONT-END APPS


  • Client Web Applications are not as they used to be
  • ...they are more complicated
  • ...harder to develop, debug and maintain
  • ...freaking huge and cumbersome when built
  • ...and get out of control easiliy

Can we do anything about it?



YES, WE CAN

The Solution lays here

  • use a tool for dependency tracking and resolving
  • use preprocessors, templates and compilers for them
  • analyze code quality and calculate code metrics
  • concatenate and minify resources for production builds

stuff people use

(they claim it helps)

RequireJS

LMD
Grunt

Steal.js
Brunch

stEAL & GRUNT

(apples and oranges)

RequireJS

LMD
Grunt

Steal.js
Brunch

GRUNT & STEAL


Grunt is system of Node.js applications that run multi-purpose tasks that can be configured with a flexible syntax and API

Steal.js is a rich JavaScript library that allows loading resources of different kinds; it also facilitates production project building

GRUNT & STEAL: ABILITIES


  • Extendable plugin-based ecosystem
  • Tons of various plugins available
  • Process assets and enhance workflow
  • High customizability


Steal



  • Client-side library
  • Dependency tracking
  • LESS, EJS, CoffeeScript, Moustache processing
  • Production-ready packaging

PROJECT: A new beginning 

Steal

A new beginning 


Project structure
project
	jquery
	steal
	app
	index.html
index.html
<script src="steal/steal.js"></script>


<script>steal('jquery/jquery.js')</script>

A NEW BEGINNING

Recruit a grunt: 200 3
$ npm i grunt-cli -g
$ npm init
$ npm i grunt --save
Project structure
project
    node_modules
    package.json
    Gruntfile.js
    index.html
package.json
{
  "name": "frontend-project",
  "version": "0.0.0",
  "description": "My amazing front-end project",
  "dependencies": {
    "grunt": "~0.4.1",
  },
  "devDependencies": {}
}
Steal

First Steps


app.js
steal('jquery/jquery.js')
.then(function($) {
    //run you application here
});
index.html
<script src="steal/steal.js?app/app.js"></script>

<script src="steal/steal.js?app"></script>

First Steps

$ npm i grunt-contrib-uglify --save-dev
Gruntfile.js
module.exports = function(grunt) {
  grunt.initConfig({
    uglify: {
      options: {
        banner: '/* <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      myapp: {
        src: 'app/app.js',
        dest: 'build/app.min.js'
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.registerTask('default', ['uglify']);
};

First Steps

index.html
<script src="build/app.min.js"></script>
$ grunt
$ grunt uglify
$ grunt uglify:build
Steal

Relations


Project structure
project
    jquery
    steal
    app
        app.js
        table
            table.js
            resources
                less
                views
                scripts
    index.html

					
Steal

Relations


table.js
steal(
    'jquery/view/ejs',
    {src: "steal/less", ignore: true}
).then(
    //styles
    'resources/less/table.less',
    //templates
    'resources/views/table.ejs',
    'resources/views/cell.ejs',
    //scripts
    'resources/scripts/date.js'
).then(function($) {
    window.Table = function() {...};
});
app.js
stea('jquery')
.then('app/table/table.js')
.then(function($) {
	new window.Table(...);
});

Relations

grunt-contrib-watch
watch: {
  mysrc: {
    files: ['**/*.js'],
    tasks: ['uglify:dev'],
    options: {
      nospawn: true,
    }
  }
}
grunt-hub
hub: {
    all: {
      src: ['app/table/Gruntfile.js'],
      tasks: ['jshint', 'uglify'],
    }
}
Steal

Templating


ejs, jaml, micro, tmpl, mustache
steal(
    'jquery/view/ejs',
    {src: "steal/less", ignore: true}
).then(
    //styles
    'resources/less/table.less',
    //templates
    'resources/views/table.ejs',
    'resources/views/cell.ejs',
    //scripts
    'resources/scripts/date.js'
).then(function($) {
    window.Table = function() {...
        $(el).html($.View('resources/views/table.ejs'));
    ...};
});

Templating

All-you-can-eat buffet

  • jade
  • handlebars
  • doT
  • Dust.js
  • AngularJS
  • ...

Templating

grunt-contrib-jade
jade: {
    compile: {
        options: {
            compileDebug: false,
            client: true,
            namespace: 'App.Templates',
            processName: function(filename) {
                var basename = path.basename(filename, '.jade');
                // table.jade --> App.Templates.Table
                return basename.charAt(0).toUpperCase()
                       + basename.slice(1);
            }
        },
        files: { 'build/templates.js': 'app/table/views/*.jade' }
    }
}

Getting stylish

Steal

Getting stylish


CSS, LESS

steal(
    'jquery/view/ejs',
    {src: "steal/less", ignore: true}
).then(
    //styles
    'resources/less/table.less',
    //templates
    'resources/views/table.ejs',
    'resources/views/cell.ejs',
    //scripts
    'resources/scripts/date.js'
).then(function($) {
    window.Table = function() {...};
});

Getting Stylish


  • LESS, SCSS, Stylus
  • rework
  • generate sprites, lint, compress, prettiffy
  • ...and more!

DITCH JAVASCRIPT


  • CoffeeScript
  • TypeScript
  • ClojureScript

Bonus Features

Steal

Bonus Features


  • lazy loading
  • conditional building
//!steal-remove-start
code to be removed at build
//!steal-remove-end
steal({
    src: "app/table/table.js",
    type: "js",
    packaged: false,
    unique: true,
    ignore: false,
    waits: false
})

Bonus Features


  • grunt-contrib-*
  • clean, copy, concat, compress...
  • documentation, dependencies, conversion
  • TDD, BDD, functional, headless envs...
  • livereload
  • Write your own: Grunt API

Production packaging

Steal

Production Packaging

project
    jquery
    steal
    app
        build-scripts
build_app.js
( function( args ) {
    load( "steal/rhino/rhino.js" );
    new steal.File( "Build" ).mkdir();
    steal.build("index.html", { to: "Build", all: true });
})();
> java -jar steal\rhino\js.jar -opt -1 app\build-scripts\build_app.js

Production Packaging

Build
grunt build
deploy & publish
Steal

PROS


  • client-side-oriented
  • easy bootstrapping
  • encourage modularity
  • no additional build configuration

Pros


  • Versatility
  • Extensibility
  • Popularity

PROS

Steal

CONS

  • adding compiled langs support requires extra effort
  • templating interface is jQuery-dependent
  • current build process uses Rhino (Node.js coming)
  • quirks: LESS in IE dynamic style application, mandatory steal wrapper when calling steal

Cons


  • You have to install Node.js
  • [and probably switch to a Unix-based OS]
  • No guarantees about plugin quality

Evil Grunt Plugins


options.use.forEach(function (e) {
  var fnName = e.shift();
  var fnArgs = e.map(function (arg) {
    return JSON.stringify(arg);
  }).join(', ');
  css.use(eval(fnName + '(' + fnArgs + ')'));
});

CONS

That's it, folks