Upload
john-hann
View
1.926
Download
2
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Demo
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/
Zero config!
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
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