Node.js für Webentwicklung – Installation & erste Scripte (2025)
Node.js ist aus der modernen Webentwicklung nicht mehr wegzudenken: Build-Tools, Bundler, SASS-Compiler, Deploy-Scripte und APIs lassen sich elegant automatisieren. Hier zeige ich die Installation mit nvm auf macOS, erkläre das NPM-Ecosystem und stelle praktische Scripte vor – von einfachen File-Watchern bis zu kompletten Build-Pipelines für produktive Web-Workflows.

~9 Min. Lesezeit · Veröffentlicht am
Was ist Node.js & warum für Webentwicklung?
Node.js ist eine JavaScript-Runtime außerhalb des Browsers – basierend auf Googles V8-Engine. Für Webentwickler bedeutet das:
- Build-Automation: SASS kompilieren, CSS/JS minifizieren, Bilder optimieren
- Development-Server: Live-Reload, Hot Module Replacement
- Package-Management: Über 2 Millionen NPM-Pakete für jede Aufgabe
- Deploy-Scripte: FTP/SFTP-Upload, Dateisynchronisation
- Backend-APIs: Express.js, ähnliche Frameworks
Installation mit nvm (macOS)
Warum nvm statt direkter Installation? Verschiedene Projekte benötigen oft verschiedene Node-Versionen. nvm (Node Version Manager) macht Versionswechsel trivial.
nvm via Homebrew installieren
Voraussetzung: Homebrew ist installiert
brew install nvm
mkdir -p ~/.nvm
# In ~/.zshrc oder ~/.zprofile hinzufügen:
echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
echo '[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && . "/opt/homebrew/opt/nvm/nvm.sh"' >> ~/.zshrc
echo '[ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && . "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm"' >> ~/.zshrc
# Terminal neu starten oder Source laden:
source ~/.zshrc Node.js LTS installieren
# Aktuelle LTS-Version installieren
nvm install --lts
nvm use --lts
nvm alias default node # Als Standard setzen
# Versionen prüfen
node -v # z.B. v20.11.0
npm -v # z.B. 10.2.4 Projektspezifische Node-Versionen
# .nvmrc-Datei im Projektordner:
echo "20.11.0" > .nvmrc
# Automatisch richtige Version laden:
nvm use Erste Schritte: NPM & package.json
Die package.json ist das Herzstück jedes Node.js-Projekts – sie definiert Dependencies, Scripts und Metadaten.
Neues Projekt initialisieren
mkdir mein-webprojekt && cd mein-webprojekt
npm init -y # Erstellt package.json mit Defaults
# Oder interaktiv:
npm init NPM vs. Yarn vs. pnpm
- NPM: Standard, kommt mit Node.js
- Yarn: Schneller, besseres Caching (
npm install -g yarn) - pnpm: Platz-effizient durch Symlinks (
npm install -g pnpm)
Pakete installieren
# Development-Dependencies (nur beim Entwickeln)
npm install --save-dev vite sass eslint prettier
# Production-Dependencies (auch auf Server)
npm install express dotenv
# Global installieren (system-weit verfügbar)
npm install -g http-server nodemon Build-Tools & Bundler
Moderne Webentwicklung nutzt Build-Systeme für Optimierung und Developer Experience.
Vite (empfohlen für neue Projekte)
Vite ist ultraschnell und unterstützt alle modernen Frameworks:
npm install --save-dev vite
# package.json Scripts:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
} Webpack (für komplexe Setups)
npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save-dev css-loader sass-loader style-loader
npm install --save-dev html-webpack-plugin mini-css-extract-plugin Parcel (Zero-Config)
npm install --save-dev parcel
# Kein Config nötig - erkennt Entry-Points automatisch Praktische Scripte für Webentwickler
1. SASS/SCSS Compiler & Watcher
npm install --save-dev sass chokidar-cli
// package.json
{
"scripts": {
"sass:build": "sass src/scss:dist/css --style=compressed",
"sass:watch": "sass src/scss:dist/css --watch",
"sass:dev": "sass src/scss:dist/css --watch --source-map"
}
} 2. File-Watcher für automatische Tasks
// scripts/watch.mjs
import chokidar from 'chokidar';
import { execSync } from 'child_process';
const watcher = chokidar.watch(['src/**/*.js', 'src/**/*.scss'], {
ignored: /node_modules/,
persistent: true
});
watcher
.on('change', path => {
console.log(`📝 Geändert: ${path}`);
if (path.endsWith('.scss')) {
execSync('npm run sass:build');
}
execSync('npm run minify:js');
})
.on('ready', () => console.log('👀 Watching files...')); 3. Deploy-Script mit SFTP
npm install --save-dev ssh2-sftp-client
// scripts/deploy.mjs
import Client from 'ssh2-sftp-client';
import path from 'path';
const sftp = new Client();
async function deploy() {
try {
await sftp.connect({
host: process.env.DEPLOY_HOST,
username: process.env.DEPLOY_USER,
password: process.env.DEPLOY_PASS,
port: 22
});
console.log('🚀 Uploading files...');
await sftp.uploadDir('./dist', '/path/to/remote/www');
console.log('✅ Deploy completed!');
} catch (err) {
console.error('❌ Deploy failed:', err.message);
} finally {
await sftp.end();
}
}
deploy(); 4. Bilder-Optimierung
npm install --save-dev sharp
// scripts/optimize-images.mjs
import sharp from 'sharp';
import { readdir } from 'fs/promises';
import path from 'path';
const inputDir = './src/images';
const outputDir = './dist/images';
async function optimizeImages() {
const files = await readdir(inputDir);
for (const file of files) {
if (!/\\.(jpg|jpeg|png)$/i.test(file)) continue;
const inputPath = path.join(inputDir, file);
const outputPath = path.join(outputDir, file);
await sharp(inputPath)
.resize(1920, 1080, { fit: 'inside', withoutEnlargement: true })
.jpeg({ quality: 85 })
.toFile(outputPath);
console.log(`✨ Optimiert: ${file}`);
}
}
optimizeImages(); Workflow-Automation
NPM Scripts orchestrieren
// package.json - Kompletter Workflow
{
"scripts": {
"clean": "rm -rf dist",
"build:css": "sass src/scss:dist/css --style=compressed",
"build:js": "vite build",
"optimize:images": "node scripts/optimize-images.mjs",
"prebuild": "npm run clean",
"build": "npm run build:css && npm run build:js && npm run optimize:images",
"dev": "concurrently \"sass src/scss:dist/css --watch\" \"vite\"",
"deploy": "npm run build && node scripts/deploy.mjs"
}
} Concurrently für parallele Tasks
npm install --save-dev concurrently
"dev": "concurrently -k -p \"[{name}]\" -n \"SASS,VITE\" -c \"yellow,cyan\" \"sass src/scss:dist/css --watch\" \"vite\"" Node.js APIs für Webentwickler
File System (fs)
import { readFile, writeFile, readdir } from 'fs/promises';
import { existsSync } from 'fs';
// Datei lesen
const content = await readFile('./src/data.json', 'utf8');
const data = JSON.parse(content);
// Datei schreiben
await writeFile('./dist/processed-data.json', JSON.stringify(data, null, 2));
// Ordner auslesen
const files = await readdir('./src/images');
const imageFiles = files.filter(f => /\\.(jpg|png|webp)$/i.test(f)); Path-Handling
import path from 'path';
import { fileURLToPath } from 'url';
// ES Module __dirname equivalent
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Pfade sicher zusammenfügen
const outputPath = path.join(__dirname, '..', 'dist', 'bundle.js');
const extension = path.extname('./style.scss'); // .scss Einfacher HTTP-Server
// server.mjs
import http from 'http';
import { readFile } from 'fs/promises';
import path from 'path';
const server = http.createServer(async (req, res) => {
let filePath = '.' + req.url;
if (filePath === './') filePath = './index.html';
try {
const content = await readFile(filePath);
const ext = path.extname(filePath);
const mimeTypes = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript'
};
res.writeHead(200, { 'Content-Type': mimeTypes[ext] || 'text/plain' });
res.end(content);
} catch (err) {
res.writeHead(404);
res.end('404 Not Found');
}
});
server.listen(3000, () => console.log('Server läuft auf http://localhost:3000')); Apple Silicon Tipps
- Native Builds: Moderne Node.js Versionen laufen nativ auf ARM64
- Legacy-Pakete: Bei Problemen Rosetta nutzen:
arch -x86_64 npm install - Python-Dependencies: Manche native Addons brauchen Xcode Command Line Tools
- Memory Limits: Node.js nutzt standardmäßig ~1.4GB RAM, bei großen Builds erhöhen:
node --max-old-space-size=4096
Tipp: Bei Build-Problemen erst rm -rf node_modules package-lock.json && npm install probieren – löst oft Architecture-Konflikte.FAQ
NPM vs. Yarn vs. pnpm – was nehmen?
NPM für Einsteiger und einfache Projekte. Yarn wenn Performance wichtig ist. pnpm bei vielen Projekten (spart Speicher durch Symlinks).
Globale vs. lokale Pakete?
Tools wie nodemon oder http-server global, projektspezifische Dependencies lokal. Mit npx können lokale Pakete ohne globale Installation ausgeführt werden.
Warum .mjs statt .js?
ES Modules (.mjs) sind moderner und explizit. Alternativ "type": "module" in package.json setzen, dann sind .js-Dateien automatisch Module.
Node.js für reine Frontend-Projekte?
Absolut! Auch ohne Backend profitieren Sie von Build-Tools, Package-Management und Development-Servern. Vite/Webpack bauen alles zu statischen Assets.
💡 Nächste Schritte: Kombiniere Node.js mit meinem macOS Webentwicklungs-Setup für einen vollständigen Workflow. Für Package-Management siehe auch meinen Homebrew-Guide.