Heim > Web-Frontend > js-Tutorial > Von Null bis Storefront: Meine Reise zum Aufbau einer E-Commerce-Site

Von Null bis Storefront: Meine Reise zum Aufbau einer E-Commerce-Site

Susan Sarandon
Freigeben: 2024-11-10 02:54:02
Original
222 Leute haben es durchsucht

Inhalt

  1. Einführung
  2. Tech Stack
  3. Kurzübersicht
  4. API
  5. Frontend
  6. Admin-Dashboard
  7. Ressourcen

Quellcode: https://github.com/aelassas/wexcommerce

Demo: https://wexcommerce.dynv6.net:8002

Einführung

Für Entwickler, die kreative Freiheit und technische Kontrolle schätzen, können traditionelle E-Commerce-Plattformen wie Shopify einschränkend wirken. Während die Vorlagen von Shopify eine schnelle Einrichtung ermöglichen und ihre Storefront-API eine gewisse Flexibilität bietet, bietet keine der beiden Lösungen die vollständige architektonische Freiheit, die sich moderne Entwickler wünschen.

Die Idee entstand aus dem Wunsch heraus, ohne Grenzen zu bauen – eine vollständig anpassbare E-Commerce-Site, bei der jeder Aspekt in Ihrer Kontrolle liegt:

  • Besitzen Sie die Benutzeroberfläche/UX: Entwerfen Sie einzigartige Kundenerlebnisse, ohne gegen Vorlagenbeschränkungen anzukämpfen
  • Kontrollieren Sie das Backend: Implementieren Sie benutzerdefinierte Geschäftslogik und Datenstrukturen, die perfekt zu den Anforderungen passen
  • Master DevOps: Stellen Sie die Anwendung mit bevorzugten Tools und Workflows bereit, skalieren und überwachen Sie sie
  • Frei erweitern: Fügen Sie neue Funktionen und Integrationen ohne Plattformbeschränkungen oder zusätzliche Gebühren hinzu

Tech-Stack

Hier ist der Tech-Stack, der es möglich gemacht hat:

  • Node.js
  • Next.js
  • MongoDB
  • MUI
  • TypeScript
  • Streifen
  • Docker

Eine wichtige Designentscheidung wurde aufgrund seiner zahlreichen Vorteile für die Verwendung von TypeScript getroffen. TypeScript bietet starke Typisierung, Tools und Integration, was zu hochwertigem, skalierbarem, besser lesbarem und wartbarem Code führt, der einfach zu debuggen und zu testen ist.

Ich habe mich für Next.js wegen seiner leistungsstarken Rendering-Funktionen, MongoDB für die flexible Datenmodellierung und Stripe für die sichere Zahlungsabwicklung entschieden.

Wenn Sie sich für diesen Stack entscheiden, bauen Sie nicht nur einen Shop auf – Sie investieren in eine Grundlage, die sich mit Ihren Bedürfnissen weiterentwickeln kann, unterstützt durch robuste Open-Source-Technologien und eine wachsende Entwickler-Community.

Der Aufbau einer Website mit Next.js bietet eine solide Grundlage für die Skalierung eines Unternehmens. Konzentrieren Sie sich auf Leistung, Sicherheit und Benutzererfahrung und bewahren Sie gleichzeitig die Codequalität und Dokumentation. Regelmäßige Updates und Überwachung stellen sicher, dass die Plattform wettbewerbsfähig und zuverlässig bleibt.

Next.js zeichnet sich durch Folgendes als ausgezeichnete Wahl aus:

  • Überragende Leistung: Integrierte Optimierungen für schnelle Seitenladevorgänge und nahtlose Benutzererlebnisse
  • SEO-Vorteile: Serverseitige Rendering-Funktionen, die sicherstellen, dass Ihre Produkte auffindbar sind
  • Skalierbarkeit: Unternehmenstaugliche Architektur, die mit Ihrem Unternehmen wächst
  • Reichhaltiges Ökosystem: Riesige Sammlung von Bibliotheken und Tools für eine schnelle Entwicklung
  • Entwicklererfahrung: Intuitiver Entwicklungsworkflow mit Hot-Reloading und automatischem Routing

Schneller Überblick

Frontend

Vom Frontend aus kann der Benutzer nach verfügbaren Produkten suchen, Produkte in den Warenkorb legen und zur Kasse gehen.

Unten ist die Landingpage des Frontends:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten ist die Suchseite des Frontends:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie eine Beispielproduktseite:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie eine Vollbildansicht der Produktbilder:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten ist die Warenkorbseite:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Checkout-Seite:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Anmeldeseite:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Anmeldeseite:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten ist die Seite, auf der der Benutzer seine Bestellungen sehen kann:

From Zero to Storefront: My Journey Building an E-commerce Site

Das ist es! Das sind die Hauptseiten des Frontends.

Admin-Dashboard

Über das Admin-Dashboard können Administratoren Kategorien, Produkte, Benutzer und Bestellungen verwalten.

Administratoren können auch die folgenden Einstellungen verwalten:

  • Gebietsschemaeinstellungen: Sprache der Plattform (Englisch oder Französisch) und Währung
  • Liefereinstellungen: Aktivierte Liefermethoden und die jeweiligen Kosten
  • Zahlungseinstellungen: Zahlungsmethoden aktiviert (Kreditkarte, Nachnahme oder Überweisung)
  • Bankeinstellungen: Bankinformationen für Überweisungen (IBAN und andere Informationen)

Unten finden Sie die Anmeldeseite:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Dashboard-Seite, auf der Administratoren Bestellungen sehen und verwalten können:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Seite, auf der Administratoren Kategorien verwalten:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Seite, auf der Administratoren Produkte sehen und verwalten können:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Seite, auf der Administratoren Produkte bearbeiten:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie eine Vollbildansicht der Produktbilder:

From Zero to Storefront: My Journey Building an E-commerce Site

Unten finden Sie die Einstellungsseite:

From Zero to Storefront: My Journey Building an E-commerce Site

Das ist es. Das sind die Hauptseiten des Admin-Dashboards.

API

From Zero to Storefront: My Journey Building an E-commerce Site

Die API ist eine Node.js-Serveranwendung, die mithilfe von Express eine RESTful-API bereitstellt, die Zugriff auf die MongoDB-Datenbank ermöglicht.

Die API wird vom Frontend, dem Admin-Dashboard und auch von der mobilen App verwendet.

Die API stellt alle Funktionen bereit, die für das Admin-Dashboard und das Frontend benötigt werden. Die API folgt dem MVC-Entwurfsmuster. Zur Authentifizierung wird JWT verwendet. Es gibt einige Funktionen, die eine Authentifizierung erfordern, wie zum Beispiel Funktionen im Zusammenhang mit der Verwaltung von Produkten und Bestellungen, und andere, die keine Authentifizierung erfordern, wie zum Beispiel das Abrufen von Kategorien und verfügbaren Produkten für nicht authentifizierte Benutzer:

  • ./api/src/models/ Ordner enthält MongoDB-Modelle.
  • ./api/src/routes/-Ordner enthält Express-Routen.
  • ./api/src/controllers/ Ordner enthält Controller.
  • ./api/src/middlewares/ Ordner enthält Middlewares.
  • ./api/src/app.ts ist der Hauptserver, auf den Routen geladen werden.
  • ./api/src/index.ts ist der Haupteinstiegspunkt der API.

index.ts befindet sich auf dem Hauptserver:

import 'dotenv/config'
import process from 'node:process'
import fs from 'node:fs/promises'
import http from 'node:http'
import https, { ServerOptions } from 'node:https'
import * as env from './config/env.config'
import * as databaseHelper from './common/databaseHelper'
import app from './app'
import * as logger from './common/logger'

if (
  await databaseHelper.connect(env.DB_URI, env.DB_SSL, env.DB_DEBUG)
  && await databaseHelper.initialize()
) {
  let server: http.Server | https.Server

  if (env.HTTPS) {
    https.globalAgent.maxSockets = Number.POSITIVE_INFINITY
    const privateKey = await fs.readFile(env.PRIVATE_KEY, 'utf8')
    const certificate = await fs.readFile(env.CERTIFICATE, 'utf8')
    const credentials: ServerOptions = { key: privateKey, cert: certificate }
    server = https.createServer(credentials, app)

    server.listen(env.PORT, () => {
      logger.info('HTTPS server is running on Port', env.PORT)
    })
  } else {
    server = app.listen(env.PORT, () => {
      logger.info('HTTP server is running on Port', env.PORT)
    })
  }

  const close = () => {
    logger.info('Gracefully stopping...')
    server.close(async () => {
      logger.info(`HTTP${env.HTTPS ? 'S' : ''} server closed`)
      await databaseHelper.close(true)
      logger.info('MongoDB connection closed')
      process.exit(0)
    })
  }

  ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => process.on(signal, close))
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Dies ist eine TypeScript-Datei, die einen Server mit Node.js und Express startet. Es importiert mehrere Module, darunter dotenv, Process, fs, http, https, mongoose und app. Anschließend wird eine Verbindung mit der MongoDB-Datenbank hergestellt. Anschließend prüft es, ob die HTTPS-Umgebungsvariable auf „true“ gesetzt ist, und erstellt in diesem Fall mithilfe des https-Moduls und des bereitgestellten privaten Schlüssels und Zertifikats einen HTTPS-Server. Andernfalls wird mithilfe des http-Moduls ein HTTP-Server erstellt. Der Server lauscht auf dem Port, der in der Umgebungsvariablen PORT angegeben ist.

Die Schließfunktion ist so definiert, dass sie den Server ordnungsgemäß stoppt, wenn ein Beendigungssignal empfangen wird. Es schließt den Server und die MongoDB-Verbindung und beendet dann den Prozess mit dem Statuscode 0. Schließlich registriert es die Schließfunktion, die aufgerufen werden soll, wenn der Prozess ein SIGINT-, SIGTERM- oder SIGQUIT-Signal empfängt.

app.ts ist der Haupteinstiegspunkt der API:

import express from 'express'
import compression from 'compression'
import helmet from 'helmet'
import nocache from 'nocache'
import cookieParser from 'cookie-parser'
import i18n from './lang/i18n'
import * as env from './config/env.config'
import cors from './middlewares/cors'
import allowedMethods from './middlewares/allowedMethods'
import userRoutes from './routes/userRoutes'
import categoryRoutes from './routes/categoryRoutes'
import productRoutes from './routes/productRoutes'
import cartRoutes from './routes/cartRoutes'
import orderRoutes from './routes/orderRoutes'
import notificationRoutes from './routes/notificationRoutes'
import deliveryTypeRoutes from './routes/deliveryTypeRoutes'
import paymentTypeRoutes from './routes/paymentTypeRoutes'
import settingRoutes from './routes/settingRoutes'
import stripeRoutes from './routes/stripeRoutes'
import wishlistRoutes from './routes/wishlistRoutes'
import * as helper from './common/helper'

const app = express()

app.use(helmet.contentSecurityPolicy())
app.use(helmet.dnsPrefetchControl())
app.use(helmet.crossOriginEmbedderPolicy())
app.use(helmet.frameguard())
app.use(helmet.hidePoweredBy())
app.use(helmet.hsts())
app.use(helmet.ieNoOpen())
app.use(helmet.noSniff())
app.use(helmet.permittedCrossDomainPolicies())
app.use(helmet.referrerPolicy())
app.use(helmet.xssFilter())
app.use(helmet.originAgentCluster())
app.use(helmet.crossOriginResourcePolicy({ policy: 'cross-origin' }))
app.use(helmet.crossOriginOpenerPolicy())

app.use(nocache())
app.use(compression({ threshold: 0 }))
app.use(express.urlencoded({ limit: '50mb', extended: true }))
app.use(express.json({ limit: '50mb' }))

app.use(cors())
app.options('*', cors())
app.use(cookieParser(env.COOKIE_SECRET))
app.use(allowedMethods)

app.use('/', userRoutes)
app.use('/', categoryRoutes)
app.use('/', productRoutes)
app.use('/', cartRoutes)
app.use('/', orderRoutes)
app.use('/', notificationRoutes)
app.use('/', deliveryTypeRoutes)
app.use('/', paymentTypeRoutes)
app.use('/', settingRoutes)
app.use('/', stripeRoutes)
app.use('/', wishlistRoutes)

i18n.locale = env.DEFAULT_LANGUAGE

await helper.mkdir(env.CDN_USERS)
await helper.mkdir(env.CDN_TEMP_USERS)
await helper.mkdir(env.CDN_CATEGORIES)
await helper.mkdir(env.CDN_TEMP_CATEGORIES)
await helper.mkdir(env.CDN_PRODUCTS)
await helper.mkdir(env.CDN_TEMP_PRODUCTS)

export default app
Nach dem Login kopieren
Nach dem Login kopieren

Zuerst erstellen wir eine Express-App und laden Middlewares wie Cors, Kompression, Helm und Nocache. Mithilfe der Helm-Middleware-Bibliothek haben wir verschiedene Sicherheitsmaßnahmen eingerichtet. Wir importieren auch verschiedene Routendateien für verschiedene Teile der Anwendung, wie z. B. „productRoutes“, „orderRoutes“, „categoryRoutes“, „notificationRoutes“ und „userRoutes“. Zum Schluss laden wir Express-Routen und exportieren die App.

Es gibt 11 Routen in der API. Jede Route verfügt über einen eigenen Controller, der dem MVC-Entwurfsmuster und den SOLID-Prinzipien folgt. Nachfolgend sind die Hauptrouten aufgeführt:

  • userRoutes: Stellt REST-Funktionen für Benutzer bereit
  • categoryRoutes: Bietet REST-Funktionen im Zusammenhang mit Kategorien
  • productRoutes: Bietet REST-Funktionen im Zusammenhang mit Produkten
  • cartRoutes: Bietet REST-Funktionen im Zusammenhang mit Einkaufswagen
  • wishlistRoutes: Bietet REST-Funktionen im Zusammenhang mit Wunschlisten
  • deliveryTypeRoutes: Stellt REST-Funktionen im Zusammenhang mit Zustellungsmethoden bereit
  • paymentTypeRoutes: Bietet REST-Funktionen im Zusammenhang mit Zahlungsmethoden
  • orderRoutes: Bietet REST-Funktionen im Zusammenhang mit Bestellungen
  • notificationRoutes: Bietet REST-Funktionen im Zusammenhang mit Benachrichtigungen
  • settingRoutes: Bietet REST-Funktionen im Zusammenhang mit Einstellungen
  • stripeRoutes: Bietet REST-Funktionen im Zusammenhang mit dem Stripe-Zahlungsgateway

Wir werden nicht jede Route einzeln erklären. Wir nehmen zum Beispiel die KategorieRouten und sehen, wie sie erstellt wurde:

import 'dotenv/config'
import process from 'node:process'
import fs from 'node:fs/promises'
import http from 'node:http'
import https, { ServerOptions } from 'node:https'
import * as env from './config/env.config'
import * as databaseHelper from './common/databaseHelper'
import app from './app'
import * as logger from './common/logger'

if (
  await databaseHelper.connect(env.DB_URI, env.DB_SSL, env.DB_DEBUG)
  && await databaseHelper.initialize()
) {
  let server: http.Server | https.Server

  if (env.HTTPS) {
    https.globalAgent.maxSockets = Number.POSITIVE_INFINITY
    const privateKey = await fs.readFile(env.PRIVATE_KEY, 'utf8')
    const certificate = await fs.readFile(env.CERTIFICATE, 'utf8')
    const credentials: ServerOptions = { key: privateKey, cert: certificate }
    server = https.createServer(credentials, app)

    server.listen(env.PORT, () => {
      logger.info('HTTPS server is running on Port', env.PORT)
    })
  } else {
    server = app.listen(env.PORT, () => {
      logger.info('HTTP server is running on Port', env.PORT)
    })
  }

  const close = () => {
    logger.info('Gracefully stopping...')
    server.close(async () => {
      logger.info(`HTTP${env.HTTPS ? 'S' : ''} server closed`)
      await databaseHelper.close(true)
      logger.info('MongoDB connection closed')
      process.exit(0)
    })
  }

  ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => process.on(signal, close))
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Zuerst erstellen wir einen Express-Router. Dann erstellen wir Routen unter Verwendung ihres Namens, ihrer Methode, Middleware und ihres Controllers.

routeNames enthält die Routennamen der KategorieRoutes:

import express from 'express'
import compression from 'compression'
import helmet from 'helmet'
import nocache from 'nocache'
import cookieParser from 'cookie-parser'
import i18n from './lang/i18n'
import * as env from './config/env.config'
import cors from './middlewares/cors'
import allowedMethods from './middlewares/allowedMethods'
import userRoutes from './routes/userRoutes'
import categoryRoutes from './routes/categoryRoutes'
import productRoutes from './routes/productRoutes'
import cartRoutes from './routes/cartRoutes'
import orderRoutes from './routes/orderRoutes'
import notificationRoutes from './routes/notificationRoutes'
import deliveryTypeRoutes from './routes/deliveryTypeRoutes'
import paymentTypeRoutes from './routes/paymentTypeRoutes'
import settingRoutes from './routes/settingRoutes'
import stripeRoutes from './routes/stripeRoutes'
import wishlistRoutes from './routes/wishlistRoutes'
import * as helper from './common/helper'

const app = express()

app.use(helmet.contentSecurityPolicy())
app.use(helmet.dnsPrefetchControl())
app.use(helmet.crossOriginEmbedderPolicy())
app.use(helmet.frameguard())
app.use(helmet.hidePoweredBy())
app.use(helmet.hsts())
app.use(helmet.ieNoOpen())
app.use(helmet.noSniff())
app.use(helmet.permittedCrossDomainPolicies())
app.use(helmet.referrerPolicy())
app.use(helmet.xssFilter())
app.use(helmet.originAgentCluster())
app.use(helmet.crossOriginResourcePolicy({ policy: 'cross-origin' }))
app.use(helmet.crossOriginOpenerPolicy())

app.use(nocache())
app.use(compression({ threshold: 0 }))
app.use(express.urlencoded({ limit: '50mb', extended: true }))
app.use(express.json({ limit: '50mb' }))

app.use(cors())
app.options('*', cors())
app.use(cookieParser(env.COOKIE_SECRET))
app.use(allowedMethods)

app.use('/', userRoutes)
app.use('/', categoryRoutes)
app.use('/', productRoutes)
app.use('/', cartRoutes)
app.use('/', orderRoutes)
app.use('/', notificationRoutes)
app.use('/', deliveryTypeRoutes)
app.use('/', paymentTypeRoutes)
app.use('/', settingRoutes)
app.use('/', stripeRoutes)
app.use('/', wishlistRoutes)

i18n.locale = env.DEFAULT_LANGUAGE

await helper.mkdir(env.CDN_USERS)
await helper.mkdir(env.CDN_TEMP_USERS)
await helper.mkdir(env.CDN_CATEGORIES)
await helper.mkdir(env.CDN_TEMP_CATEGORIES)
await helper.mkdir(env.CDN_PRODUCTS)
await helper.mkdir(env.CDN_TEMP_PRODUCTS)

export default app
Nach dem Login kopieren
Nach dem Login kopieren

categoryController enthält die Hauptgeschäftslogik in Bezug auf Kategorien. Wir werden nicht den gesamten Quellcode des Controllers sehen, da er recht umfangreich ist, aber wir nehmen zum Beispiel die Funktion zum Erstellen eines Controllers.

Unten finden Sie das Kategoriemodell:

import express from 'express'
import multer from 'multer'
import routeNames from '../config/categoryRoutes.config'
import authJwt from '../middlewares/authJwt'
import * as categoryController from '../controllers/categoryController'

const routes = express.Router()

routes.route(routeNames.validate).post(authJwt.verifyToken, categoryController.validate)
routes.route(routeNames.checkCategory).get(authJwt.verifyToken, categoryController.checkCategory)
routes.route(routeNames.create).post(authJwt.verifyToken, categoryController.create)
routes.route(routeNames.update).put(authJwt.verifyToken, categoryController.update)
routes.route(routeNames.delete).delete(authJwt.verifyToken, categoryController.deleteCategory)
routes.route(routeNames.getCategory).get(authJwt.verifyToken, categoryController.getCategory)
routes.route(routeNames.getCategories).get(categoryController.getCategories)
routes.route(routeNames.getFeaturedCategories).get(categoryController.getFeaturedCategories)
routes.route(routeNames.searchCategories).get(authJwt.verifyToken, categoryController.searchCategories)
routes.route(routeNames.createImage).post([authJwt.verifyToken, multer({ storage: multer.memoryStorage() }).single('image')], categoryController.createImage)
routes.route(routeNames.updateImage).post([authJwt.verifyToken, multer({ storage: multer.memoryStorage() }).single('image')], categoryController.updateImage)
routes.route(routeNames.deleteImage).post(authJwt.verifyToken, categoryController.deleteImage)
routes.route(routeNames.deleteTempImage).post(authJwt.verifyToken, categoryController.deleteTempImage)

export default routes
Nach dem Login kopieren

Eine Kategorie hat mehrere Werte. Ein Wert pro Sprache. Standardmäßig werden Englisch und Französisch unterstützt.

Unten ist das Wertmodell:

export default {
    validate: '/api/validate-category',
    checkCategory: '/api/check-category/:id',
    create: '/api/create-category',
    update: '/api/update-category/:id',
    delete: '/api/delete-category/:id',
    getCategory: '/api/category/:id/:language',
    getCategories: '/api/categories/:language/:imageRequired',
    getFeaturedCategories: '/api/featured-categories/:language/:size',
    searchCategories: '/api/search-categories/:language',
    createImage: '/api/create-category-image',
    updateImage: '/api/update-category-image/:id',
    deleteImage: '/api/delete-category-image/:id',
    deleteTempImage: '/api/delete-temp-category-image/:image',
}
Nach dem Login kopieren

Ein Wert hat einen Sprachcode (ISO 639-1) und einen Zeichenfolgenwert.

Unten finden Sie die Funktion zum Erstellen eines Controllers:

import { Schema, model } from 'mongoose'
import * as env from '../config/env.config'

const categorySchema = new Schema<env.Category>({
  values: {
    type: [Schema.Types.ObjectId],
    ref: 'Value',
    validate: (value: any) => Array.isArray(value),
  },
  image: {
    type: String,
  },
  featured: {
    type: Boolean,
    default: false,
  },
}, {
  timestamps: true,
  strict: true,
  collection: 'Category',
})

const Category = model<env.Category>('Category', categorySchema)

export default Category
Nach dem Login kopieren

In dieser Funktion rufen wir den Hauptteil der Anfrage ab, durchlaufen die im Hauptteil bereitgestellten Werte (ein Wert pro Sprache) und erstellen einen Wert. Abschließend erstellen wir die Kategorie abhängig von den erstellten Werten und der Bilddatei.

Frontend

Das Frontend ist eine Webanwendung, die mit Next.js und MUI erstellt wurde. Über das Frontend kann der Benutzer nach verfügbaren Produkten suchen, diese in den Warenkorb legen und je nach verfügbaren Liefer- und Zahlungsmethoden zur Kasse gehen.

  • ./frontend/public/-Ordner enthält öffentliche Assets.
  • ./frontend/src/styles/ Ordner enthält CSS-Stile.
  • ./frontend/src/components/ Ordner enthält React-Komponenten.
  • ./frontend/src/lang/ enthält Gebietsschemadateien.
  • ./frontend/src/app/-Ordner enthält Next.js-Seiten.
  • ./frontend/src/lib/ enthält Serveraktionen.
  • ./frontend/next.config.ts ist die Hauptkonfigurationsdatei des Frontends.

Das Frontend wurde mit create-next-app:
erstellt

import { Schema, model } from 'mongoose'
import * as env from '../config/env.config'

const locationValueSchema = new Schema<env.Value>(
  {
    language: {
      type: String,
      required: [true, "can't be blank"],
      index: true,
      trim: true,
      lowercase: true,
      minLength: 2,
      maxLength: 2,
    },
    value: {
      type: String,
      required: [true, "can't be blank"],
      index: true,
      trim: true,
    },
  },
  {
    timestamps: true,
    strict: true,
    collection: 'Value',
  },
)

const Value = model<env.Value>('Value', locationValueSchema)

export default Value
Nach dem Login kopieren

In Next.js ist eine Seite eine React-Komponente, die aus einer .js-, .jsx-, .ts- oder .tsx-Datei im Seitenverzeichnis exportiert wird. Jede Seite ist anhand ihres Dateinamens einer Route zugeordnet.

Standardmäßig rendert Next.js jede Seite vorab. Das bedeutet, dass Next.js im Voraus HTML für jede Seite generiert, anstatt alles durch clientseitiges JavaScript erledigen zu lassen. Vorab-Rendering kann zu einer besseren Leistung und SEO führen.

Jeder generierte HTML-Code ist mit dem minimalen JavaScript-Code verknüpft, der für diese Seite erforderlich ist. Wenn eine Seite vom Browser geladen wird, wird deren JavaScript-Code ausgeführt und macht die Seite vollständig interaktiv. (Dieser Vorgang wird als Hydratation bezeichnet.)

Das Frontend nutzt Server-Side Rendering zur SEO-Optimierung, damit Produkte von Suchmaschinen indiziert werden können.

Admin-Dashboard

Das Admin-Dashboard ist eine Webanwendung, die mit Next.js und MUI erstellt wurde. Über das Admin-Dashboard können Administratoren Kategorien, Produkte, Bestellungen und Benutzer verwalten. Wenn eine neue Bestellung erstellt wird, erhält der Admin-Benutzer eine Benachrichtigung und eine E-Mail.

  • ./backend/public/-Ordner enthält öffentliche Assets.
  • ./backend/src/styles/ Ordner enthält CSS-Stile.
  • ./backend/src/components/ Ordner enthält React-Komponenten.
  • ./backend/src/lang/ enthält Gebietsschemadateien.
  • ./backend/src/app/-Ordner enthält Next.js-Seiten.
  • ./backend/src/lib/ enthält Serveraktionen.
  • ./backend/next.config.ts ist die Hauptkonfigurationsdatei des Backends.

Das Admin-Dashboard wurde ebenfalls mit create-next-app erstellt:

import 'dotenv/config'
import process from 'node:process'
import fs from 'node:fs/promises'
import http from 'node:http'
import https, { ServerOptions } from 'node:https'
import * as env from './config/env.config'
import * as databaseHelper from './common/databaseHelper'
import app from './app'
import * as logger from './common/logger'

if (
  await databaseHelper.connect(env.DB_URI, env.DB_SSL, env.DB_DEBUG)
  && await databaseHelper.initialize()
) {
  let server: http.Server | https.Server

  if (env.HTTPS) {
    https.globalAgent.maxSockets = Number.POSITIVE_INFINITY
    const privateKey = await fs.readFile(env.PRIVATE_KEY, 'utf8')
    const certificate = await fs.readFile(env.CERTIFICATE, 'utf8')
    const credentials: ServerOptions = { key: privateKey, cert: certificate }
    server = https.createServer(credentials, app)

    server.listen(env.PORT, () => {
      logger.info('HTTPS server is running on Port', env.PORT)
    })
  } else {
    server = app.listen(env.PORT, () => {
      logger.info('HTTP server is running on Port', env.PORT)
    })
  }

  const close = () => {
    logger.info('Gracefully stopping...')
    server.close(async () => {
      logger.info(`HTTP${env.HTTPS ? 'S' : ''} server closed`)
      await databaseHelper.close(true)
      logger.info('MongoDB connection closed')
      process.exit(0)
    })
  }

  ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => process.on(signal, close))
}
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

Ressourcen

  1. Übersicht
  2. Installation (selbst gehostet)
  3. Installieren (Docker)
    1. Docker-Image
    2. SSL
  4. Stripe einrichten
  5. Von der Quelle ausführen
  6. Demo-Datenbank
    1. Windows, Linux und macOS
    2. Docker
  7. Sprache und Währung ändern
  8. Neue Sprache hinzufügen
  9. Unit-Tests und Abdeckung
  10. Protokolle

Das ist es! Ich hoffe, die Lektüre hat Ihnen gefallen.

Das obige ist der detaillierte Inhalt vonVon Null bis Storefront: Meine Reise zum Aufbau einer E-Commerce-Site. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage