|
| 1 | +--- |
| 2 | +author: [Felicitas Pojtinger] |
| 3 | +date: "2023-01-28" |
| 4 | +subject: "Uni Webdev Backend Summary" |
| 5 | +keywords: [webdev-backend, hdm-stuttgart] |
| 6 | +subtitle: "Summary for the webdev backend course at HdM Stuttgart" |
| 7 | +lang: "de" |
| 8 | +--- |
| 9 | + |
| 10 | +# Uni Webdev Backend Summary |
| 11 | + |
| 12 | +## Meta |
| 13 | + |
| 14 | +### Contributing |
| 15 | + |
| 16 | +These study materials are heavily based on [professor Toenniessen's "Web Development Backend" lecture at HdM Stuttgart](https://www.hdm-stuttgart.de/bibliothek/studieninteressierte/bachelor/block?sgname=Mobile+Medien+%28Bachelor%2C+7+Semester%29&sgblockID=2573378&sgang=550041&blockname=Web+Development+Backend) and prior work of fellow students. |
| 17 | + |
| 18 | +**Found an error or have a suggestion?** Please open an issue on GitHub ([github.com/pojntfx/uni-webdev-backend-notes](https://github.com/pojntfx/uni-webdev-backend-notes)): |
| 19 | + |
| 20 | +{ width=150px } |
| 21 | + |
| 22 | +If you like the study materials, a GitHub star is always appreciated :) |
| 23 | + |
| 24 | +### License |
| 25 | + |
| 26 | +{ width=128px } |
| 27 | + |
| 28 | +Uni Webdev Backend Notes (c) 2023 Felicitas Pojtinger and contributors |
| 29 | + |
| 30 | +SPDX-License-Identifier: AGPL-3.0 |
| 31 | +\newpage |
| 32 | + |
| 33 | +## Themen der Vorlesung |
| 34 | + |
| 35 | +1. **Einführung in Node.js** und einfache HTML-Fileserver |
| 36 | +2. **RESTful Endpoints** mit Express.js |
| 37 | +3. Die Template-Engine **EJS** und **Express-Sessions** |
| 38 | +4. Datenbanken mit **MongoDB und Mongoose** |
| 39 | +5. Bidirektionale Client-Server-Kommunikation mit **WebSocket** |
| 40 | + |
| 41 | +## Einführung in Node.js |
| 42 | + |
| 43 | +### Warum Node.js |
| 44 | + |
| 45 | +- Node.js kann **auf dem Server** verwendet werden, im Gegensatz zum Browser |
| 46 | +- JavaScript ist die am **häufigsten verwendete Sprache** im Web und durch die Arbeit im Frontend bekannt |
| 47 | +- JavaScript eignet sich durch seinen **Event-Loop** besonders gut für HTTP-Server |
| 48 | +- Non-Blocking IO ermöglicht es, viele **parallele Anfragen** zu verarbeiten |
| 49 | +- Node.js ist **sehr schnell** |
| 50 | +- **Einfach zu erlernen**, da das populäre Backend-Framework Express.js auf Node.js aufbaut. |
| 51 | +- Aktuelle Version von Node.js ist **16.17.1 LTS (Long Term Support)** |
| 52 | +- Bedeutende Anwender sind unter anderem **Microsoft, Yahoo, SAP, PayPal** und viele andere große Unternehmen verwenden Node.js irgendwo. |
| 53 | +- Weitere Pakete können über den **Node Package Manager (npm)** hinzugefügt werden |
| 54 | + |
| 55 | +**Vorteile:** |
| 56 | + |
| 57 | +Sehr einfache APIs, **schnell zu lernen** |
| 58 | + |
| 59 | +**Nachteile:** |
| 60 | + |
| 61 | +- Etwas **kompliziertes Programmiermodell** (Event-basiert), typisch für JavaScript |
| 62 | +- **Multithreading** in Node.js nur über Worker-Threads möglich |
| 63 | + |
| 64 | +### Module |
| 65 | + |
| 66 | +Node.js hat ein Modul-Konzept, das es ermöglicht, Funktionen und Variablen **in eigene Dateien auszulagern** und sie in anderen Dateien zu importieren. |
| 67 | + |
| 68 | +Ein Beispiel dafür ist die Funktion `add(x,y)`, die in eine **separate Datei** namens 01d_Export.js ausgelagert wird: |
| 69 | + |
| 70 | +```js |
| 71 | +module.exports = function add(x, y) { |
| 72 | + return x + y; |
| 73 | +}; |
| 74 | +``` |
| 75 | + |
| 76 | +In einer anderen Datei, z.B. 01d_AddiererFctModule.js, wird das Modul importiert und verwendet: |
| 77 | + |
| 78 | +```js |
| 79 | +const add = require("./01d_Export"); |
| 80 | +const a = 5, |
| 81 | + b = 7; |
| 82 | +const s = add(a, b); |
| 83 | +console.log(`${a} + ${b} = ${s}`); |
| 84 | +``` |
| 85 | + |
| 86 | +- Mit Modulen kann der Code bei größeren Programmen übersichtlicher gestaltet werden und es ist **weniger fehleranfällig bei Änderungen** oder in der Wartung. |
| 87 | +- Durch die Trennung des Codes in Module, **erhöht sich die Übersichtlichkeit** innerhalb des jeweiligen Moduls |
| 88 | +- Einzelne Module können für sich finalisiert oder refaktoriert werden, **ohne dass es Auswirkungen auf den Rest des Codes** hat. |
| 89 | +- Durch die Aufteilung des Codes in Module, wird es einfacher, die Arbeit unter Teammitgliedern aufzuteilen, was wiederum zu **weniger Merge-Konflikten** führt. |
| 90 | + |
| 91 | +### Import & Export mit `require`/`module` |
| 92 | + |
| 93 | +**Export-Varianten**: |
| 94 | + |
| 95 | +a) Einzelne Methode oder Variable: |
| 96 | + |
| 97 | +```js |
| 98 | +module.exports = function add(x, y) { |
| 99 | + return x + y; |
| 100 | +}; |
| 101 | +``` |
| 102 | + |
| 103 | +b) Mehrere Methoden oder Variablen über ein Objekt: |
| 104 | + |
| 105 | +```js |
| 106 | +module.exports = { |
| 107 | + add: (a, b) => a + b, |
| 108 | + subtract: (a, b) => a - b, |
| 109 | +}; |
| 110 | +``` |
| 111 | + |
| 112 | +c) Mehrere einzelne Exports (mit der Convenience-Variable exports): |
| 113 | + |
| 114 | +```js |
| 115 | +exports.add = (a, b) => a + b; |
| 116 | +exports.subtract = (a, b) => a - b; |
| 117 | +``` |
| 118 | + |
| 119 | +Wenn Sie jedoch **module.exports direkt zuweisen, werden alle vorherigen Exporte überschrieben.** |
| 120 | + |
| 121 | +**Import-Varianten**: |
| 122 | + |
| 123 | +a) Gesamtes Modul importieren: |
| 124 | + |
| 125 | +```js |
| 126 | +const fs = require("fs"); |
| 127 | +fs.readFile(); |
| 128 | + |
| 129 | +const readFile = require("fs").readFile; |
| 130 | +readFile(); |
| 131 | +``` |
| 132 | + |
| 133 | +b) Destrukturierende Zuweisung: |
| 134 | + |
| 135 | +```js |
| 136 | +const { readFile } = require("fs"); |
| 137 | +readFile(); |
| 138 | + |
| 139 | +const { readFile, ...fs } = require("fs"); |
| 140 | +readFile(); |
| 141 | +fs.writeFile(); |
| 142 | +``` |
| 143 | + |
| 144 | +### Import & Export mit ES6 |
| 145 | + |
| 146 | +**Export**: |
| 147 | + |
| 148 | +```js |
| 149 | +export function add(x, y) { |
| 150 | + return x + y; |
| 151 | +} |
| 152 | + |
| 153 | +export function subtract(x, y) { |
| 154 | + return x - y; |
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +**Default-Export**: |
| 159 | + |
| 160 | +```js |
| 161 | +export default (x, y) { |
| 162 | + return x - y; |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +**Import eines gesamten Moduls**: |
| 167 | + |
| 168 | +```js |
| 169 | +import * as math from "./math.js"; |
| 170 | + |
| 171 | +console.log(math.add(5, 2)); // Ausgabe: 7 |
| 172 | +console.log(math.subtract(5, 2)); // Ausgabe: 3 |
| 173 | +``` |
| 174 | + |
| 175 | +**Import mit destrukturierenden Zuweisung**: |
| 176 | + |
| 177 | +```js |
| 178 | +import { add as addition, subtract } from "./math.js"; |
| 179 | + |
| 180 | +console.log(addition(5, 2)); // Ausgabe: 7 |
| 181 | +console.log(subtract(5, 2)); // Ausgabe: 3 |
| 182 | +``` |
| 183 | + |
| 184 | +### Callbacks vs. Promises vs. Async/Await |
| 185 | + |
| 186 | +**Callbacks:** |
| 187 | + |
| 188 | +```js |
| 189 | +const fs = require("fs"); |
| 190 | + |
| 191 | +fs.readFile("file.txt", function (err, data) { |
| 192 | + if (err) throw err; |
| 193 | + console.log(data); |
| 194 | +}); |
| 195 | +``` |
| 196 | + |
| 197 | +**Promises**: |
| 198 | + |
| 199 | +```js |
| 200 | +const fs = require("fs").promises; |
| 201 | + |
| 202 | +fs.readFile("file.txt") |
| 203 | + .then((data) => console.log(data)) |
| 204 | + .catch((err) => console.error(err)); |
| 205 | +``` |
| 206 | + |
| 207 | +**async/await**: |
| 208 | + |
| 209 | +```js |
| 210 | +const fs = require("fs").promises; |
| 211 | + |
| 212 | +async function readFileExample() { |
| 213 | + try { |
| 214 | + const data = await fs.readFile("file.txt"); |
| 215 | + console.log(data); |
| 216 | + } catch (err) { |
| 217 | + console.error(err); |
| 218 | + } |
| 219 | +} |
| 220 | + |
| 221 | +readFileExample(); |
| 222 | +``` |
| 223 | + |
| 224 | +### Statischer Webserver |
| 225 | + |
| 226 | +Mit Support für ein paar wenige MIME-Types: |
| 227 | + |
| 228 | +```js |
| 229 | +const http = require("http"); |
| 230 | +const fs = require("fs"); |
| 231 | +const { extname } = require("path"); |
| 232 | + |
| 233 | +const app = http.createServer((request, response) => { |
| 234 | + fs.readFile(__dirname + request.url, (err, data) => { |
| 235 | + const status = err ? 400 : 200; |
| 236 | + |
| 237 | + if (extname(request.url) == ".html") |
| 238 | + response.writeHead(200, { status, "Content-Type": "text/html" }); |
| 239 | + if (extname(request.url) == ".js") |
| 240 | + response.writeHead(200, { status, "Content-Type": "text/javascript" }); |
| 241 | + if (extname(request.url) == ".css") |
| 242 | + response.writeHead(200, { status, "Content-Type": "text/css" }); |
| 243 | + |
| 244 | + response.write(data); |
| 245 | + response.end(); |
| 246 | + }); |
| 247 | +}); |
| 248 | + |
| 249 | +app.listen(3000); |
| 250 | + |
| 251 | +console.log("Listening on :3000"); |
| 252 | +``` |
| 253 | + |
| 254 | +Mit Support für ein alle MIME-Types: |
| 255 | + |
| 256 | +```bash |
| 257 | +$ npm install node-static |
| 258 | +``` |
| 259 | + |
| 260 | +```js |
| 261 | +const http = require("http"); |
| 262 | +const fileserver = new (require("node-static").Server)(); |
| 263 | + |
| 264 | +const app = http.createServer((request, response) => { |
| 265 | + fileserver.serve(request, response); |
| 266 | +}); |
| 267 | + |
| 268 | +app.listen(3000); |
| 269 | + |
| 270 | +console.log("Listening on :3000"); |
| 271 | +``` |
| 272 | + |
| 273 | +Mit Support für ein alle MIME-Types & Express: |
| 274 | + |
| 275 | +```bash |
| 276 | +$ npm install express |
| 277 | +``` |
| 278 | + |
| 279 | +```js |
| 280 | +const express = require("express"); |
| 281 | +const app = express(); |
| 282 | + |
| 283 | +app.use("/WDBackend", express.static(__dirname + "/public")); |
| 284 | +app.listen(3000); |
| 285 | + |
| 286 | +console.log("Listening on :3000"); |
| 287 | +``` |
| 288 | + |
| 289 | +### NPM: Pakete Installieren |
| 290 | + |
| 291 | +- npm ist ein **Paketmanager** für Node.js (wie Maven bei Java oder pip bei Python) |
| 292 | +- Mit npm können **Thirdy-Party-Libraries installiert** werden, die auf https://www.npmjs.com gesucht werden können. |
| 293 | +- Installierte Pakete können **über `require` importiert** werden, ohne dass ein relativer Pfad angegeben werden muss. |
| 294 | +- **Projektspezifische Installation**: `npm install paket-name` oder `npm i paket-name` |
| 295 | +- **Globale Installation**: `npm i -g paket-name` |
| 296 | +- **Installation von Entwicklungspaketen**: `npm i -D paket-name` |
| 297 | +- `package-lock.json` enthält die **exakten Versionen** aller installierten Abhängigkeiten. |
| 298 | +- Der `node_modules` Ordner enthält die **Dateien aller installierten Pakete.** |
| 299 | +- Der `node_modules` Ordner sollte immer von **Git-Commits ausgeschlossen werden** |
| 300 | +- Die `package-lock.json` sollte hingegen **immer committed** werden. |
| 301 | + |
| 302 | +### NPM: `package.json` |
| 303 | + |
| 304 | +- Kann mit `npm init` erstellt werden |
| 305 | +- Unter `scripts` in der `package.json` Datei können Command-Line Befehle gespeichert werden, die später ausgeführt werden können, indem man sie in der Kommandozeile aufruft, z.B. `npm run start` oder `npm run test`. |
| 306 | + |
| 307 | +### NPM: Paketauflösung |
| 308 | + |
| 309 | +1. In einem **relativen Pfad** zur Datei, bis eine "package.json" Datei gefunden wird (npm Projekt Definition) und dort im "node_modules" Ordner |
| 310 | +2. In den **global** installierten Paketen |
| 311 | + |
| 312 | +**Best Practice**: Pakete sollten immer im Projekt installiert werden, damit dort alle Abhängigkeiten definiert sind. CLI-Tools können auch global, z.B. zur Projektinitialisierung, installiert werden. |
| 313 | + |
| 314 | +``` |
| 315 | +
|
| 316 | +``` |
0 commit comments