{"id":185,"date":"2014-10-07T23:43:27","date_gmt":"2014-10-07T21:43:27","guid":{"rendered":"http:\/\/staratnight.de\/blog\/?p=185"},"modified":"2018-12-03T00:38:06","modified_gmt":"2018-12-02T22:38:06","slug":"javascript-code-gut-strukturieren","status":"publish","type":"post","link":"https:\/\/staratnight.de\/blog\/javascript-code-gut-strukturieren\/","title":{"rendered":"JavaScript Code gut strukturieren"},"content":{"rendered":"<p>Nachdem ich nun JavaScript einigerma\u00dfen verstanden hatte, konnte ich mich dem eigentlichen Problem widmen. Wie also strukturiere ich den JavaScript Code sauber in einzelne &#8222;Klassen&#8220; und Dateien?<\/p>\n<p>Der Hauptpunkt ist, dass hinterher am besten alles wieder in einer, maximal zwei JavaScript Dateien zusammengef\u00fchrt ist, damit der Browser beim Laden der Scripte nicht unendlich viele kleine Dateien laden muss.<\/p>\n<p>Man kann nun also den Code in verschiedene Dateien aufteilen, also z.B. eine &#8222;Klasse&#8220; in einer Datei. Stellen wir uns mal folgende Struktur f\u00fcr ein Spiel vor:<\/p>\n<ul>\n<li>game.js<\/li>\n<li>sprite.js<\/li>\n<li>tile.js<\/li>\n<li>player.js<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>In jeder dieser Dateien ist eine Objekt mit seinen Eigenschaften und Methoden definiert. Hinterher soll aber nur eine Datei greatgame.js \u00fcbrigbleiben.<\/p>\n<p>Um daraus ein einzelnes Script zu machen, habe ich\u00a0<a href=\"http:\/\/gruntjs.com\/\">Grunt<\/a> verwendet. Grunt ist ein TaskRunner f\u00fcr JavaScript und f\u00fchrt dank umfangreichem Plugin-System schon sehr viele n\u00fctzliche Funktionen aus.<\/p>\n<p><!--more--><\/p>\n<p><strong>Installation<\/strong><\/p>\n<p>Voraussetzung f\u00fcr Grunt ist <a href=\"http:\/\/nodejs.org\/\">node.js<\/a>. Damit lassen sich JavaScripts auch serverseitig, also ohne einen Browser ausf\u00fchren.<\/p>\n<p>Zur Installation von node.js reicht es auf der Homepage den Installer herunterzuladen und entsprechend zu installieren.<\/p>\n<p>Anschlie\u00dfend kann grunt komfortabel \u00fcber den Nodejs Package Manager installiert werden. Dazu einfach auf der Kommandozeile folgendes eingeben:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"background-color: #000000; color: #c0c0c0; font-family: courier new,courier;\">npm install -g grunt-cli<\/span><\/p>\n<p>Grunt wird daraufhin installiert.<\/p>\n<p>Nun muss man nur noch eine Package-Definition hinterlegen um die Plugins bekannt zu machen und kann sein Grunt-Script schreiben.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Definition<\/strong><\/p>\n<p>F\u00fcr die Package-Definition wird eine Datein <span style=\"font-family: courier new,courier;\">package.json<\/span> in das Hauptverzeichnis gelegt. Dies sieht in etwa folgenderma\u00dfen aus:<\/p>\n<pre class=\"lang:xhtml decode:true\">{\r\n    \"name\": \"NameDerAnwendung\",\r\n    \"version\": \"0.1.0\",\r\n    \"description\": \"Kurzbeschreibung der Anwendung.\",\r\n    \"devDependencies\": {\r\n        \"grunt\": \"~0.4.5\",\r\n        \"grunt-contrib-jshint\": \"~0.10.0\",\r\n        \"grunt-contrib-nodeunit\": \"~0.4.1\",\r\n        \"grunt-contrib-uglify\": \"~0.5.0\",\r\n        \"grunt-contrib-concat\": \"~0.5.0\",\r\n    }\r\n}<\/pre>\n<p><strong>Wichtig:<\/strong> auch die Plugins m\u00fcssen \u00fcber den Node.js Package Manager installiert werden. Dazu entsprechend den obigen Aufruf anpassen, z.B.:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"background-color: #000000; color: #c0c0c0;\"><span style=\"font-family: courier new,courier;\">npm install -g grunt-contrib-nodeunit<\/span><br \/>\n<\/span><\/p>\n<p>Folgende Plugins werden verwendet:<\/p>\n<ul>\n<li>grunt:<br \/>\ndas ist Grunt selbst, kein Plugin&#8230;muss aber auch definiert werden<\/li>\n<li>grunt-contrib-jshint:<br \/>\njshint ist ein Werkzeug zur Pr\u00fcfung der Code-Qualit\u00e4t des JavaScript-Codes. Details gibt es auf der <a href=\"http:\/\/www.jshint.com\/\">JSHint Homepage<\/a>.<\/li>\n<li>grunt-contrib-nodeunit:<br \/>\nUnit-Test-Runner. Habe ich faktisch noch nicht ausprobiert.<\/li>\n<li>grunt-contrib-uglify:<br \/>\nUglify sorgt daf\u00fcr, dass unser Java-Script von &#8222;unn\u00fctzen&#8220; Dingen befreit wird, etwa von Leerzeilen, Leezeichen, Kommentaren, &#8230; Das verkleinert die Datei und verk\u00fcrzt die Ladezeit<\/li>\n<li>grunt-contrib-concat:<br \/>\nConcat erledigt unsere oben beschriebene Aufgabe und packt alle unsere Java-Script-Dateien zu einer zusammen.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><strong>Script<\/strong><\/p>\n<p>Das Skript selbst h\u00f6rt auf den Namen <span style=\"font-family: courier new,courier;\">Gruntfile.js<\/span> und liegt ebenfalls im Hauptverzeichnis.<\/p>\n<p>Das Grunt-Script sieht nun folgenderma\u00dfen aus:<\/p>\n<pre class=\"lang:js decode:true\">var grunt = require('grunt');\r\nmodule.exports = function(grunt) {\r\n\r\n    grunt.initConfig({\r\n        pkg: grunt.file.readJSON('package.json'),\r\n        concat: {\r\n            options: {\r\n                separator: ';'\r\n            },\r\n            dist: {\r\n                src: ['src\/**\/*.js'],\r\n                dest: 'dist\/&lt;%= pkg.name %&gt;.js'\r\n            }\r\n        },\r\n        uglify: {\r\n            options: {\r\n                banner: '\/*! &lt;%= pkg.name %&gt; &lt;%= grunt.template.today(\"dd-mm-yyyy\") %&gt; *\/\\n'\r\n            },\r\n            dist: {\r\n                files: {\r\n                    'dist\/&lt;%= pkg.name %&gt;.min.js': ['&lt;%= concat.dist.dest %&gt;']\r\n                }\r\n            }\r\n        },\r\n        jshint: {\r\n            files: ['Gruntfile.js', 'src\/**\/*.js', 'test\/**\/*.js'],\r\n            options: {\r\n                \/\/ options here to override JSHint defaults\r\n                globals: {\r\n                    jQuery: true,\r\n                    console: true,\r\n                    module: true,\r\n                    document: true\r\n                }\r\n            }\r\n        }        \r\n    });\r\n\r\n    grunt.loadNpmTasks('grunt-contrib-uglify');\r\n    grunt.loadNpmTasks('grunt-contrib-jshint');\r\n    grunt.loadNpmTasks('grunt-contrib-concat');\r\n\r\n    grunt.registerTask('test', ['jshint', 'qunit']);\r\n\r\n    grunt.registerTask('default', ['jshint', 'concat', 'uglify']);\r\n\r\n};\r\ngrunt.tasks(['default']);\r\n\r\n<\/pre>\n<p>In dieser Datei werden zun\u00e4chst die einzelnen Plugins konfiguriert.<\/p>\n<ul>\n<li>pkg:\n<ul>\n<li>Einlesen der Package-Datei f\u00fcr die o.g. Definition<\/li>\n<\/ul>\n<\/li>\n<li>concat:\n<ul>\n<li>Seperator, der zwischen den einzelnen aneinanderzuh\u00e4ngenden Dateien erg\u00e4nzt wird<\/li>\n<li>src definiert den Filter der Quelldateien und dest das Verzeichnis der Ausgabedatei mit den aneinandergereihten JavaScript-Dateien. Dies sollte auf jeden Fall ein Unterverzeichnis sein, in dem sonst keine js-Dateien liegen, um sich nicht versehentlich eine Datei zu \u00fcberschreiben.<\/li>\n<\/ul>\n<\/li>\n<li>uglify:\n<ul>\n<li>das Banner wird im Kopf der Ausgabedatei ausgegeben. Dient rein der Information.<\/li>\n<li>files beschreibt zun\u00e4chst die Ausgabedatei und dann die Quelldatei. Diese wird aus den Optionen des concat-Plugins ausgelesen.<\/li>\n<\/ul>\n<\/li>\n<li>jshint:\n<ul>\n<li>files gibt die zu pr\u00fcfenden Dateien an<\/li>\n<li>mit den Options kann man bestimmte Verhaltensweisen von jshint steuern. Etwa Pr\u00fcfungen, deaktivieren, die man nicht einhalten kann oder will.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Nach der Konfiguration der Plugins werden nun die Aufrufe des Scripts festgelegt. Dazu werden die Module zun\u00e4chst \u00fcber node.js geladen.<\/p>\n<p>Zum Schluss werden verschiedene &#8222;Profile&#8220; definiert. Hier wird zun\u00e4chst der Name des Profils angegeben und anschlie\u00dfend die Liste der Plugins, die ausgef\u00fchrt werden sollen. Wird kein Profil angegeben, so wird &#8222;Default&#8220; ausgef\u00fchrt.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Aufruf<\/strong><\/p>\n<p>Nun ist alles definiert, aber wie rufe ich das Ganze nun auf?<\/p>\n<ol>\n<li>\u00dcber die Kommandozeile:<br \/>\n<span style=\"background-color: #000000; color: #c0c0c0;\">[nodejs-Install-Verzeichnis]\\nodejs\\node.exe Gruntfile.js<\/span><\/li>\n<li>\u00dcber das NodeJS-Plugin von JetBrains f\u00fcr IntelliJ:<br \/>\nEinfach per Rechtsklick auf die Gruntfile.js-Datei und &#8222;Run &#8218;Gruntfile.js'&#8220; ausw\u00e4hlen<\/li>\n<\/ol>\n<p style=\"padding-left: 30px;\"><span style=\"background-color: #000000; color: #c0c0c0;\">\u00a0<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem ich nun JavaScript einigerma\u00dfen verstanden hatte, konnte ich mich dem eigentlichen Problem widmen. Wie also strukturiere ich den JavaScript Code sauber in&hellip;<\/p>\n","protected":false},"author":2,"featured_media":493,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[],"class_list":["post-185","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript"],"_links":{"self":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts\/185","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/comments?post=185"}],"version-history":[{"count":4,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts\/185\/revisions"}],"predecessor-version":[{"id":189,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/posts\/185\/revisions\/189"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/media\/493"}],"wp:attachment":[{"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/media?parent=185"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/categories?post=185"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/staratnight.de\/blog\/wp-json\/wp\/v2\/tags?post=185"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}