headquarter
Frontend-Entwicklung mit JavaScript Single Page Applications Server-Side HTML Rendering Client-Side HTML Rendering kein JavaScript wenig JavaScript nur JavaScript
Der Browser bietet viele neue JavaScript APIs, z.b. Geolocation, Web Storage, Indexed DB, WebGL, WebSocket, HTML Canvas JavaScript ist viel performanter geworden Anzahl an JavaScript-Frameworks ist stark gestiegen Dadurch ergeben sich viele neue Möglichkeiten, allerdings hat JavaScript Schwächen, z.b. dynamische Typisierung => schlechtes Tooling keine Packages/Assemblies oder Namensräume=> Wie strukturiere ich meinen Code?
Ziel des Vortrags Überblick über Frameworks und Tools, die den Umgang mit JavaScript erleichtern.
NodeJS Plattform um JavaScript-Code außerhalb des Browsers auszuführen Basiert auf Googles JavaScript-Runtime V8 Wird hauptsächlich genutzt um Web-Server zu realisieren, aber auch um Desktop-Anwendungen zu entwickeln (node-webkit) und als Unterstützung bei der Entwicklung mit Web-Technologien
NPM Package Manager für NodeJS NPM = Node Package Manager Wird über die Kommandozeile angesteuert, z.b. $ npm install jquery um jquery zu installieren. Abhängigkeiten von Packages werden dabei auch installiert. Eigene Packages können erstellt werden, in dem eine package.json-datei erstellt wird, $ npm init hilft dabei. Abhängigkeiten von Packages werden dort definiert => Abhängikeiten müssen nicht eingecheckt werden
Bower Package Manager für das Web Es werden keine Abhängigkeiten der Packages installiert Abhängigkeiten der Packages müssen selber verwaltet werden => besser für das Web $ npm install g bower $ bower install knockout --save
Demo NPM & Bower
Modularisierung von JavaScript In JavaScript gibt es keine Packages/Assemblies und Namensräume => keine Möglichkeit Code vernünftig zu strukturieren Closure: var Helper; (function (Helper) { function pluralize(count, word) { return count === 1? word : word + 's'; } Helper.pluralize = pluralize; })(Helper (Helper = {})); Helper.pluralize(3, 'User'); // 'Users'
JavaScript Module Loader Common JS synchron NodeJS AMD (Asynchronous Module Definition) asynchron RequireJS ECMAScript 6 synchron und asynchron
Beispiel Common JS // Person.js function Person(firstName, lastname) { this.firstname = firstname; this.lastname = lastname; } Person.prototype.getFullName = function() { return this.firstname + ' ' + this.lastname; } module.exports = Person; // App.js var Person = require('./person'); var person = new Person('Max','Mustermann');
Beispiel AMD define(['jquery', 'moment'], function($, moment) { return function(element) { var m = moment($(element).data('time')); $(element).text(m.fromnow()); } });
Require JS Beispiel RequireJS <script src="/bower_components/requirejs/require.js" data-main="js/main.js"></script> require.config({ paths: { 'jquery': '/bower_components/jquery/dist/jquery', 'moment': '/bower_components/moment/moment' } }); Require JS Optimizer Fasst Module in einer Datei zusammen => der Browser muss nur eine Datei herunterladen In JavaScript geschrieben
Demo RequireJS
Browserify $ npm install g browserify Ermöglicht NodeJS-Module im Browser zu nutzen, in dem alle Module in einer Datei zusammengefasst werden $ browserify main.js d o bundle.js Erleichtert Debugging vom Code durch Source Maps
Demo Browserify
JavaScript Task Runner Warum? => Automatisierung Kompilieren Komprimieren Bundling Unit Tests Synchronisation mit Browser GruntJS eher deskriptiv (Konfiguration) sehr viele Plug-Ins gruntfile.js GulpJS Code statt Konfiguration NodeJS Streams => sehr schnell viele Plug-Ins gulpfile.js
Beispiel GulpJS var gulp = require('gulp'); var less = require('gulp-less'); gulp.task('less', function () { gulp.src('./less/**/*.less').pipe(less()).pipe(gulp.dest('./out/css')); });
Demo GulpJS
Browser Sync Entwickeln für das Web erfordert viel Testen und Optimieren Responsive Design Viele verschiedene Browser, auch auf mobilen Geräten Browser Sync aktualisiert Web-Seite automatisch, sobald Änderungen am Code gemacht werden Funktioniert mit mehreren Browsern gleichzeitig
Demo Browser Sync
MVVM Frameworks UI-Logik wird in Model, View und View-Model eingeteilt View-Model und View werden synchronisiert (Data-Binding in zwei Richtungen) Data-Binding wird im HTML definiert AngularJS Google Single Page Application Framework: z.b. Data-Binding, Routing, Dependency Injection Dirty Cheking EmberJS Single Page Application Framework: z.b. Data-Binding, Routing Observables KnockoutJS Kein Single Page Application Framework: nur Data-Binding Observables
Beispiel KnockoutJS <input type="text" data-bind="value: message, valueupdate: 'keydown'" /> <button data-bind="click: send, enable: cansend">senden</button> function ViewModel() { this.message = ko.observable(''); this.send = function() { alert(this.message()); } this.cansend = ko.computed(function() { return this.message().length > 0; }.bind(this)); } ko.applybindings(new ViewModel(), document.body);
Beispiel AngularJS <main ng-controller="maincontroller as main"> <input type="text" ng-model="main.message" /> <button ng-disabled="main.isdisabled()" ng-click="main.send()">senden</button> </main> angular.module('myapp',[]).controller('maincontroller', MainController); function MainController() { this.message = ''; } MainController.prototype.send = function() { alert(this.message); } MainController.prototype.isDisabled = function() { return this.message === ''; }
ReactJS Facebook, kein Single Page Application Framework, kein MVVM Wie funktioniert ReactJS? Alles ist eine Komponente Jede Komponente kann in einer anderen wiederverwendet werden Jede Komponente hat eine render -Funktion Das Rendern funktioniert wie Server-seitiges HTML-Rendering (kein Two-Way Data-Binding) Komplette Bereiche einer Seite werden neu gerendert Ist das performant? Ja, da nicht direkt HTML gerendert wird, sondern ein virtuelles Document Object Model (Virtual DOM), dieses wird mit dem alten verglichen und nur die Unterschiede werden auf das echte DOM übernommen
Beispiel Virtual DOM Vorher: <ul> <li class="selected">walter White</li> <li>jesse Pinkman</li> <li>hank Shrader</li> </ul> Nachher: <ul> <li>walter White</li> <li class="selected">jesse Pinkman</li> <li>hank Shrader</li> <li>gustavo Fring</li> </ul> Änderungen: list.childnodes[0].classname = null; list.childnodes[1].classname = 'selected'; var item = document.createelement('li'); item.innertext = 'Gustavo Fring'; list.appendchild(item); DOM ist Flaschenhals bei der Performance, JavaScript selber ist mittlerweile sehr schnell!
Beispiel ReactJS var Counter = React.createClass({ getinitialstate: function() { return { count: 0 }; }, getdefaultprops: function() { return { step: 1 }; }, onclick: function() { this.setstate({ count: this.state.count + this.props.step }); }, render: function() { return React.DOM.button({onClick: this.onclick}, 'Count: ', this.state.count); } }); React.renderComponent(Counter({step: 3}), document.body);
JSX var Counter = React.createClass({ getinitialstate: function() { return { count: 0 }; }, getdefaultprops: function() { return { step: 1 }; }, onclick: function() { this.setstate({ count: this.state.count + this.props.step }); }, render: function() { return <button onclick={this.onclick}>count: {this.state.count}</button>; } }); React.renderComponent(<Counter step={3} />, document.body);
ReactJS Demo
Vorteile von ReactJS gegenüber MVVM Setzt auf schon existierende Konzepte aus JavaScript, statt auf UI-Logik in HTML z.b. $scope, ng-repeat in AngularJS oder foreach-binding in KnockoutJS es müssen keine neuen Konzepte gelernt werden leichtgewichtig Entwicklungsumgebungen müssen kein zusätzliches Tooling für das Framework bereitstellen So einfach wie Server-seitiges Rendern Funktioniert sehr gut mit anderen Frameworks zusammen Funktioniert mit älteren Browsern UI kann auch Server-seitig gerendert werden
TypeScript Microsoft / Anders Hejlsberg (C#) Skalierbare Entwicklung von JavaScript Anwendungen Erweitert JavaScript um optionale statische Typisierung Kompiliert nach JavaScript, Typisierung fällt einfach weg Jeder JavaScript-Code ist valider TypeScript-Code Erlaubt vorhandene JavaScript-Bibliotheken nachträglich zu typisieren Folgt ECMAScript 6 Standard Debugging / Unterstützung von Source Maps Open Source / Compiler in TypeScript geschrieben Visual Studio / WebStorm / SublimeText / Eclipse
TypeScript Demo GulpJS RequireJS / AMD ReactJS react-router RefluxJS TypeScript Visual Studio ASP.NET Web API
LMIS AG Neumarkt 1 49074 Osnabrück Tel.: +49 541 200 690-0 Fax: +49 541 200 690-499 E-Mail: info@lmis.de Web: www.lmis.de Handelsregister: Amtsgericht Osnabrück, HRB 19316, Ust.-Id.-Nr.: DE211909662 Vorstand: Axel van Lil, Marco Barenkamp (Vorsitzender)