国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

ホームページ ウェブフロントエンド jsチュートリアル ゼロからストアフロントまで: 電子商取引サイトを構(gòu)築する私の旅

ゼロからストアフロントまで: 電子商取引サイトを構(gòu)築する私の旅

Nov 10, 2024 am 02:54 AM

コンテンツ

  1. はじめに
  2. 技術(shù)スタック
  3. 概要
  4. API
  5. フロントエンド
  6. 管理者ダッシュボード
  7. リソース

ソースコード: https://github.com/aelassas/wexcommerce

デモ: https://wexcommerce.dynv6.net:8002

導(dǎo)入

創(chuàng)造的な自由と技術(shù)的な管理を重視する開発者にとって、Shopify のような従來の e コマース プラットフォームは制限があると感じることがあります。 Shopify のテンプレートは迅速なセットアップを提供し、Storefront API はある程度の柔軟性を提供しますが、どちらのソリューションも現(xiàn)代の開発者が切望する完全なアーキテクチャ上の自由を提供するものではありません。

このアイデアは、境界のない構(gòu)築、つまりあらゆる側(cè)面を制御できる完全にカスタマイズ可能な e コマース サイトを構(gòu)築したいという願(yuàn)望から生まれました。

  • UI/UX を所有する: テンプレートの制限と戦うことなく、獨(dú)自の顧客エクスペリエンスをデザインします
  • バックエンドの制御: 要件に完全に一致するカスタム ビジネス ロジックとデータ構(gòu)造を?qū)g裝します
  • マスター DevOps: 優(yōu)先ツールとワークフローを使用してアプリケーションをデプロイ、拡張、監(jiān)視します
  • 自由に拡張: プラットフォームの制約や追加料金なしで、新しい機(jī)能や統(tǒng)合を追加します

技術(shù)スタック

これを可能にした技術(shù)スタックは次のとおりです:

  • Node.js
  • Next.js
  • MongoDB
  • ムイ
  • TypeScript
  • ストライプ
  • ドッカー

TypeScript には多くの利點(diǎn)があるため、設(shè)計(jì)上の重要な決定事項(xiàng)として TypeScript を使用することが決定されました。 TypeScript は強(qiáng)力な型指定、ツール、統(tǒng)合を提供し、その結(jié)果、デバッグとテストが容易な、高品質(zhì)でスケーラブルで読みやすく保守しやすいコードが得られます。

私は強(qiáng)力なレンダリング機(jī)能のために Next.js を、柔軟なデータ モデリングのために MongoDB を、そして安全な支払い処理のために Stripe を選びました。

このスタックを選択すると、単にストアを構(gòu)築するだけではなく、堅(jiān)牢なオープンソース テクノロジーと成長する開発者コミュニティに支えられ、ニーズに合わせて進(jìn)化できる基盤に投資することになります。

Next.js を使用してサイトを構(gòu)築すると、ビジネスを拡大するための強(qiáng)固な基盤が得られます。コードの品質(zhì)とドキュメントを維持しながら、パフォーマンス、セキュリティ、ユーザー エクスペリエンスに重點(diǎn)を置きます。定期的な更新と監(jiān)視により、プラットフォームの競爭力と信頼性が維持されます。

Next.js は、次の理由から優(yōu)れた選択肢として際立っています。

  • 優(yōu)れたパフォーマンス: 高速なページ読み込みとシームレスなユーザー エクスペリエンスを?qū)g現(xiàn)する組み込みの最適化
  • SEO の利點(diǎn): 商品を見つけやすくするサーバー側(cè)のレンダリング機(jī)能
  • スケーラビリティ: ビジネスとともに成長するエンタープライズ対応アーキテクチャ
  • 豊富なエコシステム: 迅速な開発のためのライブラリとツールの膨大なコレクション
  • 開発者エクスペリエンス: ホットリロードと自動(dòng)ルーティングを備えた直感的な開発ワークフロー

概要

フロントエンド

ユーザーはフロントエンドから、利用可能な製品を検索し、カートに製品を追加してチェックアウトできます。

以下はフロントエンドのランディング ページです:

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

以下はフロントエンドの検索ページです:

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

以下はサンプル製品ページです:

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

以下は製品畫像の全畫面表示です:

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

以下はカートページです:

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

以下はチェックアウトページです:

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

以下はサインイン ページです:

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

以下はサインアップページです:

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

以下はユーザーが注文を確認(rèn)できるページです:

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

それだけです!これらはフロントエンドのメインページです。

管理者ダッシュボード

管理者は管理ダッシュボードから、カテゴリ、製品、ユーザー、注文を管理できます。

管理者は次の設(shè)定も管理できます:

  • ロケール設(shè)定: プラットフォームの言語 (英語またはフランス語) と通貨
  • 配信設(shè)定: 有効な配信方法とそれぞれの料金
  • 支払い設(shè)定: 有効な支払い方法 (クレジット カード、代金引換、電信送金)
  • 銀行設(shè)定: 電信送金用の銀行情報(bào) (IBAN およびその他の情報(bào))

以下はサインイン ページです:

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

以下は、管理者が注文を表示および管理できるダッシュボード ページです:

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

以下は管理者がカテゴリを管理するページです:

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

管理者が製品を表示および管理できるページは以下のとおりです:

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

以下は管理者が製品を編集するページです:

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

以下は製品畫像の全畫面表示です:

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

以下は設(shè)定ページです:

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

それだけです。これらは管理者ダッシュボードのメイン ページです。

API

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

この API は、MongoDB データベースへのアクセスを提供する Express を使用して RESTful API を公開する Node.js サーバー アプリケーションです。

API はフロントエンド、管理ダッシュボードによって使用され、モバイル アプリでも同様に使用されます。

API は、管理ダッシュボードとフロントエンドに必要なすべての機(jī)能を公開します。 API は MVC 設(shè)計(jì)パターンに従います。認(rèn)証にはJWTが使用されます。商品や注文の管理に関連する機(jī)能など、認(rèn)証が必要な機(jī)能と、認(rèn)証されていないユーザー向けのカテゴリや利用可能な商品の取得など、認(rèn)証を必要としない機(jī)能があります。

  • ./api/src/models/ フォルダーには MongoDB モデルが含まれています。
  • ./api/src/routes/ フォルダーには Express ルートが含まれています。
  • ./api/src/controllers/ フォルダーにはコントローラーが含まれています。
  • ./api/src/middlewares/ フォルダーにはミドルウェアが含まれています。
  • ./api/src/app.ts はルートがロードされるメインサーバーです。
  • ./api/src/index.ts は API のメイン エントリ ポイントです。

index.ts はメインサーバーにあります:

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))
}

これは、Node.js と Express を使用してサーバーを起動(dòng)する TypeScript ファイルです。 dotenv、process、fs、http、https、mongoose、app などのいくつかのモジュールをインポートします。次に、MongoDB データベースとの接続を確立します。次に、HTTPS 環(huán)境変數(shù)が true に設(shè)定されているかどうかを確認(rèn)し、true に設(shè)定されている場合は、https モジュールと提供された秘密キーと証明書を使用して HTTPS サーバーを作成します。それ以外の場合は、http モジュールを使用して HTTP サーバーを作成します。サーバーは、PORT 環(huán)境変數(shù)で指定されたポートで待機(jī)します。

close 関數(shù)は、終了信號を受信したときにサーバーを正常に停止するように定義されています。サーバーと MongoDB 接続を閉じ、ステータス コード 0 でプロセスを終了します。最後に、プロセスが SIGINT、SIGTERM、または SIGQUIT シグナルを受信したときに呼び出される close 関數(shù)を登録します。

app.ts は 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

まず、Express アプリを作成し、cors、compression、helmet、nocache などのミドルウェアをロードします。ヘルメットミドルウェアライブラリを利用して、さまざまなセキュリティ対策を設(shè)定します。また、productRoutes、orderRoutes、categoryRoutes、notificationRoutes、userRoutes など、アプリケーションのさまざまな部分のさまざまなルート ファイルもインポートします。最後に、Express ルートをロードし、アプリをエクスポートします。

API には 11 のルートがあります。各ルートには、MVC 設(shè)計(jì)パターンと SOLID 原則に従って獨(dú)自のコントローラーがあります。以下は主なルートです:

  • userRoutes: ユーザーに関連する REST 機(jī)能を提供します
  • categoryRoutes: カテゴリに関連する REST 関數(shù)を提供します
  • productRoutes: 製品に関連する REST 関數(shù)を提供します
  • cartRoutes: カートに関連する REST 関數(shù)を提供します
  • wishlistRoutes: ウィッシュリストに関連する REST 関數(shù)を提供します
  • deliveryTypeRoutes: 配信方法に関連する REST 関數(shù)を提供します
  • paymentTypeRoutes: 支払い方法に関連する REST 関數(shù)を提供します
  • orderRoutes: 注文に関連する REST 関數(shù)を提供します
  • notificationRoutes: 通知に関連する REST 関數(shù)を提供します
  • settingRoutes: 設(shè)定に関連する REST 関數(shù)を提供します
  • StripeRoutes: Stripe ペイメントゲートウェイに関連する REST 機(jī)能を提供します

各ルートを一つずつ説明するつもりはありません。たとえば、categoryRoutes を取り上げ、それがどのように作成されたかを見てみましょう:

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))
}

まず、Express Router を作成します。次に、その名前、メソッド、ミドルウェア、コントローラーを使用してルートを作成します。

routeNames には categoryRoutes ルート名が含まれています:

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

categoryController には、カテゴリに関する主要なビジネス ロジックが含まれています。コントローラーのソース コードは非常に大きいため、すべてを見ることはできませんが、コントローラー関數(shù)の作成を例に説明します。

以下はカテゴリモデルです:

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

カテゴリには複數(shù)の値があります。言語ごとに 1 つの値。デフォルトでは、英語とフランス語がサポートされています。

以下は価値モデルです:

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',
}

値には言語コード (ISO 639-1) と文字列値が含まれます。

以下はコントローラー関數(shù)の作成です:

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

この関數(shù)では、リクエストの本文を取得し、本文で指定された値 (言語ごとに 1 つの値) を反復(fù)処理して、値を作成します。最後に、作成した値と畫像ファイルに応じてカテゴリーを作成します。

フロントエンド

フロントエンドは、Next.js と MUI で構(gòu)築された Web アプリケーションです。フロントエンドから、ユーザーは利用可能な商品を検索し、カートに追加し、利用可能な配送方法と支払い方法に応じてチェックアウトに進(jìn)むことができます。

  • ./frontend/public/ フォルダーにはパブリック アセットが含まれています。
  • ./frontend/src/styles/ フォルダーには CSS スタイルが含まれています。
  • ./frontend/src/components/ フォルダーには React コンポーネントが含まれています。
  • ./frontend/src/lang/ にはロケール ファイルが含まれています。
  • ./frontend/src/app/ フォルダーには Next.js ページが含まれています。
  • ./frontend/src/lib/ にはサーバーアクションが含まれます。
  • ./frontend/next.config.ts はフロントエンドのメイン構(gòu)成ファイルです。

フロントエンドは create-next-app で作成されました:

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

Next.js では、ページは、pages ディレクトリ內(nèi)の .js、.jsx、.ts、または .tsx ファイルからエクスポートされた React コンポーネントです。各ページは、ファイル名に基づいてルートに関連付けられます。

デフォルトでは、Next.js はすべてのページを事前レンダリングします。これは、クライアント側(cè)の JavaScript ですべてを?qū)g行するのではなく、Next.js が各ページの HTML を事前に生成することを意味します。プリレンダリングにより、パフォーマンスと SEO が向上します。

生成された各 HTML は、そのページに必要な最小限の JavaScript コードに関連付けられます。ページがブラウザによって読み込まれると、その JavaScript コードが実行され、ページが完全にインタラクティブになります。 (このプロセスを水和といいます。)

フロントエンドは SEO 最適化のためにサーバーサイド レンダリングを使用し、検索エンジンで商品のインデックスを作成できるようにします。

管理者ダッシュボード

管理ダッシュボードは、Next.js と MUI で構(gòu)築された Web アプリケーションです。管理者は管理ダッシュボードから、カテゴリ、製品、注文、ユーザーを管理できます。新しい注文が作成されると、管理者ユーザーは通知を受け取り、電子メールを受け取ります。

  • ./backend/public/ フォルダーにはパブリック アセットが含まれています。
  • ./backend/src/styles/ フォルダーには CSS スタイルが含まれています。
  • ./backend/src/components/ フォルダーには React コンポーネントが含まれています。
  • ./backend/src/lang/ にはロケール ファイルが含まれています。
  • ./backend/src/app/ フォルダーには Next.js ページが含まれています。
  • ./backend/src/lib/ にはサーバーアクションが含まれます。
  • ./backend/next.config.ts はバックエンドのメイン構(gòu)成ファイルです。

管理ダッシュボードも create-next-app で作成されました:

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))
}

リソース

  1. 概要
  2. インストール中 (セルフホスト型)
  3. インストール(Docker)
    1. Docker イメージ
    2. SSL
  4. ストライプのセットアップ
  5. ソースから実行
  6. デモデータベース
    1. Windows、Linux、macOS
    2. ドッカー
  7. 言語と通貨を変更します
  8. 新しい言語を追加
  9. 単體テストとカバレッジ
  10. ログ

それだけです!楽しんで読んでいただければ幸いです。

以上がゼロからストアフロントまで: 電子商取引サイトを構(gòu)築する私の旅の詳細(xì)內(nèi)容です。詳細(xì)については、PHP 中國語 Web サイトの他の関連記事を參照してください。

このウェブサイトの聲明
この記事の內(nèi)容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰屬します。このサイトは、それに相當(dāng)する法的責(zé)任を負(fù)いません。盜作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡(luò)ください。

ホットAIツール

Undress AI Tool

Undress AI Tool

脫衣畫像を無料で

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

寫真から衣服を削除するオンライン AI ツール。

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中國語版

SublimeText3 中國語版

中國語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強(qiáng)力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

node.jsでHTTPリクエストを作成する方法は? node.jsでHTTPリクエストを作成する方法は? Jul 13, 2025 am 02:18 AM

node.jsでHTTPリクエストを開始するには、組み込みモジュール、axios、およびnode-fetchを使用する3つの一般的な方法があります。 1.依存関係のない內(nèi)蔵http/httpsモジュールを使用します。これは基本的なシナリオに適していますが、https.get()を使用してデータを取得したり、.write()を介してPOSTリクエストを送信するなど、データステッチとエラーモニタリングの手動(dòng)処理が必要です。 2.Axiosは、約束に基づいたサードパーティライブラリです。簡潔な構(gòu)文と強(qiáng)力な機(jī)能を備えており、非同期/待ち聲、自動(dòng)JSON変換、インターセプターなどをサポートします。非同期リクエスト操作を簡素化することをお?jiǎng)幛幛筏蓼埂?3.Node-Fetchは、約束と単純な構(gòu)文に基づいて、ブラウザフェッチに似たスタイルを提供します

JavaScriptデータ型:プリミティブ対參照 JavaScriptデータ型:プリミティブ対參照 Jul 13, 2025 am 02:43 AM

JavaScriptデータ型は、プリミティブタイプと參照タイプに分割されます。プリミティブタイプには、文字列、數(shù)字、ブール、ヌル、未定義、シンボルが含まれます。値は不変であり、コピーは値を割り當(dāng)てるときにコピーされるため、互いに影響を與えません。オブジェクト、配列、関數(shù)などの參照タイプはメモリアドレスを保存し、同じオブジェクトを指す変數(shù)は互いに影響します。 TypeofとInstanceOFを使用してタイプを決定できますが、TypeOfNullの歴史的な問題に注意してください。これらの2種類の違いを理解することは、より安定した信頼性の高いコードを書くのに役立ちます。

JavaScript Timeオブジェクト、誰かがEACTEXE、Google Chromeなどのより高速なWebサイトを構(gòu)築します。 JavaScript Timeオブジェクト、誰かがEACTEXE、Google Chromeなどのより高速なWebサイトを構(gòu)築します。 Jul 08, 2025 pm 02:27 PM

こんにちは、JavaScript開発者!今週のJavaScriptニュースへようこそ!今週は、DenoとのOracleの商標(biāo)紛爭、新しいJavaScript Timeオブジェクトがブラウザ、Google Chromeアップデート、およびいくつかの強(qiáng)力な開発ツールによってサポートされています。始めましょう! 「JavaScript」の商標(biāo)を登録しようとするDeno Oracleの試みとのOracleの商標(biāo)紛爭は、論爭を引き起こしました。 Node.jsとDenoの作成者であるRyan Dahlは、商標(biāo)をキャンセルするために請願(yuàn)書を提出しました。

ハンドリングの約束:javascriptのチェーン、エラー処理、および約束の組み合わせ ハンドリングの約束:javascriptのチェーン、エラー処理、および約束の組み合わせ Jul 08, 2025 am 02:40 AM

約束は、JavaScriptで非同期操作を処理するためのコアメカニズムです。チェーンコール、エラー処理、コンビナーの理解は、アプリケーションをマスターするための鍵です。 1.チェーンコールは、.then()を通じて新しい約束を返し、非同期プロセスの連結(jié)を?qū)g現(xiàn)します。それぞれ.then()は以前の結(jié)果を受け取り、値または約束を返すことができます。 2。エラー処理は、.catch()を使用して例外をキャッチしてサイレント障害を回避し、キャッチのデフォルト値を返すためにプロセスを継続する必要があります。 3。promise.all()などの組み合わせ(すべての成功後にのみ成功しました)、promise.race()(最初の完了が返されます)、promise.allsettled()(すべての完了を待っています)

キャッシュAPIとは何ですか?また、サービスワーカーでどのように使用されますか? キャッシュAPIとは何ですか?また、サービスワーカーでどのように使用されますか? Jul 08, 2025 am 02:43 AM

Cacheapiは、ブラウザからネットワークリクエストをキャッシュするツールです。これは、ウェブサイトのパフォーマンスとオフラインエクスペリエンスを改善するために、サービスワーカーと併用することがよくあります。 1.開発者は、スクリプト、スタイルシート、寫真などのリソースを手動(dòng)で保存できるようにします。 2。要求に応じてキャッシュ応答と一致させることができます。 3.特定のキャッシュの削除またはキャッシュ全體のクリアをサポートします。 4.フェッチイベントを聞いているサービスワーカーを介して、キャッシュの優(yōu)先順位またはネットワークの優(yōu)先戦略を?qū)g裝できます。 5.オフラインサポート、繰り返しのアクセス速度の高速化、主要なリソースのプリロード、バックグラウンドアップデートコンテンツによく使用されます。 6.それを使用する場合、キャッシュバージョンの制御、ストレージ制限、およびHTTPキャッシングメカニズムとの違いに注意する必要があります。

JSラウンドアップ:JavaScriptイベントループに深く潛り込む JSラウンドアップ:JavaScriptイベントループに深く潛り込む Jul 08, 2025 am 02:24 AM

JavaScriptのイベントループは、コールスタック、WebAPIS、およびタスクキューを調(diào)整することにより、非同期操作を管理します。 1.コールスタックは同期コードを?qū)g行し、非同期タスクに遭遇すると、処理のためにWebAPIに引き渡されます。 2。WebAPIがバックグラウンドでタスクを完了した後、コールバックを?qū)潖辘工毳濠`(マクロタスクまたはマイクロタスク)に入れます。 3.イベントループは、コールスタックが空であるかどうかをチェックします??栅螆龊稀ⅴ畅`ルバックはキューから取り出され、実行のためにコールスタックに押し込まれます。 4.マイクロタスク(Promise.thenなど)は、マクロタスク(SettimeOutなど)より優(yōu)先されます。 5.イベントループを理解するには、メインスレッドのブロックを避け、コード実行順序を最適化するのに役立ちます。

JavaScript DOMイベントでのイベントの泡立ちとキャプチャの理解 JavaScript DOMイベントでのイベントの泡立ちとキャプチャの理解 Jul 08, 2025 am 02:36 AM

イベントの泡は、ターゲット要素から祖先ノードに外側(cè)に伝播し、イベントキャプチャは外側(cè)の層からターゲット要素に內(nèi)側(cè)に伝播します。 1。イベントバブル:子要素をクリックした後、イベントは親要素のリスナーを上向きにトリガーします。たとえば、ボタンをクリックした後、最初に保育を出してから、親クリックしました。 2。イベントキャプチャ:3番目のパラメーターをtrueに設(shè)定して、リスナーが[親子要素のキャプチャリスナー]をクリックする前に[親要素のキャプチャリスナーをトリガーするなど、キャプチャステージで実行されるようにします。 3.実用的な用途には、子どもの要素イベントの統(tǒng)一された管理、傍受前処理、パフォーマンスの最適化が含まれます。 4. DOMイベントストリームは、キャプチャ、ターゲット、バブルの3つの段階に分割され、デフォルトのリスナーはバブルステージで実行されます。

マップとフィルターを超えて高次関數(shù)のJSラウンドアップ マップとフィルターを超えて高次関數(shù)のJSラウンドアップ Jul 10, 2025 am 11:41 AM

JavaScriptアレイには、Map and Filterに加えて、他の強(qiáng)力で使用されていない方法があります。 1.還元は、合計(jì)するだけでなく、カウント、グループ、フラットンアレイ、新しい構(gòu)造を構(gòu)築することもできます。 2。FindおよびFindIndexは、個(gè)々の要素またはインデックスを見つけるために使用されます。 3.一部とすべてが條件が存在するか、すべての出會いかを判斷するために使用されます。 4.ソートはソートできますが、元の配列を変更します。 5.副作用を避けるために、それを使用するときにアレイをコピーすることに注意してください。これらの方法により、コードがより簡潔で効率的になります。

See all articles