Archive for the ‘Javascript’ tag
HTML 5 und Javascript 5: Clientseitige Datenbanken
Nachdem sich die Web Hypertext Application Technology Working Group (WHATWG) 2004 gegründet hat, die aus einigen bedeutenden Internet-Riesen besteht (u.a. Apple, Mozilla, Opera), kommt wieder Fahrt in neue HTML- und Javascript-Standards. Die Gruppe hat viele Proposals erstellt, von denen jetzt einige vom W3C übernommen werden. Stichworte sind da HTML 5, ECMAScript 5, Web Workers, Web Storage, Web Sockets und einiges mehr.
Zu den Web Workern hatte ich ja bereits etwas geschrieben.
Web Sockets wird die Pushing-Technik werden, mit der Server bei Änderungen Nachrichten an den Browser schicken können, dann erübrigt sich das derzeitige Pullen und Nachfragen via AJAX, ob es Neuigkeiten gibt. Das entlastet die Server und spart Traffic, und Nachrichten kommen genau dann im Browser an wenn sie auf dem Server passieren, nicht erst beim nächsten Pull.
Heute soll es um den Web Storage gehen, die clientseitige Datenbank im Browser. In der Vergangenheit konnte man Daten nur auf der aktuellen Seite in Javascript-Variablen vorhalten, sobald aber der nächste Full-Page-Reload kommt sind die Daten futsch. Die zweite Möglichkeit waren Cookies, in denen man Daten speichern kann. Da aber Cookies bei jedem Request mitgesendet werden, ist das kein guter Speicherort für größere Datenmengen, Cookies sollte man höchstens für eine SessionID nutzen.
XSS-Angriffe erschweren mit CSP, der neuen Idee von Mozilla/Firefox
Die Entwickler bei Mozilla haben hart gearbeitet und sich eine gute Strategie ausgedacht, wie man in Zukunft Cross-Site-Scripting (XSS) erschweren kann (Achtung: unterbinden wird man es (noch) nicht können!). Viele Browserhersteller loben die Firefox-Entwickler dafür und werden die Funktionalität auch einbauen, um das Web ein wenig sicherer zu machen.
XSS ist im Grunde das böse Einfügen von externem Javascript-Code, um im Kontext einer Webseite schädliche Funktionen aufzurufen. XSS-Angriffe haben in den letzten Jahren massiv zugenommen und sind mittlerweile auf Platz 1 der Hitliste aller Internet-Angriffe. Ein einfaches Beispiel ist das folgende:
Nehmen wir an, wir haben ein Gästebuch (oder ein Blog, einen Chat oder irgendeinen anderen Web 2.0 Dienst erstellt, wo User eigenen Content beisteuern können) programmiert, und wir haben bei der Programmierung nicht aufgepasst. Nehmen wir an, wir hätten auf Serverseite bei irgendeinem Formular-Script das Entschärfen der POST-Variablen vergessen, sodass alles, was ein User im Formular eingibt, später auf der Seite von anderen Usern gelesen werden kann.
Javascript Web Worker
Ergänzend zu einem älteren Artikel über Google Gears hier eine kurze Statusmeldung: Mittlerweile sind die modernen Browser (zur Zeit Firefox 3.5, Safari 4 und Google Chrome) in der Lage, die Funktionalität der Worker auch ohne das Gears-Plugin anzubieten, sodass man auf eine große Anzahl an Nutzern zurückgreifen kann. Wir werden also in Zukunft vermehrt tolle Seiten mit vielen Effekten und Funktionalitäten sehen, und vielleicht ja auch selbst entwickeln.
Weitere Infos bietet die Suchmaschine eurer Wahl. Einfach nach „Javascript Web Worker“ suchen, es gibt bereits einige Beispiele und auch den Draft, der diese Technik hoffentlich bald zum Standard macht.
Verteiltes Rechnen mit Javascript und Google Gears
Wie ich ja bereits des öfteren anmerkte, habe ich früher ein Browsergame programmiert. Begonnen habe ich 2003, als es erst recht wenige Browsergames gab, und diese auch alle von Privatleuten als Hobby betrieben wurden. Da man natürlich Alleinstellungsmerkmale braucht gegen „die Konkurrenz“, baut man viele Ideen ein, die andere nicht haben. Unter anderem war in meinem Browsergame (es handelte sich um ein Aufbauspiel a la OGame, Stoneage etc.) das erste Mal auch ein Turniermodus (1on1) möglich, so dass man abseits der lang laufenden Welten auch in einem KO-Modus gegen andere antreten konnte. Dazu wurden Speed-Server für die ausgelosten Paare gestartet, wo dann 2 Spieler gegeneinander antreten mussten und gewisse Siegbedingungen erreichen mussten. ICQ-Benachrichtigungen bei bestimmten Ereignissen hatte ich auch recht früh eingebaut.
In der folgende Version (die leider nie das Licht der Welt erblickt hat) kamen noch viele weitere interessante Features hinzu. Der Quellcode wurde komplett neu geschrieben in PHP5, war nun voll objektorientiert (in PHP4 war das ja nur sehr beschränkt möglich), und auch neue „Web2.0“ Funktionalitäten waren mit drin.
So gab es zum Beispiel eine Möglichkeit, dass Spieler sich selbst Weltkarten zusammenbauen konnten mit einem einfachen Editor. Der Spieler hat dazu mehrere Feldtypen (Gras, Fels, Wasser, Berg, Moor) und kann daraus eine Karte basteln, auf der er dann gegen andere antreten kann (und wenn sie gut bewertet wird, kann es auch eine Karte für einen „großen“ Server werden, wo tausende Spieler drauf spielen). Eines der Probleme, die es dabei gab, war die Berechnung der Wege. Man muss, um seine Armee zu bewegen, nur das Zieldorf anwählen und kann dort angreifen. Der Dijkstra-Algorithmus bestimmt dann die Zeit, die die Armee unterwegs ist. Dazu muss man den genauen Weg kennen, denn es gibt auch unpassierbares Gelände (in diesem Fall Berge) oder Flächen, auf denen die Armee langsamer ist (Moor). Da die Karten mitunter sehr groß sind (zB 1000*1000), dauert diese Berechnung recht lang. Diese Berechnung bei jeder Armeebewegung zu machen macht die Webseite ziemlich lahm. Also habe ich für die „Standardkarten“ diese Berechnungen bereits erledigt und die 500.000 Ergebnisse (von jedem Feld zu jedem anderen) in einer Datenbank gespeichert.
Wenn nun aber viele Spieler neue Karten basteln, schafft das der Server nicht mehr, er muss ja auch nebenbei noch für die eigentlichen Webseiten und Datenbanken herhalten. Eine Berechnung für eine Karte dauert mitunter 20 Stunden (Dijkstra Algorithmus in PHP).
Was also tun? Richtig, wir verteilen die Arbeit auf die Client-Rechner. Die 500 Spieler, die auf der Webseite rumsurfen und das Spiel spielen, können nebenbei auch bei der Berechnung helfen. Doch wie macht man das? Aufwendige Dinge wie ein eigenes Client-Programm schreiben, oder Plugins für BOINC etc. sind zu aufwändig und übertrieben. Wie so häufig gibt es eine einfache Lösung: Gears von Google.
Mit Gears kann man asynchron Javascripte ausführen, die die Webseite nicht beeinträchtigen, indem man sogenannte WorkerPools mit Arbeit versorgt.
Hier habe ich mal ein einfaches Beispiel:
main.html
<script type="text/javascript" src="gears_init.js"></script> <script type="text/javascript"> var workerPool = google.gears.factory.create('beta.workerpool'); workerPool.onmessage = function(a, b, message) { alert('result from worker ' + message.sender + ': \n' + message.body); }; var childWorkerId = workerPool.createWorkerFromUrl('worker2.js'); workerPool.sendMessage([5, 1, 8], childWorkerId); </script>
worker2.js:
var wp = google.gears.workerPool; wp.onmessage = function(a, b, message) { // do calculation here var reply = message.body[0] + message.body[1] + message.body[2]; wp.sendMessage(reply, message.sender); }
Wenn man die entsprechende Webseite aufruft, wird man gefragt, ob der Zugriff auf Gears erlaubt werden soll. Wenn man Gears installiert hat, kann man also noch von Fall zu Fall unterscheiden, ob man der Webseite seine Resourcen zur Verfügung stellen möchte oder nicht.
Was passiert nun? Die Webseite startet einen WorkerPool, in diesem Workerpool wird ein Worker gestartet, der das Script worker2.js ausführen soll. Wir senden an den darin befindlichen Worker ein Array mit 3 Zahlen.
Der Worker errechnet dann die Summe dieser Zahlen, und sendet das Ergebnis zurück an den WorkerPool. Diese Nachricht fangen wir mit dem „onMessage“ Eventhandler ab und zeigen das Ergebnis mittels alert() an.
Wie würde nun die Kartenberechnung funktionieren? Wir übergeben statt dem einfachen Array ein komplexes großes Array mit dem Graphen, den Kantengewichten usw. Im Worker findet dann die eigentliche Dijkstra-Berechnung statt. Dort wäre es sinnvoll, nicht die ganze Karte zu berechnen (Dauer 20 Stunden), sondern nur kleine Häppchen, die in wenigen Sekunden bearbeitet sind. Statt das Ergebnis dann via alert() auszugeben, schicken wir es via AJAX zurück an den Webserver, der das Ergebnis in die Datenbank einträgt.
Leider ist es bei diesen ersten Tests geblieben, ich habe die eigentlichen umfangreichen Dijkstra-Berechnungen nie in Javascript mit Gears umgesetzt. Aber möglich ist es.
Eine einzige Hürde gibt es: Auf dem Clientrechner muss Gears installiert sein. Mit einer guten Community und Nutzern, die einem vertrauen, ist aber auch das machbar.
Alternativ kann man natürlich auch ohne Gears die Berechnungen in Javascript durchführen lassen. Dabei muss man jedoch beachten, dass der Browser dadurch nicht unbenutzbar wird. Man muss also die Berechnung künstlich bremsen, außerdem muss man eine Lösung dafür finden, dass der Browser lang laufende Javascripte gern auch mal abbrechen möchte.
Mit Gears passiert sowas nicht.
Anwendungsfälle des Dijkstra-Algorithmus sind beispielsweise das bekannte „Friend of a Friend“ Problem (soziale Netzwerke zeigen an, über wieviele Kontakte man eine andere Person kennt) oder alle anderen Arten, wo man in einem Graphen den kürzesten Pfad ermitteln möchte. Man kann so sicherlich auch noch andere, komplexe Berechnungen auf die Clients auslagern.
Gears kann man natürlich auch noch für viele weitere Dinge nutzen, wie schöne Benachrichtigungen, als lokalen Speicher für Dateien oder Daten (Datenbank), Geolocation (was ja mittlerweile die Browser schon nativ beherrschen) usw.
Habt ihr Erfahrungen mit Gears, oder Ideen welche revolutionären Dinge man damit umsetzen könnte?
Externe Javascript Dateien zusammenfassen
Wir alle wissen: Langsame Webseiten bekommen weniger Besucher. Dazu gibt es auch Auswertungen von großen Portalen und Suchmaschinen.
Doch wie beschleunigt man die eigene Webseite? Häufig übersieht man einen wichtigen Teil: Das Frontend bzw. den Client.
Mag das PHP-Script auch sehr schnell sein (die Zeit gemessen mit microtime() ergibt 0.1 Sekunden), die Seite kann sich trotzdem langsam anfühlen. Das liegt häufig an vielen externen Dateien, die der Browser noch nachladen muss. Dazu gehören sowohl CSS-Dateien, Javascript-Dateien, Bilder usw.