Dive into SPA with

RaveJS

and

Grails

Fabrice Matrat


@fabricematrat
fabricematrat@gmail.com

Beware



  • Strongly opinionated
  • my own Point of View

Single Page Application



Traditional vs SPA



SPA



Characteristics



  • Fits on a single page
  • Persisting client state
  • Loads on initial page load
  • Asynch loads of features

And ?



    Pros

  • Responsive
  • Application like interaction
  • Raw Data
  • Caching
  • Offline
  • JavaScript

Cons

  • SEO
  • JavaScript

Sample: Amadeus



Sample: Juju



Grails ?



GSPs are Old Fashion



Hybrid client/server view rendering with Grails

See Rob Fletcher Presentation @GR8Conf US

Be carefull



http://blog.mwaysolutions.com/2013/11/08/client-vs-serverside-rendering-the-big-battle-2/

Grails/JS



UI Performance Plugin


Authors: Burt Beckwith

  • Minification, GZip
  • Caching, headers
  • Taglibs
  • Gzips dynamic text content
  • Sprites
  • JS at the bottom
  • Grails friendly

Resource Plugin



HTML resource management enhancements to replace g.resource

Marc Palmer, Luke Daley, Peter N. Steinmetz

  • Declare and Link resources in app
  • Using require taglib in GSPs
  • Redirection
  • Dependencies

Asset Plugin



  • File Dependencies
  • Assets in plugins
  • Better Development Environment
  • Production Environment
  • Faster Startup times
  • Coffee, LESS .. are better citizens

File



//=require ember
//=require handlebars
//=require_self
//=require_tree helpers
//=require_tree models
//=require_tree controllers
//=require_tree views

MyApp = Ember.Application.create({
    ready: function() {
        console.log("Application Launched!");
    }
});

JQuery



  • Good Documentation
  • Lots of efforts and tuning
  • Better Dom Manupulation API ?
  • Wide adoption

But !



  • Need Module
  • Dom Manipulation/JS Utilities !?
  • Promise broken
  • Weight

Venkat Subramaniam

JQUERY FOR GRAILS DEVELOPERS

Bootstrap



Pros

  • First one
  • Good Documentation
  • Wide adoption

Cons

  • Website look all the same
  • Weight

Is this enough ?



Embrace JS Community



NodeJS



Grunt



A Task Runner



  • concat
  • init
  • lint
  • min
  • qunit
  • server
  • test
  • watch

Customization



  • Simple config
  • Common build steps
  • Plugins

More than 3400 plugins

No more built-in tasks

How



npm install -g grunt-cli

grunt --version

Gruntfile.js



uglify: {
    build: {
        files: {
           'build/js/base.min.js': ['assets/js/base.js']
        }
    }
}

Gulp


/>

What's new ?



  • Stream-based build system
  • Code over configuration
  • Small, idiomatic Node modules
  • Really simple, elegant API
  • Faster
  • 800 plugins

How



var gulp = require('gulp'),
  stylus = require('gulp-stylus'),
  autoprefixer = require('gulp-autoprefixer');

gulp.task('default', function() {
  return gulp.src('src/styles/*.styl')
    .pipe(stylus())
    .pipe(autoprefixer())
    .pipe(gulp.dest('public/styles'));
});

Use a MVC



http://todomvc.com around 70 MVCs

Package and Module



The future of JS is module not framework
John Hann

What is a package ?



a package is a set of one or more modules that are meant to work together

What is a module ?



a module is a way of exposing an Object or a function, respecting isolation, namespacing and private state

Module Pattern



  • Isolation
  • Namespacing
  • Private State

Module Pattern In Action



var MODULE = (function () {
    var my = {};
    var privateVariable = 1;

    function privateMethod() {
        // ...
    }

    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };

    return my;
}());

var my_module = new MODULE();

NPM



  • The package manager with the Node.js
  • Install code and Manage code dependencies
  • More that 90 000 packages in npm

Usage



npm install angular   
npm uninstall angular
npm update angular  
npm search angular

Wait, I'm a front-end engineer

and

I am using Grails for backend not NodeJS/NPM !



Bower



  • Most popular package manager for client-side JS
  • 20000 packages

Usage



bower install --save backbone
bower uninstall --save backbone
bower-update //to update properly
bower search backbone

Differences with NPM



  • With Bower, each package is installed once
  • NPM dictates that packages follow the CommonJS specification
  • Bower makes no assumptions about how assets are written or included
  • Bower is simplistic compare to NPM

Expose and Use Module



Format



  • CommonJS
  • AMD
  • Harmony

http://addyosmani.com/writing-modular-js

CommonJS


MODULE.js

var privateVariable = 1;
var privateMethod = function () {  // ... };
exports.moduleMethod: function () {  // ... };

someplace.js

var my_module = require(‘./MODULE’);

AMD


MODULE.js

define(function () {
  return function() {
    var privateVariable = 1;
    var privateMethod = function () { // ... };
    return function () {  // ... };
  };
});

someplace.js

define(['MODULE'], function (my_module) {
});

Harmony


MODULE.js

export function MODULE() {
  var privateVariable = 1;
  var privateMethod = function () { // ... };
  // ...
};

someplace.js

import my_module from './MODULE';

Haaaaa !!!!!!



  • Already 3 Module Formats
  • Dart, ES5, ES6
  • SASS, LESS, Stylus
  • Grunt, Gulp
  • Linter
  • JS Unit Test
  • Pkg Manager

Problem



  • boilerplate
  • conf
  • setup

Grails, Dependency Management



  • Ivy
    • snapshot handling
    • Pb with packaging type
    • complex POMs and classifiers
  • Aether
    • Improvment
  • Gradle for Grails 3

Grails Plugins for JS



  • Resource plugin
  • Asset Plugin
  • 115 Plugins for CSS
  • 166 Plugins for JavaScript

Problem



  • boilerplate
  • conf
  • setup

It's a mess !

┏( ^◡^)┛ ┗(^◡^ )┓

RaveJS

┗( ^◡^)┓ ┓(^◡^ )┛

Goal



  • Rave eliminates
    • configuration
    • machinery
    • complexity
  • Not a framework
  • Integration with most framework

First



Use Metadata from Package Author

bower.json



  • name
  • main
  • dependencies
  • devDependencies
  • resolutions
  • moduleType

description, licence, version, ignore, keywords

authors, homepage, repository, private

{
    "name": "wire",
    "version": "0.10.9",
    "main": "./wire.js",
    "moduleType": ["amd"],
    "dependencies": {
        "meld": "~1",
        "when": "~3",
        "poly": "~0"
    },
    "devDependencies": {
        "curl": "~0",
        "requirejs": "~2",
        "requirejs-domready": "~2",
        "sizzle": "~1",
        "jquery": "~1",
        "dojo": "~1",
        "dijit": "~1"
    }
}

package.json



  • name
  • main
  • dependencies
  • devDependencies
  • peerDependencies
  • bundledDependencies
  • optionalDependencies
  • directories

      description, keywords, homepage, bugs, ...

{
    "name": "wire",
    "version": "0.10.9",
    "dependencies": {
        "meld": "~1",
        "when": ">=2.6.0 "
    },
    "devDependencies": {
        "buster": "~0.7",
        "bower": "~1",
        "gent": "~0.6"
    },
    "main": "./wire",
    "directories": {
        "test": "test"
    },
    "scripts": {
        "test": "buster-test -e node",
        "prepublish": "bower install"
    }
}

Mix NPM and Bower



data-rave-meta="bower.json, package.json"

npm install --save angular
bower install --save when

Embraces the future



an ES6 Loader polyfill built in

Dynamically loads ES6 modules in current browsers

Rave extensions



  • Loading patterns
  • Build patterns
  • Deployment patterns
  • Testing patterns
  • Adding missing metada from third party packages

Interpreter



In Browser Console, type rave()

  • rave.dump()
  • rave.version
  • rave.checkVersions()
  • rave.help()

Rave Starter



  • Opinionated Starter
  • Change it, Remove it, Love it
  • Already some available
  • Create your own

Debug



HTML attribute

  • data-debug
  • data-when-debug
  • data-rave-debug

Production Ready ?



No :(

Coding Time



Let' try it with angular !

MVC



SPA Architecture



Which One ?



Inspiration



  • Spring like
  • Functional
  • JS prototypal roots
  • Architecture tool kit
  • HTML, CSS, and Javascript

Small package



Wire



  • Dependency Injection
  • Lifecycle management
  • Configuration

Show me



define({
  helloWired: {
    create: {
      module: 'app/hello-wired',
      args: { $ref: 'dom.first!hello' }
    },
    init: {
      sayHello: { $ref: 'message' }
    }
  }
});

Meld



  • Aspect Oriented Programming
  • change/add behavior to existing methods

Seen this before ?



var origDoSomething = thing.doSomething;

thing.doSomething = function() {
  doSomethingElseFirst();
  return origDoSomething.apply(this, arguments);
}

Meld in Action



var myObject = {
  doSomething: function(a, b) { return a + b; }
};

// Call a function after myObject.doSomething returns
var remover = meld.after(myObject, 'doSomething', function(result) {
  console.log('myObject.doSomething returned: ' + result);
});

myObject.doSomething(1, 2); // Logs: "myObject.doSomething returned: 3"
remover.remove();
myObject.doSomething(1, 2); // Nothing logged

AOP + DI



todos: {
  create: {
    module: 'cola/Collection',
    args: {
      strategyOptions: {
        validator: { module: 'app/create/validateTodo' }
      }
    }
  },
  before: {
    add: 'cleanTodo | generateMetadata',
    update: 'cleanTodo'
  }
}

meld + wire = <3

Coding Time



Let' try RaveJS + CujoJS !

Key takeaways



  • RaveJS simplify your life
  • CujoJS provides vital architectural tools
  • Grails provides the best server-side architecture
  • Help for a better integration


That's all Folks !