Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Entwicklung moderner Web-Apps mit HTML5 und JavaScript

Entwicklung moderner Web-Apps mit HTML5 und JavaScript

Thorsten Rinne

March 05, 2014
Tweet

More Decks by Thorsten Rinne

Other Decks in Programming

Transcript

  1. • Browser • Yeoman = Bower + Grunt + Awesomeness

    • HTML5 und JavaScript APIs • Unsere Web App • Tipps & Tricks
  2. Welche Versionen? • Chrome latest (derzeit Version 32) • Chromium

    latest (derzeit Version 34) • Firefox latest (derzeit Version 27) • Firefox Nightly latest (derzeit Version 30) • Safari latest (derzeit Version 6.1 bzw 7) • Opera kann man sich sparen, da wie Chrome
  3. • Internet Explorer 7 (??) • Internet Explorer 8 (?)

    • Internet Explorer 9 • Internet Explorer 10 (?) • Internet Explorer 11
  4. The JavaScript Task Runner • aufgabenbasiertes Kommandozeilen-Tool • ähnlich make

    / rake / ant / phing • Konfiguration in JavaScript • Große Community • Hunderte Plugins • Linting, Concat, Watcher, Testing out of the box
  5. package.json { "name": „chat.js", "version": "1.0.0", "dependencies": {}, "devDependencies": {

    "grunt": "~0.4.1", "grunt-contrib-jshint": "~0.4.1", "grunt-contrib-uglify": "~0.2.2" }, "engines": { "node": ">=0.10.0" } }
  6. Gruntfile.js module.exports = function(grunt) { ! grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify:

    { options: { banner: '/*! <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); ! grunt.loadNpmTasks('grunt-contrib-uglify'); ! grunt.registerTask('default', ['uglify']); ! };
  7. Grunt Tasks // Run Jasmine and DalekJS tests grunt.registerTask(
 'testrun',


    ['jshint', 'jasmine', 'dalek'] ); ! // Build production grunt.registerTask(
 'production', ['copy', 'less', 'cssmin', 'jshint', 'uglify'] );
  8. LiveReload • Plugin • Chrome • Firefox • Safari •

    Triggert Seitenreload via grunt watch • Browser Extensions auf http://livereload.com/
  9. Package Manager für das Web • Installieren und Entfernen von

    Paketen • Keine Abhängigkeiten • keine sudo Rechte nötig • Schnell installiert:
 
 $ npm install bower -g
  10. Pakete installieren $ bower install $ bower install <package> $

    bower install <package>#<version> $ bower install <name>=<package>#<version>
  11. Paket-Quellen • Registrierte Bower-Pakete wie z.B. jQuery • Git-Repositories •

    Lokale Ordner • URLs mit .zip/.tar.gz Dateien • Werden normal nach bower_components installiert
  12. Pakete suchen $ bower search angular Search results: ! angular

    git://github.com/angular/bower-angular.git angular-mocks git://github.com/angular/bower-angular-mocks.git angular-resource git://github.com/angular/bower-angular-resource.git angular-scenario git://github.com/angular/bower-angular-scenario.git angular-cookies git://github.com/angular/bower-angular-cookies.git angular-sanitize git://github.com/angular/bower-angular-sanitize.git angular-bootstrap git://github.com/angular-ui/bootstrap-bower.git
  13. Konfiguration bower.json {
 "name": "yatego.com",
 "version": "2.0.0",
 "dependencies": {
 "jquery":

    "1.10.2",
 "bootstrap": "3.0.0",
 "modernizr": "2.6.2"
 },
 "devDependencies": {
 "jasmine": "~1.3.1", },
 "resolutions": {
 "jquery": "1.10.2"
 }
 }
  14. Yeoman • Scaffolding neuer Apps • Schreibt Grunt Konfiguration •

    Yeoman = Grunt + Bower + Awesomeness • über 500 Generatoren • Installation
 
 $ npm install -g yo

  15. Yeoman $ npm install -g generator-webapp
 
 $ cd /path/to/webroot


    
 $ mkdir jsdays-app
 
 $ cd jsdays-app
 
 $ yo webapp

  16. Generator WebApp • Watcher für HTML, CSS und JS mit

    LiveReload • Builtin Webserver auf Port 9000 • JSHint • Mocha-Tests • Bootstrap 3
  17. Verfügbare Generatoren • AngularJS • Bootstrap • WordPress • EmberJS

    • Firefox OS Apps • ExpressJS • Laravel • Knockout • Jekyll • Phonegap • Meteor • Symfony2
  18. Struktur • Frontend • JavaScript • LESS / CSS •

    Media • Tests • Backend • MVC • Templates • Routes • Tests
  19. JavaScript API • FullScreen API • Forms • Webworkers •

    Geolocation • Storage • Offline Application
  20. var elem = $('#content')[0]; if (elem.requestFullscreen) { elem.requestFullscreen(); } else

    if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); } else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(); } Full Screen
  21. • Bitte mit Vorsicht verwenden • Styling für z.B. Hintergrund:

    • -webkit-full-screen • -moz-full-screen Full Screen
  22. Progress var interval = setInterval(function () { var progress =

    $('progress'); ! if (progress.val() < progress.attr('max')) { progress.val(progress.val() + 1); } else { clearInterval(interval); } }, 10);
  23. output $('#output').on('input', function () { var nr1 = parseInt($('#nr1').val()); var

    nr2 = parseInt($('#nr2').val()); $('output').val(nr1 + nr2); }); Element zur Ausgabe von Berechnungen
  24. Input Types • Viele Aufgaben, die bisher mit JavaScript erledigt

    wurden, funktionieren jetzt mit HTML5 nativ • Können (kaum) angepasst werden
  25. Input types • tel • search • url • email

    • date • month • week • time • number • range • color
  26. Attribute • autofocus • placeholder • form • required •

    autocomplete • pattern • dirname • novalidate • formaction • formenctype • formmethod • formnovalidate • formtarget
  27. Webworker • Workerthreads im Browser • Rechenintensive Prozesse auslagern •

    Zugriff auf: navigator, location, XMLHttpRequest,... • Kein Zugriff auf: DOM, window, document, parent
  28. Webworker var i, n = 1, results = 1; outerLoop:

    while (true) { n += 1; for (i = 2; i <= Math.sqrt(n); i += 1) { if (n % i === 0) { continue outerLoop; } } self.postMessage(n); results += 1; if (results >= 1000) { self.close(); } }
  29. Websockets • Bidirektionale Kommunikation zwischen Client und Server • Protokoll

    auf TCP-Basis • Eventbasiert • Sichere Variante wss://
  30. Websockets var addr = 'ws://localhost:8181/'; var socket = new WebSocket(addr,

    'myapp'); ! $('#sayHello').on('click', function () { socket.send('Hello Server'); }); ! socket.onmessage = function (msg) { $('#response').html(msg.data); }; !
  31. var WebSocketServer = require('websocket').server; var http = require('http'); var server

    = http.createServer().listen(8181); wsServer = new WebSocketServer({ httpServer: server, autoAcceptConnections: false }); wsServer.on('request', function(req) { var connection = req.accept('myapp', req.origin); ! connection.on('message', function(message) { connection.sendUTF("Hello Client!"); console.log(message.utf8Data); }); });
  32. Geolocation var geolocation = navigator.geolocation; ! geolocation.getCurrentPosition(function (pos) { var

    posString = 'Lat: ' + pos.coords.latitude + ' Long: ' + pos.coords.longitude; ! $('#position').html(posString); });
  33. <!DOCTYPE html> <html> <head> </head> <link href="//developers.google.com/maps/ documentation/javascript/examples/default.css" rel="stylesheet"> <script

    src="//maps.googleapis.com/maps/ api/js?v=3.exp&sensor=false" /> <script src="/js/geolocation2.js" /> <body> <div id="map-canvas"></div> </body> </html>
  34. function initialize() { ! navigator.geolocation.getCurrentPosition(function (pos) { var myLatlng =

    new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude); var mapOptions = { zoom: 4, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions); ! var marker = new google.maps.Marker({ position: myLatlng, map: map, title: 'Hello World!' }); }); } ! google.maps.event.addDomListener(window, 'load', initialize);
  35. Storage • Local Storage - zeitlich unbegrenzt • Session Storage

    - nur für eine Browser-Session • IndexedDB • Web SQL
  36. <div> Items in Storage: &nbsp;<span id="itemCount"></span> </div> <table id="content"> <thead>

    <tr><th>key</th><th>value</th><th></th></tr> </thead> <tbody></tbody> </table> <div id="add"> <div> <label class="control-label">key:</label> <input id="storageKey"> </div> <div> <label class="control-label">value:</label> <input id="storageVal"> </div> <div> <button id="save">OK</button> </div> </div>
  37. var writeLine = function (k, v) { var line =

    '<tr><td>' + k + '</td><td>' + v + '</td><td><button data-value="' + k + '">delete' + '</button></td></tr>'; ! $('#content tbody').append(line); writeStorageLength(); }; ! ! for (var i = 0; i < localStorage.length; i++) { k = localStorage.key(i); v = localStorage.getItem(k); writeLine(k, v); }
  38. var writeStorageLength = function () { $('#itemCount').html(localStorage.length); }; $('#save').on('click', function

    () { var k = $('#storageKey').val(); var v = $('#storageVal').val(); localStorage.setItem(k, v); writeLine(k, v); }); ! $('#content').on('click', function (e) { localStorage.removeItem((e.target). data('value')); $(e.target).closest('tr').remove(); writeStorageLength(); });
  39. Offline Application • Dateien werden nur einmalig vom Server geholt

    • Manifestdatei enthält die Konfiguration
  40. Offline Application CACHE MANIFEST index.html ! js/articles.js js/customers.js js/init.js js/jquery.js

    js/orders.js ! css/bootstrap.css?v=1 ! NETWORK: orders offline.manifest
  41. Creating Application Cache with manifest http:// localhost:8080/offline.manifest Application Cache Checking

    event Application Cache Downloading event Application Cache Progress event (0 of 7) http:// localhost:8080/js/customers.js Application Cache Progress event (1 of 7) http:// localhost:8080/css/bootstrap.css?v=1 Application Cache Progress event (2 of 7) http:// localhost:8080/js/jquery.js Application Cache Progress event (3 of 7) http:// localhost:8080/js/articles.js Application Cache Progress event (4 of 7) http:// localhost:8080/index.html Application Cache Progress event (5 of 7) http:// localhost:8080/js/init.js Application Cache Progress event (6 of 7) http:// localhost:8080/js/orders.js Application Cache Progress event (7 of 7) Application Cache Cached event
  42. CSS LEVEL 3 • In der Entwicklung seit 2000 •

    Modularer Aufbau • Bekannte Module • Selectors Level 3 • Media Queries
  43. Box Shadow .shadow { -webkit-box-shadow: 
 2px 2px 2px 2px

    rgba(0, 0, 0, 1); box-shadow: 
 2px 2px 2px 2px rgba(0, 0, 0, 1); }
  44. Media Queries @media (min-width: 1200px) {
 ... } @media (min-width:

    768px) and (max-width: 979px) { ... } @media (max-width: 767px) {
 ... } @media (max-width: 480px) {
 ... }
  45. Selektoren Level 3 • a[src^="https"]
 Jedes <a> Element, dessen src-Attribut

    mit https beginnt • a[src$=".pdf"]
 Jedes <a> Element, dessen src-Attribut mit .pdf endet • a[src*="jsdays"]
 Jedes <a> Element, dessen src-Attribut mit jsdays beinhaltet
  46. Selektoren Level 3 • p:nth-child(2n)
 Jedes 2. <p> Element seines

    Elternelements • :root
 Das Rootelement eines Dokuments • :empty
 Jedes Element ohne Kindelemente
  47. Selektoren Level 3 • input:enabled
 Jedes aktive <input> Element •

    input:disabled
 Jedes nicht aktive <input> Element • input:checked
 Jedes „ge-checkte“ <input> Element (Checkbox)
  48. Modulloader • define: Wenn man ein Modul erstellen möchte, auf

    das weitere Module aufbauen • require: Wenn man Dinge laden und verwenden möchte
  49. Strict Mode - Mehr Fehler • Keine versehentlichen globals (ReferenceError)

    • Schärfere Regeln bei Zuweisungen • Non-writable, getter-only, neue Properties bei non-extensible Objekten • Kein Löschen von nicht löschbaren Eigenschaften (prototype) • Eindeutige Propertynamen • Eindeutige Namen für Argumente (function (a, a, b)...) • Keine Oktalnotation (z.B. 012 - SyntaxError)
  50. Strict Mode Einfachere Benutzung • “with” ist verboten • (var

    x = 1; with (obj) { x};) • Keine neuen Variablen mit “eval” • eval(“var x”); • Keine Variablen löschen • var x = 123; delete x;
  51. Strict Mode Eval & Arguments • eval und arguments können

    nicht mehr mit anderen Werten belegt oder an einen Kontext gebunden werden • arguments kann nicht mehr durch Aliases verändert werden • function func(arg) { var arg = 15; return [arg, arguments[0]]}; • arguments.callee existiert nicht mehr - TypeError
  52. Strict Mode Sicherheit • Kein Zugriff mehr auf das globale

    Objekt aus Funktionen • function f() { return this; } - undefined • Kein Zugriff auf func.arguments und func.caller von außerhalb • Kein Zugriff auf Variablen in einer Funktion von außerhalb
  53. Strict Mode • Reservierte Wörter: implements, interface, let, package, private,

    protected, public, static, und yield • Keine Funktionsdefinition in Bedingungen und Schleifen
  54. Object.* • Object.seal(obj)/Object.isSealed(obj) • Keine Änderungen mehr an Eigenschaften •

    Object.freeze(obj)/Object.isFrozen(obj) • Keine Schreibzugriffe mehr auf Eigenschaften + seal
  55. Object.* • Object.defineProperty • set: magic setter function • get:

    magic getter function • value: default value • configurable: can be deleted • enumerable: can be iterated • writable: can be changed
  56. package.json { "name": "chat.js", "version": "1.0.0", "dependencies": { "express": "~3.4.8",

    "express-hbs": "~0.7.9", "socket.io": "~0.9.x" }, "repository": { "type": "git", "url": "git://github.com/thorsten/chat-js.git" } }
  57. socket.io var http = require('http'); var server = http.createServer(app); server.listen(8080);

    var io = require('socket.io').listen(server); ! io.sockets.on('connection', function (socket) { ! socket.on('msg', function(message) { console.log(message); }); ! });
  58. script(src="http://localhost:3000/socket.io/ socket.io.js") var socket = io.connect('http://localhost:3000'); ! $('#chat').on('submit', function (e)

    { e.preventDefault(); var value = $('#message').val(); $('#message').val(''); $('#message').focus(); $('#messages').append(value + '<br />'); ! socket.emit('msg', value); return false; });
  59. Bootstrap • Scaffolding (Grid, Layout, Responsive) • Base CSS (Buttons,

    Forms, Tables) • Components (Navigation, Alerts, Pagination) • JavaScript (Modal, Tooltip)
  60. LESS: Nested Rules #head { background-color: @dark; height:25px; div {

    color: @light; background-color: @dark; &:hover { background-color: @light; color: @dark; } } }
  61. .rounded-corners (@radius: 10px;) { -webkit-border-radius: @radius; -moz-border-radius: @radius; border-radius: @radius;

    } ! #info { .rounded-corners(5px); width: 250px; margin: 10px; padding-left: 5px; background-color: lightgreen; } LESS - Mixins
  62. Performance-Messung • Übersicht des Speicherverbrauchs • Hilft bei Suche nach

    Performanceproblemen • Layout oder Skripte • Ziel: 60 Frames pro Sekunde :-)
  63. Memory und DOM Leaks • JavaScript CPU Profiling • Heap

    Snapshot für • JavaScript Objekte • DOM Knoten • Suche nach potentiellen Memory und DOM Leaks
  64. Mobile Testing • User Agent • Verschiedene Endgeräte • Android

    • iOS • Windows Phone • Simulation von Touch Events • Ändern der Geolocation und des Accelerometers
  65. Frameworks • Bootstrap • Ratchet v2 • Foundation v3 •

    Foundation v4 • Skeleton • 960.gs • http://responsive.vermilion.com/compare.php
  66. Kontakt Thorsten Rinne! [email protected] ! Yatego GmbH Kobellstr. 15 80336

    München Deutschland ! @ThorstenRinne ! https://github.com/thorsten Sebastian Springer! sebastian.springer@mayflower.de ! Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland ! @basti_springer ! https://github.com/sspringer82