Top Banner
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
26

Introducing RaveJS: Zero-config JavaScript applications

Dec 05, 2014

Download

Technology

John Hann

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
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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