Node.js ve Express kullanarak bir web sitesi nasıl oluşturulur
Bu örnek, mantıksal web sitesi davranışı sağlamak için Node.js kullanan bir web sitesi oluşturur. Express.js çerçevesini kullanan web sitesi, web sitesinin diğer bölümlerine mantıksal yönlendirme ile bir web uygulaması olarak uygulanır.
HTML ve CSS, CSS Grid ve Flexbox kullanan duyarlı web sitesi tasarımımıza dayanmaktadır. HTML bir şablon olarak yeniden düzenlenir, böylece yeni sayfalar eklenirken mizanpaj kodu yeniden kullanılabilir.
Düğüm Yükle
Node olarak da adlandırılan Node.js, JavaScript’te sunucu tarafı uygulamaları yazmak için bir çalışma zamanı ortamıdır.
Node bilgisayarınızda zaten kuruluysa, bu bölümü atlayabilir ve yeni bir Express uygulaması oluşturmaya devam edebilirsiniz.
Node yükleyicisini resmi Node.js indirme web sitesinden indirin. İşletim sisteminiz için LTS (uzun vadeli destek) sürümünü seçin.
Windows ve macOS
Düğüm yükleyiciyi açın ve çalıştırın (Windows’ta .msi, macOS’te .pkg).
Windows’ta, Yerel Modüller için Araçlar etiketli yükleme ekranında Gerekli araçları otomatik olarak yükle kutusunu işaretleyin.
Linux
Linux sistemlerinde, paket yöneticinizi kullanarak Node kurabilir, derlenmiş ikili dosyaları manuel olarak kurabilir veya Node’u kaynaktan oluşturabilirsiniz. Ayrıntılı bilgi için resmi Node.js kurulum wikisine bakın.
Tüm işletim sistemleri
Kurulum tamamlandığında, bir terminal veya komut istemi penceresi açın. Düğüm paket yöneticisi olan npm’yi güncellemek için aşağıdaki komutu çalıştırın. -g (genel) anahtarı, yazılımın yalnızca geçerli Düğüm uygulamasında değil, sistem genelinde yüklendiğini belirtir.
pencereler
npm install -g npm
Linux ve macOS
sudo npm install -g npm
Son olarak, express-generator uygulamasını global olarak kurmak için npm’yi kullanın.
pencereler
npm install -g express-generator
Linux ve macOS
sudo npm install -g express-generator
Yeni bir Express uygulaması yapın
Bir terminal veya komut istemi penceresinde yeni bir Express.js uygulaması oluşturun. Örneğimizde, uygulama adı myapp’dir ve görünüm motoru pug olarak belirtilmiştir.
express myapp --view="pug"
Dizini yeni Express uygulamasıyla değiştirin.
cd myapp
Express uygulama dizininde, package.json dosyasında listelendiği gibi gerekli bağımlılıkları indirmek ve kurmak için npm kurulumunu kullanın.
npm install
Yüklü bağımlılıklar için herhangi bir güvenlik güncellemesi varsa, bir bildirim görüntülenir.
found 1 low severity vulnerability run `npm audit fix` to fix them, or `npm audit` for details
Öyleyse, güvenlik güncellemelerini uygulayın.
npm audit fix
nodemon’u yükle
Express uygulama dizininde nodemon’u yükleyin. –save-dev seçeneği, nodemon’un bir geliştirme bağımlılığı olduğunu gösterir. Uygulamanın kendisinde kullanılmaz, geliştirme sırasında kullanılan bir araçtır.
npm install --save-dev nodemon
Bir geliştirme başlangıç komut dosyası ekleyin
Geliştirme başlatma komut dosyası, ayrıntılı hata mesajları gibi uygulamayı geliştirmenize yardımcı olan seçeneklerle web uygulamanızı başlatmanın bir yolunu sağlar.
Bir metin düzenleyicide, uygulama dizininde package.json dosyasını açın. Bu JSON dosyası, Node uygulamanız tarafından kullanılan bağımlılıkları belirtir. Ayrıca, uygulamayı farklı şekillerde başlatan adlandırılmış başlatma komut dosyaları içerir.
package.json’da “komut dosyaları” girişini bulun. Varsayılan olarak, yalnızca bir komut dosyası (“start”) içerir.
"scripts": { "start": "node ./bin/www" },
Aşağıdaki gibi bir komut dosyası devstart tanımlayan yeni bir satır ekleyin.
Linux ve macOS
"scripts": { "start": "node ./bin/www", "devstart": "DEBUG=myapp:* nodemon ./bin/www" },
pencereler
"scripts": { "start": "node ./bin/www", "devstart": "SET DEBUG=myapp:* & nodemon ./bin/www" },
Bu komut dosyaları (“start” ve “devstart”), npm run scriptname komutu çalıştırılarak çalıştırılabilir.
npm run devstart komutu, uygulamayı iki ek geliştirme özelliği etkinleştirilmiş olarak başlatır.
- DEBUG ortam değişkeni, HTTP 404 gibi konsol günlüğü ve hata sayfalarının yığın izleme gibi ek bilgileri görüntülemesini belirterek ayarlanır.
- Ayrıca, nodemon belirli önemli web sitesi dosyalarını izler. Bir sayfayı yeniden tasarlama veya statik içeriği değiştirme gibi bu dosyaları değiştirirseniz, nodemon değişiklikleri yansıtmak için sunucuyu otomatik olarak yeniden başlatır.
Web sunucusunu geliştirme modunda başlatın.
npm run devstart
Windows Güvenlik Duvarı web sunucusu uygulamasını engelliyorsa, Erişime İzin Ver’i tıklayın.
Web uygulamasını önizleyin
Uygulama çalışırken, bilgisayarınız bir web sunucusu gibi davranır ve 3000 numaralı bağlantı noktasında HTTP sunar.
Web sitesini önizlemek için localhost:3000 adresine bir web tarayıcısı açın.
Yerel ağınıza bağlı herhangi bir cihaz, uygulamayı ipaddress:3000 adresinde görüntüleyebilir; burada ipaddress, uygulamayı çalıştıran bilgisayarın yerel IP adresidir.
Bilgisayarın yerel IP adresinin ne olduğundan emin değilseniz, bakınız: IP adresimi nasıl bulabilirim.
Web sitesini bir mobil cihazda önizlemek için Wi-Fi’sini yerel ağınıza bağlayın ve adresi bir tarayıcıda açın.
HTML şablonları
Örneğimiz, CSS Grid ve Flexbox kullanarak duyarlı bir web sitesinin nasıl oluşturulacağına ilişkin CSS, JavaScript ve HTML’yi kullanır. CSS ve JavaScript kelimesi kelimesine kullanılır. HTML, bir şablonlama diline yeniden düzenlenir.
Bir şablonlama dili kullanarak, düzen kodu yalnızca bir kez yazılır ve diğer sayfalar tarafından devralınır.
Bir şablonu nihai biçimine dönüştüren yazılıma şablon işlemci denir. HTML bağlamında, bir şablon işlemciye görünüm motoru denir.
Express.js, Pug dahil olmak üzere çeşitli görüntüleme motorlarını destekler.
Pug’a Genel Bakış
Pug dili, HTML belgelerini faydalar ve ek özellikler sağlayacak şekilde tanımlar. Pug dosyaları, kullanıcı onları istediğinde HTML’ye dönüştürülür.
Pug’ın dil sözdizimi, etiketlerin kapatılması veya parantez içine alınması ihtiyacını ortadan kaldırır. Ayrıca devralınan şablonları, yinelemeyi, koşulları ve JavaScript değerlendirmesini de destekler.
Örnek HTML’den Pug’a dönüştürme
Bunlar, CSS Grid ve Flexbox kullanarak duyarlı bir web sitesinin nasıl oluşturulacağına ilişkin HTML’nin ilk birkaç satırıdır.
<!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">☰</h1>
Pug’da aynı HTML bu şekilde yazılabilir.
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')") ☰
Eleman etiketleri parantez olmadan yazılır. Alt öğeler girintilidir. Girinti düzeyi, bir öğenin kapsamını belirler, bu nedenle kapanış etiketleri gerekli değildir.
“id” ve “class” CSS seçicileri, element#id, element.class, element#id.class, vb. olarak yazılabilir. Herhangi bir element belirtilmemişse, elementin bir div olduğu varsayılır. Örneğin, HTML’deki
Öğe adı ve seçicilerinden sonra, nitelikler virgülle ayrılmış bir liste olarak parantez içinde belirtilebilir. Örneğin:
HTML
<div class="button" onmouseover="glow()" onclick="start()">
Boksör
.button(onmouseover="glow()", onclick="start()")
Bir satırda birden çok öğe listeleme
Elemanın ardından iki nokta üst üste (:) geliyorsa, onu aynı satırda bir alt eleman takip edebilir. Pug’ın aşağıdaki iki bölümü aynı HTML çıktısını üretir.
a(href="/home") p Home
a(href="https://www.computerhope.com/home"): p Home
Yukarıdakilerin her ikisi de aşağıdaki HTML’ye işlenir.
<a href="https://www.computerhope.com/home"><p>Home</p></a>
JavaScript’i Değerlendirmek
Öğeyi bir eşittir işareti (=) izliyorsa, o satırı takip eden her şey arabelleğe alınmış kod olarak yorumlanır. Kod JavaScript olarak değerlendirilir ve çıktı “arabelleğe alınır” (öğenin içeriği olarak dahil edilir). En basit haliyle, arabelleğe alınmış kod, uygulama tarafından iletilen bir değişkenin adı olabilir.
Örneğin, ana sayfanın uygulama yönlendiricisi olan index.js, “Our Farm Stand” değerine sahip değişken başlığını Pug’a ileten express.Router() yöntemine iletir. Pug layout.pug’u oluşturduğunda aşağıdaki satır:
title= pagetitle
… şu şekilde yorumlanır:
title Our Farm Stand
… aşağıdaki HTML olarak işlenir:
<title>Our Farm Stand</title>
Şablon devralma
Pug belgeleri, genişletme ve engelleme anahtar sözcüklerini kullanarak diğer Pug belgelerini devralabilir.
Örneğin, sayfanın paylaşılan öğeleriyle temel bir web sitesi düzeni, layout.pug oluşturabilirsiniz.
doctype html html head title Page Title body p Content block foo
Blok foo deyimi, “buraya, bu şablonu devralan başka bir Pug belgesinde belirtilen, foo adlı bir içerik bloğu ekleyin” diyor.
layout.pug öğesini devralan belgeler, extension layout layout ifadesi ile başlamalı ve en üst girinti düzeyinde (yeni bir satırın başında) bir blok foo ifadesi içermelidir. Bu “blok foo” ifadesinin alt öğeleri şablona karşılık gelen bloğun bulunduğu yere eklenir.
Bir Pug belgesi, layout.pug öğesini aşağıdaki gibi devralabilir.
extends layout block foo p This is the home page.
Belge işlendiğinde, Pug motoru layout.pug dosyasını yükler. layout.pug’daki foo satır bloğu p ile değiştirilir. Bu, ana sayfadır.
Varsayılan Express uygulamasına genel bakış
Express uygulamasının varsayılan yapısı, her dosya ve dizinin açıklamalarıyla birlikte burada listelenir.
myapp\/ (Contains the entire Express app) ├─ app.js The core logic of the Express app. ├─ bin\/ (Contains the app's executable scripts) │ └─ www A wrapper that runs app.js. ├─ node_modules\/ (Contains dependencies installed by npm) ├─ package-lock.json JSON manifest of installed dependencies. ├─ package.json JSON of dependencies and config specific to your app. ├─ public\/ (Files downloaded by the user's web browser) │ ├─ images\/ (Contains client-accessible image files) │ ├─ javascripts\/ (Contains client-accessible JavaScript files) │ └─ stylesheets\/ (Contains client-accessible CSS) │ └─ style.css The site's CSS stylesheet. ├─ routes\/ (Contains logic for individual site routes) │ ├─ index.js Logic of the "index" route (/). │ └─ users.js Logic of the "users" route (/users). └─ views\/ (Contains HTML templates) ├─ error.pug View displayed for error pages, such as HTML 404. ├─ index.pug View displayed for the site root (/). └─ layout.pug View template of layout shared by all pages.
Web sitesinin temel işlevleri app.js’de tanımlanmıştır. Rotalar bu dosyada adlandırılır ve belirtilir.
Rota, www.example.com/search, www.example.com/login vb. gibi URL’de benzersiz bir yola sahip sitenin bir sayfası veya bölümüdür. Bu rotalar adlandırılır ve rota mantık komut dosyalarıyla ilişkilendirilir, app.js’de.
Rota mantığı komut dosyaları, rotalar klasöründe saklanır. Bir kullanıcı bir rota istediğinde, rota mantığı komut dosyası HTTP istek verilerini işler ve bir yanıt gönderir.
Görünümler klasörü, görünüm motoru (Pug) tarafından işlenen, görünümler adı verilen HTML şablonlarını içerir.
Uygulama: JavaScript, CSS ve Pug
Aşağıdaki kod, Express web uygulamasını uygular.
Uygulama dosyası yapısı
myapp/ ├─ app.js App core logic ├─ bin/ │ └─ www ├─ node_modules/ ├─ package-lock.json ├─ package.json ├─ public/ │ ├─ images/ │ ├─ javascripts/ │ │ └─ menu.js Implements menu toggle │ └─ stylesheets/ │ └─ style.css Stylesheet ├─ routes/ │ ├─ about.js Logic for route /about │ ├─ advice.js Logic for route /advice │ ├─ contact.js Logic for route /contact │ ├─ index.js Logic for route / │ ├─ recipes.js Logic for route /recipes │ ├─ tips.js Logic for route /tips │ └─ users.js Not used, can be deleted └─ views/ ├─ about.pug View for route /about ├─ advice.pug View for route /advice ├─ contact.pug View for route /contact ├─ error.pug ├─ index.pug View for route / ├─ layout.pug View template shared by all pages ├─ recipes.pug View for route /recipes └─ tips.pug View for route /tips blue = modified, green = new, red = not used
uygulamam/app.js
Temel uygulama mantığı, tanımlanmış ek yollar ile, esasen varsayılan Express uygulamasıyla aynıdır. “Kullanıcılar” rotası kaldırıldı.
/\/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;
uygulamam/routes/layout.pug
layout.pug dosyası, sitedeki her sayfa tarafından paylaşılan sayfanın temel düzenini içerir. Ana gövde içeriği (ana gövdeyi engelle) dışında bir sayfayı görüntülemek için gereken her şeyi içerir.
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')") ☰ 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')") ☰ h1.placeholder ☰ 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 © 2020 Alice & Bob's Farm Stand
uygulamam/görünümler/index.pug
index.pug dosyası layout.pug dosyasını genişletir ve \/yolu için ana gövde içeriği içerir.
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–6pm p Celebrate the season with fresh-pressed cider from our orchards. .eventitem h4.title Bread baking workshop p.date December 13, 9am–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
uygulamam/routes/index.js
index.js dosyası \/yolu için mantık içerir.
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;
uygulamam/public/javascripts/menu.js
menu.js dosyası, Grid ve Flexbox örneğindeki JavaScript’i içerir. Menü geçiş işlevini uygular.
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; } }
uygulamam/public/stylesheets/style.css
style.css dosyası, Grid ve Flexbox örneğindeki CSS’yi içerir.
/* 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 */ } }
ikincil yollar
Aşağıdaki dosyalar ikincil yolların mantığını içerir – Hakkında, Tavsiye, İletişim, vb.
uygulamam/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;
uygulamam/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;
uygulamam/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;
uygulamam/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;
ikincil görünümler
Aşağıdaki görünümler layout.pug’u devralır.
uygulamam/views/about.pug
extends layout block mainbody #mainbody section#mainbodyitems p Alice & Bob have been operating their farm stand since 1992.
uygulamam/views/advice.pug
extends layout block mainbody #mainbody section#mainbodyitems h3 Homesteading Advice p Never, ever stand behind a heifer.
uygulamam/görünümler/contact.pug
extends layout block mainbody #mainbody section#mainbodyitems h3 Alice & Bob p 1344 Chattanooga Way p Homestead, VT 05401 p (802) 555-5555
uygulamam/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°. Cover and bake for 30 minutes.
uygulamam/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.
Dış görünüş
Portre modunda, menüde ikincil rotalara erişilir.
Yatay modda bunlara başlıktan ve sol panelden erişilebilir.