26
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ RaveJS: Zero-config app development John Hann , JavaScript Barbarian, Pivotal @unscriptable

Introducing RaveJS: Zero-config JavaScript applications

Embed Size (px)

DESCRIPTION

Introducing RaveJS. Rave eliminates configuration, machinery, and complexity. Stop configuring and tweaking file watchers, minifiers, and transpilers just to get to a runnable app. Instead, go from zero to "hello world" in 30 seconds. In the next 30 seconds, easily add capabilities and frameworks to your application simply by installing *Rave Extensions* and *Rave Starter* packages from npm and Bower, the leading JavaScript package managers. Finally, install additional *Rave Extension* packages to apply your favorite build, deploy, and testing patterns. https://github.com/RaveJS

Citation preview

Page 1: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

RaveJS: Zero-config app development

John Hann, JavaScript Barbarian, Pivotal@unscriptable

Page 2: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

I work for Pivotal's Frameworks and Runtimes group

2

Page 3: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

I work on the cujoJS Toolkit - cujojs.com

3

Page 4: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/4

JavaScript is awesome

Architecture Language Tooling

• Package managers• Minifiers / optimizers• Bundlers / builders• Pre-processors• CI

• SASS/SCSS, LESS, Stylus --> CSS

• Dart --> Javascript• ES6 --> ES5• Transpile all the things!

• SPA, AOP, DI, IOC• MV-WTF• Modules, components• Linters, unit testers,

integration testers

Page 5: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

More is more

5

More sophistication

More complexity

More machinery

More configuration

More maintenance

Page 6: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

“JavaScript needs a build step.”

WTF?6

Page 7: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

What happened to the good ol' days?<!doctype html>

<html lang="en"><head><script src="easy.js"></script><link href="easy.css" type="stylesheet"/></head><body> <div class="container">click me</div></body></html>

7

Page 8: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Problem: HTML forces crappy JavaScript

You have to choose

• Simple HTML or

• Architecturally sound code and best practices

Doing it the "right way" requires

• Too much boilerplate, configuration, and setup

Too much work to create

• Apps

• Prototypes and experiments

• Demos and tutorials

8

Page 9: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Example: recent project

~400 LOC in Gruntfile.js~70 LOC in RequireJS main.js

>100 LOC in karma configs

9

Page 10: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

'use strict';

module.exports = function (grunt) {

  // Load grunt tasks automatically  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times  require('time-grunt')(grunt);

  // Define the configuration for all the tasks  grunt.initConfig({

    // Project settings    xd: {      app: 'app',      dist: 'dist'    },    // Set bower task's targetDir to use app directory    bower: {      options: {        targetDir: '<%= xd.app %>/lib'      },      // Provide install target      install: {}    },    // Watches files for changes and runs tasks based on the changed files    watch: {      files: ['<%= xd.app %>/**/*', '*.js', '.jshintrc'],      tasks: ['build'],      livereload: {        options: {          livereload: '<%= connect.options.livereload %>'        },        files: ['<%= xd.app %>/**/*', '*.js', '.jshintrc']      }    },    protractor: {      options: {

        //configFile: "test/protractor.conf.js", // Default config file        keepAlive: true, // If false, the grunt process stops when the test fails.        noColor: false, // If true, protractor will not use colors in its output.        args: {          specs: [            './test/e2e/**/*.spec.js'          ],          baseUrl: 'http://localhost:8000',          chromeDriver: 'node_modules/protractor/selenium/chromedriver'        }      },      run: {      }    },    // The actual grunt server settings    connect: {      options: {        port: 8000,        // Set to '0.0.0.0' to access the server from outside.        hostname: '0.0.0.0',        livereload: 35729      },      livereload: {        options: {          open: true,          base: [            '.tmp',            '<%= xd.app %>'          ],          middleware: function (connect, options) {

            if (!Array.isArray(options.base)) {              options.base = [options.base];            }            var middlewares = [require('grunt-connect-proxy/lib/utils').proxyRequest];

            options.base.forEach(function (base) {

              grunt.log.warn(base);              middlewares.push(connect.static(base));            });            return middlewares;          }        }      },      test: {        options: {          port: 9001,          base: [            '.tmp',            'test',            '<%= xd.app %>'          ]        }      },      dist: {        options: {          base: '<%= xd.dist %>'        }      },      proxies: [        {          context: ['/batch', '/job', '/modules', '/streams'],          host: 'localhost',          port: 9393,          changeOrigin: true        }      ]    },

    // Make sure code styles are up to par and there are no obvious mistakes    jshint: {      options: {        jshintrc: '.jshintrc',        reporter: require('jshint-stylish')      },      all: [        'Gruntfile.js',        '<%= xd.app %>/scripts/{,**/}*.js'      ],      test: {        options: {          jshintrc: 'test/.jshintrc'        },

        src: ['test/spec/{,*/}*.js']      }    },    less: {      dist: {        files: {          '<%= xd.app %>/styles/main.css': ['<%= xd.app %>/styles/main.less']        },        options: {          sourceMap: true,          sourceMapFilename: '<%= xd.app %>/styles/main.css.map',          sourceMapBasepath: '<%= xd.app %>/',          sourceMapRootpath: '/'        }      }    },    // Empties folders to start fresh    clean: {      dist: {        files: [          {            dot: true,            src: [              '.tmp',              '<%= xd.dist %>/*'            ]          }        ]      },      server: '.tmp'    },

    // Add vendor prefixed styles    autoprefixer: {      options: {        browsers: ['last 1 version']      },      dist: {        files: [          {            expand: true,            cwd: '.tmp/styles/',            src: '{,*/}*.css',            dest: '.tmp/styles/'          }

        ]      }    },

// imagemin: {// dist: {// files: [// {// expand: true,// cwd: '<%= xd.app %>/images',// src: '{,*/}*.{png,jpg,jpeg,gif}',// dest: '<%= xd.dist %>/images'// }// ]// }// },

    // Renames files for browser caching purposes    rev: {      dist: {        files: {          src: [            // TODO: commenting out js files for now.            // '<%= xd.dist %>/scripts/{,*/}*.js',            '<%= xd.dist %>/styles/{,*/}*.css',            '<%= xd.dist %>/images/{,*/}*.{png,jpg,jpeg,gif}',            '<%= xd.dist %>/fonts/*'          ]        }      }    },

    // Reads HTML for usemin blocks to enable smart builds that automatically    // concat, minify and revision files. Creates configurations in memory so    // additional tasks can operate on them    useminPrepare: {      html: '<%= xd.app %>/index.html',      options: {        dest: '<%= xd.dist %>'      }    },

    // Performs rewrites based on rev and the useminPrepare configuration    usemin: {      html: ['<%= xd.dist %>/{,*/}*.html'],      css: ['<%= xd.dist %>/styles/{,*/}*.css'],      options: {        assetsDirs: ['<%= xd.dist %>', '<%= xd.dist %>/images']      }    },

    htmlmin: {      dist: {        options: {          collapseWhitespace: true,          collapseBooleanAttributes: true,          removeCommentsFromCDATA: true,          removeOptionalTags: true        },        files: [          {            expand: true,            cwd: '<%= xd.dist %>',            src: ['*.html', 'views/{,*/}*.html'],            dest: '<%= xd.dist %>'          }        ]      }    },    // Allow the use of non-minsafe AngularJS files. Automatically makes it    // minsafe compatible so Uglify does not destroy the ng references// ngmin: {// dist: {// files: [// {// expand: true,// cwd: '.tmp/concat/js',// src: '*.js',// dest: '.tmp/concat/js'// }// ]// }

// },    // Copies remaining files to places other tasks can use    copy: {      dist: {        files: [          {            expand: true,            dot: true,            cwd: '<%= xd.app %>',            dest: '<%= xd.dist %>',            src: [              '*.{ico,png,txt}',              '*.html',              'views/{,*/}*.html',              'lib/**/*',              'scripts/**/*',              'fonts/*',              'images/*'            ]          }        ]      },      styles: {        expand: true,        cwd: '<%= xd.app %>/styles',        dest: '.tmp/styles/',        src: '{,*/}*.css'      },      testfiles: {        files: [          { src: 'test/people.txt', dest: '/tmp/xd-tests/people.txt' }        ]      }    },    // Run some tasks in parallel to speed up the build process    concurrent: {      server: [        'copy:styles'      ],      test: [        'copy:styles'      ],      dist: [        // TODO: copy:styles copies .css files into .tmp        // TODO: hence probably not to include copy:styles in here.        // 'copy:styles'

10

Gruntfile.js

Page 11: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

require.config({  paths: {    domReady: '../lib/requirejs-domready/domReady',    angular: '../lib/angular/angular',    jquery: '../lib/jquery/jquery',    bootstrap: '../lib/bootstrap/bootstrap',    ngResource: '../lib/angular-resource/angular-resource',    uiRouter: '../lib/angular-ui-router/angular-ui-router',    cgBusy: '../lib/angular-busy/angular-busy',    ngGrowl: '../lib/angular-growl/angular-growl',    angularHighlightjs: '../lib/angular-highlightjs/angular-highlightjs',    highlightjs: '../lib/highlightjs/highlight.pack'  },  shim: {    angular: {      deps: ['bootstrap'],      exports: 'angular'    },    bootstrap: {      deps: ['jquery']    },    'uiRouter': {      deps: ['angular']    },

    'ngResource': {      deps: ['angular']    },    'cgBusy': {      deps: ['angular']    },    'ngGrowl': {      deps: ['angular']    },    'angularHighlightjs': {      deps: ['angular', 'highlightjs']    }  }});

define([  'require',  'angular',  'app',  './routes'], function (require, angular) {  'use strict';

  require(['domReady!'], function (document) {    console.log('Start angular application.');    angular.bootstrap(document, ['xdAdmin']);  });  require(['jquery', 'bootstrap'], function () {

    console.log('Loaded Twitter Bootstrap.');    updateGrowl();    $(window).on('scroll resize', function () {      updateGrowl();    });  });

  function updateGrowl() {    var bodyScrollTop = $('body').scrollTop();    var navHeight = $('nav').outerHeight();

    if (bodyScrollTop > navHeight) {      $('.growl').css('top', 10);    } else if (bodyScrollTop >= 0) {      var distance = navHeight - bodyScrollTop;      $('.growl').css('top', distance + 10);    }  }});

11

RequireJS main.js

Page 12: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

module.exports = function(config) {

  config.set({    // base path, that will be used to resolve files and exclude    basePath: '',

    // testing framework to use (jasmine/mocha/qunit/...)    frameworks: ['ng-scenario'],

    // list of files / patterns to load in the browser    files: [      'test/e2e/*.js',      'test/e2e/**/*.js'    ],

    // list of files / patterns to exclude    exclude: [],

    // web server port    port: 7070,

    // level of logging    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes    autoWatch: false,

    // Start these browsers, currently available:    // - Chrome    // - ChromeCanary    // - Firefox    // - Opera    // - Safari (only Mac)    // - PhantomJS    // - IE (only Windows)    browsers: ['PhantomJS'],

    // Continuous Integration mode    // if true, it capture browsers, run tests and exit    singleRun: true,

    // Uncomment the following lines if you are using grunt's server to run the tests    proxies: {        '/': 'http://localhost:8000/'    },    // // URL root prevent conflicts with the site root    urlRoot: '/_karma_/'  });};module.exports = function (config) {  'use strict';  config.set({    // base path, that will be used to resolve files and exclude    basePath: '',

    // testing framework to use (jasmine/mocha/qunit/...)    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser    files: [      'app/lib/angular/angular.js',      'app/lib/angular-mocks/angular-mocks.js',      'app/lib/angular-resource/angular-resource.js',      'app/lib/angular-cookies/angular-cookies.js',      'app/lib/angular-sanitize/angular-sanitize.js',      'app/lib/angular-route/angular-route.js',      'app/lib/angular-ui-router/angular-ui-router.js',      'app/lib/angular-growl/angular-growl.js',      'app/lib/angular-promise-tracker/promise-tracker.js',      'app/lib/angular-busy/angular-busy.js',      'app/scripts/*.js',      'app/scripts/**/*.js',      'test/spec/**/*.js',      'test/test-main.js'    ],

    // list of files / patterns to exclude

    exclude: [],

    // web server port    port: 7070,

    // level of logging    // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes    autoWatch: true,

    // Start these browsers, currently available:    // - Chrome    // - ChromeCanary    // - Firefox    // - Opera    // - Safari (only Mac)    // - PhantomJS    // - IE (only Windows)    browsers: ['PhantomJS'],

    // Continuous Integration mode    // if true, it capture browsers, run tests and exit    singleRun: false  });

12

karma.conf.js

Page 13: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Can we simplify this mess?

We must

13

Page 14: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

RaveJS

14

┏( ˆ◡ˆ)┛┗(ˆ◡ˆ )┓

https://github.com/RaveJS

Page 15: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

NO NO NO NO NO Rave JS is NOT a new framework

• …but it integrates with most (if not all)

RaveJS is NOT another {AMD|script|ES6} loader

• …but it is an ES6 loader extension with a built-in shim• Loads AMD, CommonJS, and (soon) ES6

• Loads other things via loader extensions

RaveJS is NOT ready for production, yet :(

• …but it is ready to play with

• Feedback and PRs welcome!

15

Page 16: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

RaveJS's goals in 3 bullets

Provide a default, instantly-runnable configuration

Make it easy to become sophisticated

Make it easy to assert your opinion

16

Page 17: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Provide a default, instantly-runnable configuration

No machinery or configuration (just a static web server)1. Download/install a Rave Starter (or start "from scratch")

2. Launch your favorite browser

3. Open your favorite editor or IDE

Run-time is responsive to environment1.Write code

2.Reload

3.Repeat

17

Page 18: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Make it easy to become sophisticated

CLI one-liner to switch mode

• Responsive / dev <--> Built / production

• Easily switch back

• Still zero configuration!

CLI one-liner to launch tests

• Unit tests, integration tests, push to CI

18

Page 19: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Make it easy to assert your opinion

Add microlibs, frameworks, third-party integrations

• e.g. Knockout-Backbone

Add capabilities: loader extensions, shims

• e.g. JSON loader, WebComponents shim

Install build, deploy, and testing patterns (SPA is default)

• Spring, JEE, Rails

• Buster, Karma

19

Page 20: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

How?Metadata

20

Page 21: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Metadata all the things!

Provide default, minimal metadata out of the box

Allow devs to generate metadata naturally

• bower install --save

• npm install --save

Allow third parties to provide metadata

• Rave Integration Extensions• bower install --save awesome-third-party-integration-package

• Rave Starters

21

Page 22: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Rave Extensions

Add microlibs, frameworks, third-party integrations

• bower install --save rave-knockout-backbone

Add capabilities: loader extensions, shims

• npm install --save rave-load-css• bower install --save rave-polymer

Install build, deploy, and test patterns (SPA is default)

• bower install --save-dev rave-spring-boot• bower install --save-dev rave-buster

22

Page 23: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

To CLI or not to CLI?

Rave CLI

• rave install <package-on-bower-or-npm>• Finds best package for your app, invokes --save (biggest newb mistake)

• rave unbuild• Uses grunt or gulp (or both!) automatically

Familiar, established CLIs

• npm install --save <package>• npm test• gulp rave --unbuild• grunt rave --test

23

Page 25: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/25

Rave is a Work in Progress

ASAP Summer 2014 Fall 2014

• Testing patterns• Even more extensions

and patterns• Showcase/directory of

community Rave Extensions?

• ES6 module syntax**• IE8+ compatibility** • AngularJS 1.3

extensions and patterns**

• Spring, JEE patterns• Minification

• Bower*, npm*• AMD*, node*• Text*, CSS*, JSON*• cujoJS extensions*• Default build & deploy

patterns**

*done! **in progress

Page 26: Introducing RaveJS: Zero-config JavaScript applications

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under aCreative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Questions?

John Hann, JavaScript Barbarian, Pivotal@unscriptable