So erstellen Sie eine Website mit Node.js und Express

Node.js-Webanwendung

In diesem Beispiel wird eine Website mit Node.js erstellt, um ein logisches Websiteverhalten bereitzustellen. Mithilfe des Express.js-Frameworks wird die Website als Webanwendung implementiert, mit logischem Routing zu anderen Abschnitten der Website.

HTML und CSS basieren auf unserem responsiven Website-Design mit CSS Grid und Flexbox. Der HTML-Code wird als Vorlage umgestaltet, sodass der Layoutcode beim Hinzufügen neuer Seiten wiederverwendet werden kann.

Knoten installieren

Node.js, auch Node genannt, ist eine Laufzeitumgebung zum Schreiben serverseitiger Anwendungen in JavaScript.

Notiz

Wenn Node bereits auf Ihrem Computer installiert ist, können Sie diesen Abschnitt überspringen und mit der Erstellung einer neuen Express-App fortfahren.

Laden Sie das Node-Installationsprogramm von der offiziellen Node.js-Download-Website herunter. Wählen Sie die LTS-Version (Long Term Support) für Ihr Betriebssystem.

Windows und macOS

Öffnen Sie das Node-Installationsprogramm und führen Sie es aus (.msi unter Windows, .pkg unter macOS).

Aktivieren Sie unter Windows auf dem Installationsbildschirm mit der Bezeichnung Tools for Native Modules das Kontrollkästchen Notwendige Tools automatisch installieren.

Linux

Auf Linux-Systemen können Sie Node mit Ihrem Paketmanager installieren, die kompilierten Binärdateien manuell installieren oder Node aus der Quelle erstellen. Ausführliche Informationen finden Sie im offiziellen Installations-Wiki von Node.js.

Alle Betriebssysteme

Öffnen Sie nach Abschluss der Installation ein Terminal- oder Eingabeaufforderungsfenster. Führen Sie den folgenden Befehl aus, um npm, den Node-Paketmanager, zu aktualisieren. Der Schalter -g (global) gibt an, dass die Software systemweit installiert wird, nicht nur die aktuelle Node-App.

Windows

npm install -g npm

Linux und macOS

sudo npm install -g npm

Verwenden Sie schließlich npm, um die Express-Generator-Anwendung global zu installieren.

Windows

npm install -g express-generator

Linux und macOS

sudo npm install -g express-generator

Erstellen Sie eine neue Express-App

Generieren Sie in einem Terminal- oder Eingabeaufforderungsfenster eine neue Express.js-App. In unserem Beispiel lautet der App-Name myapp, und die Ansichts-Engine ist als pug angegeben.

express myapp --view="pug"

Wechseln Sie in das Verzeichnis der neuen Express-App.

cd myapp

Verwenden Sie im Express-App-Verzeichnis npm install, um die erforderlichen Abhängigkeiten herunterzuladen und zu installieren, wie in der Datei „package.json“ aufgeführt.

npm install

Wenn Sicherheitsupdates für die installierten Abhängigkeiten verfügbar sind, wird eine Benachrichtigung angezeigt.

found 1 low severity vulnerability
  run `npm audit fix` to fix them, or `npm audit` for details

Wenden Sie in diesem Fall die Sicherheitsupdates an.

npm audit fix

nodemon installieren

Installieren Sie im Verzeichnis der Express-App nodemon. Die Option –save-dev gibt an, dass nodemon eine Entwicklungsabhängigkeit ist. Es wird nicht in der Anwendung selbst verwendet, sondern ist ein Werkzeug, das während der Entwicklung verwendet wird.

npm install --save-dev nodemon

Fügen Sie ein Startskript für die Entwicklung hinzu

Ein Startskript für die Entwicklung bietet eine Möglichkeit, Ihre Webanwendung mit Optionen zu starten, die Ihnen bei der Entwicklung der App helfen, z. B. ausführliche Fehlermeldungen.

Öffnen Sie in einem Texteditor die Datei package.json im App-Verzeichnis. Diese JSON-Datei gibt die Abhängigkeiten an, die von Ihrer Node-App verwendet werden. Darüber hinaus enthält es benannte Startskripts, die die Anwendung auf unterschiedliche Weise starten.

Suchen Sie in package.json den Eintrag „scripts“. Standardmäßig enthält es nur ein Skript (“Start”).

  "scripts": {
    "start": "node ./bin/www"
  },

Fügen Sie eine neue Zeile hinzu, die ein Skript devstart wie folgt definiert.

Linux und macOS

  "scripts": {
    "start": "node ./bin/www",
    "devstart": "DEBUG=myapp:* nodemon ./bin/www"
  },

Windows

  "scripts": {
    "start": "node ./bin/www",
    "devstart": "SET DEBUG=myapp:* & nodemon ./bin/www"
  },

Diese Skripte (“start” und “devstart”) können durch Ausführen des Befehls npm run scriptname ausgeführt werden.

Der Befehl npm run devstart startet die App mit zwei zusätzlichen aktivierten Entwicklungsfunktionen.

  • Die Umgebungsvariable DEBUG wird gesetzt und gibt an, dass die Protokoll- und Fehlerseiten der Konsole, wie z. B. HTTP 404, zusätzliche Informationen wie einen Stack-Trace anzeigen.
  • Darüber hinaus überwacht nodemon bestimmte wichtige Website-Dateien. Wenn Sie diese Dateien ändern, z. B. eine Seite neu gestalten oder statische Inhalte ändern, startet nodemon den Server automatisch neu, um die Änderungen widerzuspiegeln.

Starten Sie den Webserver im Entwicklungsmodus.

npm run devstart
Tipp

Wenn die Windows-Firewall die Webserveranwendung blockiert, klicken Sie auf Zugriff zulassen.

Vorschau der Web-App

Wenn die Anwendung ausgeführt wird, fungiert Ihr Computer als Webserver und stellt HTTP auf Port 3000 bereit.

Um eine Vorschau der Website anzuzeigen, öffnen Sie einen Webbrowser mit der Adresse localhost:3000.

Standardmäßige Express.js-App

Jedes mit Ihrem lokalen Netzwerk verbundene Gerät kann die Anwendung unter der Adresse IP-Adresse: 3000 anzeigen, wobei IP-Adresse die lokale IP-Adresse des Computers ist, auf dem die App ausgeführt wird.

Tipp

Wenn Sie sich nicht sicher sind, wie die lokale IP-Adresse des Computers lautet, lesen Sie: So finden Sie meine IP-Adresse.

Um eine Vorschau der Website auf einem mobilen Gerät anzuzeigen, verbinden Sie das WLAN mit Ihrem lokalen Netzwerk und öffnen Sie die Adresse in einem Browser.

Express.js auf Mobilgeräten

HTML-Vorlagen

Unser Beispiel verwendet CSS, JavaScript und HTML aus der Anleitung zum Erstellen einer responsiven Website mit CSS Grid und Flexbox. CSS und JavaScript werden wörtlich verwendet. Der HTML-Code wird in eine Templating-Sprache umgestaltet.

Unter Verwendung einer Vorlagensprache wird der Layoutcode nur einmal geschrieben und von anderen Seiten geerbt.

Die Software, die eine Vorlage in ihr endgültiges Format konvertiert, wird als Vorlagenprozessor bezeichnet. Im Zusammenhang mit HTML wird ein Vorlagenprozessor als Ansichtsmaschine bezeichnet.

Express.js unterstützt mehrere Ansichtsmodule, einschließlich Pug.

Überblick über Mops

Die Pug-Sprache beschreibt HTML-Dokumente auf eine Weise, die Vorteile und zusätzliche Funktionen bietet. Pug-Dateien werden in HTML gerendert, wenn der Benutzer sie anfordert.

Die Sprachsyntax von Pug beseitigt die Notwendigkeit, Tags zu schließen oder in Klammern einzuschließen. Es unterstützt auch geerbte Vorlagen, Iterationen, Bedingungen und JavaScript-Evaluierung.

Beispiel für eine HTML-zu-Pug-Konvertierung

Dies sind die ersten Zeilen des HTML-Codes zum Erstellen einer responsiven Website mit CSS Grid und Flexbox.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta charset="utf-8">
    <title>Title</title>
    <link rel="stylesheet" href="index.css">
    <script src="index.js"></script>
  </head>
  <body>
    <div id="menu">
      <section id="menuitems">
        <div class="menubutton">
          <h1 onclick="menuToggle('hide')" class="menubutton">&#9776;</h1>

In Pug kann das gleiche HTML so geschrieben werden.

doctype html
html
  head
    meta(name="viewport" content="width=device-width, initial-scale=1")
    meta(charset="utf-8")
 title Title
    link(rel="stylesheet", href="index.css")
    script(src="index.js")
  body
    #menu
      section#menuitems
        .menubutton
          h1.menubutton(onclick="menuToggle('hide')") &#9776;

Element-Tags werden ohne Klammern geschrieben. Untergeordnete Elemente werden eingerückt. Die Ebene der Einrückung bestimmt den Umfang eines Elements, daher sind schließende Tags nicht erforderlich.

Die CSS-Selektoren „id“ und „class“ können als element#id, element.class, element#id.class usw. geschrieben werden. Wenn kein Element angegeben ist, wird davon ausgegangen, dass das Element ein div ist. Beispielsweise kann

in HTML als .foo in Pug geschrieben werden.

Nach dem Elementnamen und seinen Selektoren können Attribute in Klammern als kommagetrennte Liste angegeben werden. Zum Beispiel:

HTML

<div class="button" onmouseover="glow()" onclick="start()">

Mops

.button(onmouseover="glow()", onclick="start()")

Mehrere Elemente in einer Zeile auflisten

Wenn auf das Element ein Doppelpunkt (:) folgt, kann darauf ein untergeordnetes Element in derselben Zeile folgen. Die folgenden zwei Abschnitte von Pug erzeugen dieselbe HTML-Ausgabe.

a(href="/home")
  p Home
a(href="https://www.computerhope.com/home"): p Home

Beides wird im folgenden HTML gerendert.

<a href="https://www.computerhope.com/home"><p>Home</p></a>

Auswertung von JavaScript

Wenn dem Element ein Gleichheitszeichen (=) folgt, wird alles, was in dieser Zeile folgt, als gepufferter Code interpretiert. Der Code wird als JavaScript ausgewertet und die Ausgabe „gepuffert“ (als Inhalt des Elements aufgenommen). In seiner einfachsten Form kann gepufferter Code der Name einer Variablen sein, die von der Anwendung übergeben wird.

Beispielsweise übergibt der App-Router für die Homepage, index.js, die Variable title mit dem Wert „Our Farm Stand“ an die Methode express.Router(), die sie an Pug weitergibt. Wenn Pug layout.pug rendert, die folgende Zeile:

title= pagetitle

…wird interpretiert als:

title Our Farm Stand

… was als folgender HTML-Code gerendert wird:

<title>Our Farm Stand</title>

Vorlagenvererbung

Pug-Dokumente können andere Pug-Dokumente mit den Schlüsselwörtern extend und block erben.

Sie können beispielsweise ein grundlegendes Website-Layout, layout.pug, mit gemeinsam genutzten Elementen der Seite erstellen.

doctype html
html
  head
 title Page Title
  body
    p Content
    block foo

Die Block-foo-Anweisung lautet: „Fügen Sie hier einen Inhaltsblock mit dem Namen foo ein, der in einem anderen Pug-Dokument angegeben ist, das diese Vorlage erbt.“

Dokumente, die layout.pug erben, müssen mit der Anweisung „extensions layout“ beginnen und auf der obersten Einzugsebene (am Anfang einer neuen Zeile) eine block foo-Anweisung enthalten. Die Kinder dieser “block foo”-Anweisung werden in die Vorlage an der Stelle des entsprechenden Blocks eingefügt.

Ein Pug-Dokument kann layout.pug wie folgt erben.

extends layout
block foo
  p This is the home page.

Wenn das Dokument gerendert wird, lädt die Pug-Engine die Datei layout.pug. Der Zeilenblock foo in layout.pug wird durch p ersetzt. Dies ist die Startseite.

Überblick über die standardmäßige Express-App

Die Standardstruktur der Express-App ist hier aufgelistet, mit Beschreibungen jeder Datei und jedes Verzeichnisses.

myapp/                  (Contains the entire Express app)
&boxvr;&boxh; app.js               The core logic of the Express app.
&boxvr;&boxh; bin/                 (Contains the app's executable scripts)
&boxv;  &boxur;&boxh; www               A wrapper that runs app.js.
&boxvr;&boxh; node_modules/        (Contains dependencies installed by npm)
&boxvr;&boxh; package-lock.json    JSON manifest of installed dependencies.
&boxvr;&boxh; package.json         JSON of dependencies and config specific to your app.
&boxvr;&boxh; public/              (Files downloaded by the user's web browser)
&boxv;  &boxvr;&boxh; images/           (Contains client-accessible image files)
&boxv;  &boxvr;&boxh; javascripts/      (Contains client-accessible JavaScript files)
&boxv;  &boxur;&boxh; stylesheets/      (Contains client-accessible CSS)
&boxv;     &boxur;&boxh; style.css      The site's CSS stylesheet.
&boxvr;&boxh; routes/              (Contains logic for individual site routes)
&boxv;  &boxvr;&boxh; index.js          Logic of the "index" route (/).
&boxv;  &boxur;&boxh; users.js          Logic of the "users" route (/users).
&boxur;&boxh; views/               (Contains HTML templates)
   &boxvr;&boxh; error.pug         View displayed for error pages, such as HTML 404.
   &boxvr;&boxh; index.pug         View displayed for the site root (/).
   &boxur;&boxh; layout.pug        View template of layout shared by all pages.

Die Kernfunktionalität der Website ist in app.js definiert. Routen werden in dieser Datei benannt und spezifiziert.

Eine Route ist eine Seite oder ein Abschnitt der Website mit einem eindeutigen Pfad in der URL, z. B. www.example.com/search, www.example.com/login usw. Diese Routen sind benannt und mit Routenlogik-Skripts verknüpft. in app.js.

Routenlogikskripte werden im Routenordner gespeichert. Wenn ein Benutzer eine Route anfordert, verarbeitet sein Routenlogikskript die HTTP-Anforderungsdaten und sendet eine Antwort.

Der Views-Ordner enthält die HTML-Vorlagen, Views genannt, die von der View-Engine (Pug) verarbeitet werden.

Implementierung: JavaScript, CSS und Pug

Der folgende Code implementiert die Express-Web-App.

App-Dateistruktur

myapp/
&boxvr;&boxh; app.js               App core logic
&boxvr;&boxh; bin/
&boxv;  &boxur;&boxh; www
&boxvr;&boxh; node_modules/
&boxvr;&boxh; package-lock.json
&boxvr;&boxh; package.json
&boxvr;&boxh; public/
&boxv;  &boxvr;&boxh; images/
&boxv;  &boxvr;&boxh; javascripts/
&boxv;  &boxv;  &boxur;&boxh; menu.js        Implements menu toggle
&boxv;  &boxur;&boxh; stylesheets/
&boxv;     &boxur;&boxh; style.css      Stylesheet
&boxvr;&boxh; routes/
&boxv;  &boxvr;&boxh; about.js          Logic for route /about
&boxv;  &boxvr;&boxh; advice.js         Logic for route /advice
&boxv;  &boxvr;&boxh; contact.js        Logic for route /contact
&boxv;  &boxvr;&boxh; index.js          Logic for route /
&boxv;  &boxvr;&boxh; recipes.js        Logic for route /recipes
&boxv;  &boxvr;&boxh; tips.js           Logic for route /tips
&boxv;  &boxur;&boxh; users.js          Not used, can be deleted
&boxur;&boxh; views/
   &boxvr;&boxh; about.pug         View for route /about
   &boxvr;&boxh; advice.pug        View for route /advice
   &boxvr;&boxh; contact.pug       View for route /contact
   &boxvr;&boxh; error.pug
   &boxvr;&boxh; index.pug         View for route /
   &boxvr;&boxh; layout.pug        View template shared by all pages
   &boxvr;&boxh; recipes.pug       View for route /recipes
   &boxur;&boxh; tips.pug          View for route /tips
blue = modified, green = new, red = not used

meineapp/app.js

Die Kern-App-Logik ist im Wesentlichen dieselbe wie die standardmäßige Express-App, wobei zusätzliche Routen definiert sind. Die Route “users” wird entfernt.

// core dependencies
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
// create route objectsvar indexRouter = require('./routes/index');var aboutRouter = require('./routes/about');var contactRouter = require('./routes/contact');var tipsRouter = require('./routes/tips');var recipesRouter = require('./routes/recipes');var adviceRouter = require('./routes/advice');
// the app object
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// app config
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// tell the app to use these routesapp.use("https://www.computerhope.com/", indexRouter);app.use('/about', aboutRouter);app.use('/contact', contactRouter);app.use('/tips', tipsRouter);app.use('/recipes', recipesRouter);app.use('/advice', adviceRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});
// expose this app to scripts that require it, i.e. myapp/bin/www
module.exports = app;

meineapp/routes/layout.pug

Die Datei layout.pug enthält das Kernlayout der Seite, das von allen Seiten der Website gemeinsam genutzt wird. Es enthält alles, was zum Anzeigen einer Seite erforderlich ist, mit Ausnahme des Haupttextinhalts (Block Haupttext).

doctype html
html
  head
 title= pagetitle
    meta(charset="utf-8")
    meta(name="viewport" content="width=device-width, initial-scale=1")
    script(src="/javascripts/menu.js")
    link(rel="stylesheet", href="/stylesheets/style.css")
  body
    #menu
      section#menuitems
        .menubutton
          h1.menubutton(onclick="menuToggle('hide')") &#9776;
        a(href="/")
          h3.menuhead Our Farm Stand
        a(href="/tips")
          h3.sectrule Tips for living well
        a(href="/recipes")
          h3 Recipes
        a(href="/advice")
          h3 Homesteading advice
        a(href="/about")
          h3.sectrule About Us
        a(href="/contact")
          h3 Contact Us
    #container
      #header
        a(href="/")
          h1.logo Our Farm Stand
        .headspace
        h1.menubutton(onclick="menuToggle('show')") &#9776;
        h1.placeholder &#9776;
        h2.navitem
          a(href="/about")
            .clickable-area About Us
        h2.navitem
          a(href="/contact")
            .clickable-area Contact Us
      #panel.left
        section#sections
          .sectionlink
            a(href="/tips")
              .clickable-area Tips for living well
          .sectionlink
            a(href="/recipes")
              .clickable-area Recipes
          .sectionlink
            a(href="/advice")
              .clickable-area Homesteading advice
      block mainbody
      #panel.right
        h3 Our friends
        section#partners.tall
          .partnerlink
            a(href="/")
              .clickable-area Green Valley Greens
          .partnerlink
            a(href="/")
              .clickable-area Turkey Hill Farm
          .partnerlink
            a(href="/")
              .clickable-area Burt's Maple Syrup
          .partnerlink
            a(href="/")
              .clickable-area Only Organic Seeds
      #footer
        p Copyright &copy; 2020 Alice &amp; Bob's Farm Stand

myapp/views/index.pug

Die Datei index.pug erweitert layout.pug und enthält Hauptinhalt für die Route /.

extends layout
block mainbody
  #mainbody
    section.mainbodyitems
      h3 Announcements
      section.announcements
        .announceitem
          h4.title Open for business
          p.date Jan. 15
          p Renovations of our new storefront are complete, and we're open for business.
      h3 Items for sale
      section.forsaleitems
        table
          tr
            th Item
            th Description
            th Price
            th.qty Qty
          tr
            td Milk
            td Good source of calcium.
            td.price $2
              span.perunit  / half gal.
            td.qty 3
          tr
            td Eggs
            td Great for breakfast and baking.
            td.price $4
              span.perunit  / doz.
            td.qty 6
          tr
            td Whole chicken
            td Perfect for roasting.
            td.price $5
              span.perunit  / lb.
            td.qty 4
      h3 Upcoming events
      section
        .eventitem
          h4.title Cider Fest
          p.date October 20, 2pm&ndash;6pm
          p Celebrate the season with fresh-pressed cider from our orchards.
        .eventitem
          h4.title Bread baking workshop
          p.date December 13, 9am&ndash;noon
          p Learn how to create and cultivate a sourdough starter.
      h3 Message of the day
      section
        .motditem
          p Eat better food. Support your local farm stand.
        h3#partners.wide Our friends
        section#partners.wide
          .partnerlink.wide
            a(href="")
              .clickable-area Green Valley Greens
          .partnerlink.wide
            a(href="")
              .clickable-area Turkey Hill Farm
          .partnerlink.wide
            a(href="/")
              .clickable-area Burt's Maple Syrup
          .partnerlink.wide
            a(href="")
              .clickable-area Only Organic Seeds
        .bodyspace

meineapp/routes/index.js

Die Datei index.js enthält Logik für die Route /.

var express = require('express');
var router = express.Router();
router.get("https://www.computerhope.com/", function(req, res, next) {
  res.render('index', { pagetitle: 'Our Farm Stand' });
});
module.exports = router;

Die Datei menu.js enthält das JavaScript aus dem Grid- und Flexbox-Beispiel. Es implementiert die Menüumschaltfunktion.

function menuToggle(state) {
  var ele = document.getElementById('menu');
  switch(state) {
    case 'show':
      ele.style.opacity=1;
      ele.style.color="rgb(96, 96, 96)";
      ele.style.visibility='visible';
      ele.style.transition='visibility 0s, opacity 0.3s';
      break;
    case 'hide':
      ele.style.opacity=0;
      ele.style.color="black";
      ele.style.visibility='hidden';
      ele.style.transition='visibility 0.3s, opacity 0.3s'; 
      break;
  }
}

meineapp/public/stylesheets/style.css

Die Datei style.css enthält das CSS aus dem Grid- und Flexbox-Beispiel.

/* element styles */
* {
  margin: 0;     /* by default, all elements (selector *) have no margin */
}
html {
  width: 100%;                    /* 100% width of parent (root) element */
  height: 100vh;                              /* 100% height of viewport */
  background: rgb(0, 0, 0, 0.1);                            /* 10% black */
  font-size: 1.0em;                                /* our root font size */
  font-family: Arial, Helvetica, sans-serif;             /* default font */
}
body {
  min-height: 100%;
}
section {
  padding: 0.5rem;
  flex-grow: 1;         /* in a flexbox, sections expand along flex axis */
}
h1 {                                           /* Website name in header */
  font-size: 2.0rem;
  font-weight: normal;
}
h2 {                                                   /* About, Contact */
  font-size: 1.25rem;
}
h3 {                                                 /* Section headings */
  font-size: 1.2rem;
  padding: 0.5rem;
}
h4 {                                               /* Section item title */
  font-weight: normal;
  padding: 0.5rem;
}
p {                                                 /* Section item body */
  padding: 0.5rem;
}
a:link, a:visited {            /* anchor links, and visited anchor links */
  color: black;
  text-decoration: none;                            /* disable underline */
}
a:hover {                                 /* when anchor link is hovered */
  color: rgb(25, 25, 25);
}
a:active {                                /* when anchor link is clicked */
  color: rgb(96, 96, 96);
}
/* component styles */
#container {
  display: grid;
  height: 100vh;
  grid-template-columns:
    [left] 10rem auto 10rem [right];
  grid-template-rows:
    [top] 5rem auto 5rem [bottom];     /* header height fits its content */
  grid-template-areas:
    "head head head"
    "panleft mainbody panright"
    "foot foot foot";
}
#header {
  grid-area: head;                    /* corresponds to name in template */
  background: rgb(0, 0, 0, 0.2);                            /* 20% black */
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: baseline;  /* site name and nav item text aligns baseline */
  padding: 1.0rem;
}
#panel {                                       /* for element id="panel" */
  display: flex;                     /* this element is a flexbox parent */
  flex-direction: column;          /* its child elements flex vertically */
  padding: 0.5rem;
  background: rgb(0, 0, 0, 0.1);                            /* 10% black */
}
#panel.left {                 /* for element id="panel" and class="left" */
  grid-area: panleft;                  /* this element fills a grid area */
}
#panel.right {
  grid-area: panright;
}
#footer {
  grid-area: foot;
  display: flex;                     /* this element is a flexbox parent */
  flex-direction: column;          /* its child elements flex vertically */
  justify-content: center;           /* horizontal center footer content */
  align-items: center;                 /* vertical center footer content */
  padding: 0.5rem;
  background: rgb(0, 0, 0, 0.2);
}
#mainbody {                                 /* for element id="mainbody" */
  display: flex;                     /* this element is a flexbox parent */
  flex-direction: column;          /* its child elements flex vertically */
  grid-area: mainbody;
  justify-self: center;          /* fixed-width mainbody always centered */
  width: 100%;
  min-width: 22.5rem;            /* mainbody width can't go < 22.5rem */
}
div#panel,
div#mainbody {                               /* extra space under header */
  padding-top: 0.5rem;
}
#partners, #sections {     /* for element id="partners" or id="sections" */
  display: flex;                     /* this element is a flexbox parent */
  flex-direction: row;           /* its child elements flex horizontally */
  flex-wrap: wrap;           /* its child elements can wrap to next line */
  align-content: flex-start;       /* child elements start in upper left */
}
#partners.wide {           /* for element id="partners" and class="wide" */
  display: none;              /* by default, do not display this element */
}
#menu {
  position: absolute;      /* menu position unaffected by other elements */
  right: 0;                       /* zero pixels from the right boundary */
  background: rgb(239, 239, 239);
  border: 0.15rem solid rgb(0, 0, 0, 0.4);
  visibility: hidden;        /* visibility property supports transitions */
  opacity: 0;      /* opacity + visibility transition = menu fade effect */
  z-index: 1;              /* ensure menu appears over all other content */
}
#menuitems {               /* menu is implemented as a flexbox container */
  display: flex;
  flex-direction: column;
  padding: 1rem;
}
#menuitems h3 {
  border-top: 0.15rem solid rgb(0, 0, 0, 0.1);  /* light horizontal rule */
}
#menuitems .sectrule {
  border-color: rgb(0, 0, 0, 0.25);            /* darker horizontal rule */
}
#menuitems .menuhead {
  border-top: none;
}
#menuitems h3:hover {
  background-color: rgb(0, 0, 0, 0.1);     /* gray of rollover menuitems */
}
.menubutton {
  text-align: right;
  cursor: pointer;            /* indicates it can be clicked like a link */
  user-select: none;            /* user cannot select the button as text */
}
#menuitems .alignright {
  text-align: right;            /* right-aligned menu item text (unused) */
}
#header h1.menubutton {
  display: none;        /* in default view (landscape), hide menu button */
  border: 0.15rem solid rgb(0, 0, 0, 0);   /* (invisible) alignment shim */
}
#header .placeholder {    /* this invisible button is rendered when menu */
  color: rgb(0, 0, 0, 0); /* button is hidden, so header height matches. */
  user-select: none;       /* user can't select text of invisible button */
}
.sectionlink, .partnerlink {
  border-radius: 0.25rem;     /* give this element a slight rounded edge */
  font-weight: normal;
  font-size: 1.1rem;
  padding: 0.5rem;
  width: 7rem;                            /* fixed width for these items */
  margin-bottom: 1rem;                  /* slight margin for readability */
  background: rgb(0, 0, 0, 0.1);
}
.sectionlink:hover, .partnerlink:hover {
  background-color: rgb(0, 0, 0, 0.065);   /* brighten bg on mouse hover */
}
.partnerlink {
  height: 7rem;        /* partner elements are additionally fixed height */
}
.partnerlink.wide {
  margin: 0.5rem 1rem 0.5rem 0;      /* margins for spacing if they wrap */
}
.clickable-area {      /* use whenever a clickable area excludes margins */
  height: 100%;                 /* clickable area spans height of parent */
}
.eventitem, .announceitem, .motditem {
  margin-bottom: 0.5rem;                /* slight margin for readability */
}
.title {                                    /* e.g., "Open for business" */
  font-style: italic;
  font-weight: normal;
  font-size: 1.1rem;
}
.date, .ingredient {                                         /* e.g., January 1, 2021 */
  font-style: italic;
  font-size: 0.9rem;
  padding: 0 0 0.01rem 0.5rem;
  color: rgb(0, 0, 0, 0.5);
}
.navitem {                                             /* About, Contact */
  font-weight: normal;
  padding: 0 0.5rem 0 1rem;
}
.headspace, .panspace, .footspace, .bodyspace {
  flex-grow: 1;      /* these elements expand on flex axis to fill space */
}
/* table styles ("items for sale") */
table {
  border-collapse: collapse;               /* pixel-adjacent table cells */
  width: 100%;
  margin-bottom: 1rem;
}
th {
  text-align: left;
}
tr {
  margin: 4rem 0 0 0;
  border-bottom: 0.15rem solid rgb(0, 0, 0, 0.2);     /* horizontal rule */
}
td, th {
  padding: 0.5rem;
  vertical-align: top;
}
td.price {
  white-space: nowrap;        /* white space in price does not wrap line */
}
td.qty, th.qty {
  text-align: center;
}
span.perunit {
  opacity: 0.5;
}
/* responsive styles applied in portrait mode */
@media screen and (max-width: 45rem) {      /* if viewport width < 45rem */
  #panel.left {
    grid-column-end: left;         /* panel grid area shrinks to nothing */
  }
  #panel.right {
    grid-column-start: right;      /* panel grid area shrinks to nothing */
  }
  #partners.tall {
    display: none;  /* hide partners in panel (overwrites display: flex) */
  }
  #partners.wide {
    display: flex;   /* show partners in body (overwrites display: none) */
  }
  #panel,                                 /* these disappear from layout */
  #header .placeholder,
  .navitem {
    display: none;
  }
  #mainbody {
    grid-column-start: left;         /* mainbody now starts at left edge */
    grid-column-end: right;           /* mainbody now ends at right edge */
  }
  #header h1.menubutton {              /* display the header menu button */
    display: inline;                         /* overwrites display: none */
  }
}

Nebenwege

Die folgenden Dateien enthalten die Logik für sekundäre Routen – About, Advice, Contact usw.

meineapp/routes/about.js

var express = require('express');
var router = express.Router();
router.get("https://www.computerhope.com/", function(req, res, next) {
  res.render('about', { pagetitle: 'About Us' });
});
module.exports = router;

myapp/routes/advice.js

var express = require('express');
var router = express.Router();
router.get("https://www.computerhope.com/", function(req, res, next) {
  res.render('advice', { pagetitle: 'Homesteading Advice' });
});
module.exports = router;

meineapp/routes/contact.js

var express = require('express');
var router = express.Router();
router.get("https://www.computerhope.com/", function(req, res, next) {
  res.render('contact', { pagetitle: 'Contact Us' });
});
module.exports = router;

myapp/routes/recipes.js

var express = require('express');
var router = express.Router();
router.get("https://www.computerhope.com/", function(req, res, next) {
  res.render('recipes', { pagetitle: 'Recipes' });
});
module.exports = router;

myapp/routes/tips.js

var express = require('express');
var router = express.Router();
router.get("https://www.computerhope.com/", function(req, res, next) {
  res.render('tips', { pagetitle: 'Tips For Living Well' });
});
module.exports = router;

Sekundäre Ansichten

Die folgenden Ansichten erben layout.pug.

myapp/views/about.pug

extends layout
block mainbody
  #mainbody
    section#mainbodyitems
      p Alice &amp; Bob have been operating their farm stand since 1992.

myapp/views/advice.pug

extends layout
block mainbody
  #mainbody
    section#mainbodyitems
      h3 Homesteading Advice
      p Never, ever stand behind a heifer.

myapp/views/contact.pug

extends layout
block mainbody
  #mainbody
    section#mainbodyitems
      h3 Alice &amp; Bob
      p 1344 Chattanooga Way
      p Homestead, VT 05401
      p (802) 555-5555

myapp/views/recipes.pug

extends layout
block mainbody
  #mainbody
    section#mainbodyitems
      h3 Alice's Recipes
      p
        b No-knead next-day dutch oven bread
      p.ingredient 1/4 tsp active dry yeast
      p.ingredient 3 cups all-purpose flour
      p.ingredient 1 1/2 tsp salt
      p.ingredient Cornmeal or wheat bran for dusting
      p In a large bowl, dissolve yeast in water.
      p Add the flour and salt, stirring until blended.
      p Cover bowl. Let rest at least 8 hours, preferably 12 to 18, at warm room temperature, about 70 degrees.
      p When the surface of the dough is dotted with bubbles, it's ready to be folded. Lightly flour a work surface. Sprinkle flour on the dough and fold it over on itself once or twice. Cover loosely and let it rest about 15 minutes.
      p Using just enough flour to keep the dough from sticking, gently shape it into a ball. Generously coat a clean dish towel with flour, wheat bran, or cornmeal. Put the seam side of the dough on the towel. Cover with another towel and let rise for 1 to 2 hours.
      p Heat oven to 475&deg;. Cover and bake for 30 minutes.

myapp/views/tips.pug

extends layout
block mainbody
  #mainbody
    section#mainbodyitems
      h3 Alice's Tips
      p Always rise before the sun.
      p Never use fake maple syrup.
      p If the bear is black, be loud, attack.
      p If the bear is brown, play dead, lie down.

Aussehen

Im Hochformat wird über das Menü auf sekundäre Routen zugegriffen.

Hochformat

Im Querformat sind sie über die Kopfzeile und das linke Bedienfeld zugänglich.

Landschaftsansicht

Neueste Artikel
Vielleicht möchten Sie lesen

LEAVE A REPLY

Please enter your comment!
Please enter your name here