Zum Inhalt springen

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.

Node.js für Webentwicklung – Installation & erste Scripte – Symbolbild

~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:

💡 Node.js vs. Browser-JavaScript: Im Browser läuft JS sandboxed ohne Dateisystem-Zugriff. Node.js kann Dateien lesen/schreiben, HTTP-Server starten und System-Commands ausführen – perfekt für Build-Tools!

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

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

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.