سرور مجازی

۱۰ مطلب با کلمه‌ی کلیدی «سرور» ثبت شده است

  • ۰
  • ۰

چگونه با Angular 11 و Scully یک Jamstack Portfolio بسازیم

ورود به سایت

معرفی

به عنوان یک توسعه دهنده، راه های زیادی وجود دارد که می توانید مهارت ها، دستاوردها و کار خود را نشان دهید. اینها شامل مشارکت‌های منبع باز، پروژه‌های شخصی، مشارکت‌های گفتاری، پست‌های وبلاگ، و غیره می‌شوند. با این حال، انجام همه این کارها ممکن است بیهوده باشد، اگر کار شما در چندین پلتفرم پراکنده باشد و وقتی مردم شما را جستجو می‌کنند، پیدا کردن آن دشوار باشد. نداشتن مکانی مرکزی برای نمایش دستاوردهای شما می تواند بر علیه شما کار کند و ممکن است باعث شود مشتریان، استخدام کنندگان و کارفرمایان بالقوه ارزش شما را دست کم بگیرند. پورتفولیو به شما این امکان را می دهد که بهترین کار خود را به جلو بفرستید، دستاوردهای شما را آسان می کند، به شما کمک می کند خود را برندسازی کنید، و ارتباطاتی را که منجر به فرصت های بالقوه پرسود می شود، تسهیل می کند. جفت کردن نمونه کارها با یک وبلاگ به شما ابزاری می دهد تا افکار خود را به اشتراک بگذارید، آنچه را که یاد می گیرید مستند کنید و اعتبار خود را بیشتر بسازید.

با استفاده از طیف گسترده ای از ویژگی های قوی آنها، می توانید یک نمونه کار جذاب و سریع با استفاده از Angular و Scully بسازید. Angular یک پلت فرم همه کاره است که به شما امکان می دهد همه چیز را از وب گرفته تا برنامه های بومی و تلفن همراه ایجاد کنید. ابزارهای مفید مختلفی را ارائه می‌کند که توسعه برنامه را ساده می‌کند و در نتیجه برنامه‌های سریع‌تری با عملکرد عالی ایجاد می‌کند.

برنامه های زاویه ای می توانند حتی با ثابت کردن آنها سریعتر شوند. با استفاده از Scully، می‌توانید برنامه‌های Angular را به برنامه‌های Jamstack با ارائه سریع‌تر تبدیل کنید. Scully یک مولد سایت استاتیک است که یک صفحه HTML ثابت برای هر مسیر در برنامه Angular شما ایجاد می کند. این صفحات سریعتر ارائه می شوند و برای سئو موثر هستند. همچنین ابزارهایی مانند مولد وبلاگ را ارائه می دهد که می توانید با آن وبلاگ نمونه کار خود را بسازید.

در این آموزش با استفاده از Angular 11 و Scully یک نمونه کار و یک وبلاگ می سازید. شما یک برنامه Angular ایجاد می کنید، صفحاتی را برای نمایش پروژه ها و نمایه خود اضافه می کنید و خدماتی را برای پر کردن این صفحات اضافه می کنید. علاوه بر این، شما یک وبلاگ ایجاد می کنید و برای آن پست ایجاد می کنید. در نهایت، شما برنامه را با استفاده از Scully به یک سایت ثابت تبدیل خواهید کرد.

پیش نیازها

برای تکمیل این آموزش شما نیاز دارید:

  • یک محیط توسعه که Node.js نسخه ۱۲ یا بالاتر را اجرا می کند.
  • Angular CLI نصب شده است، که می توانید با دنبال کردن مرحله 1 آموزش شروع با Angular با استفاده از Angular CLI انجام دهید. این آموزش با استفاده از Angular CLI v11.2.14 ساخته شده است. با اجرای دستور: می توانید این نسخه را نصب کنید
    npm -g نصب @angular/cli@11.2.14
  • Chromium نصب شده است (فقط کاربران ویندوز). Scully به Chromium نیاز دارد. اگر از macOS، اوبونتو یا سیستم عامل دیگری استفاده می‌کنید، به‌طور پیش‌فرض، Scully یک نسخه محلی را دانلود می‌کند که اگر قبلاً نصب نشده باشد، از آن برای ارائه یک سایت ثابت استفاده می‌کند. با این حال، اگر از ویندوز استفاده می کنید، باید Chrome را روی WSL نصب کنید، که می توانید با دنبال کردن این راهنما در مورد پیش نیازهای WSL برای Scully این کار را انجام دهید.
  • درک درستی از HTML، CSS، و TypeScript .
  • آشنایی با RxJS که می توانید در مستندات محصول RxJS بیابید.
  • درک درستی از Angular که می توانید در آموزش شروع با Angular CLI بیابید.

مرحله 1 – راه اندازی برنامه Angular

در این مرحله، اپلیکیشن نمونه کارها را با استفاده از Angular CLI تولید خواهید کرد. CLI برنامه را داربست می کند و تمام وابستگی های لازم برای اجرای آن را نصب می کند. سپس وابستگی هایی مانند Bootstrap، Font Awesome و Scully را اضافه خواهید کرد. اسکالی برنامه را ثابت می کند. بوت استرپ اجزا و یک ظاهر طراحی را ارائه می دهد. Font Awesome آیکون ها را عرضه می کند. پس از نصب این وابستگی‌ها، دارایی‌هایی مانند فونت‌ها و فایل‌های JSON را اضافه می‌کنید که حاوی داده‌های نمونه کار شما هستند.

برای شروع، دستور زیر را اجرا کنید تا برنامه تولید شود. به آن پورتفولیو می گویند. این آموزش شامل تست هایی برای برنامه نیست، بنابراین می توانید از پرچم -S برای رد شدن از تولید فایل آزمایشی استفاده کنید. اگر می‌خواهید بعداً آزمایش‌هایی اضافه کنید، می‌توانید این پرچم را حذف کنید.

ng new portfolio -S

وقتی از شما پرسیده شد که آیا می‌خواهید مسیریابی Angular را اضافه کنید، با بله پاسخ دهید. این به ابزار CLI می‌گوید که یک ماژول جداگانه برای مدیریت مسیریابی برنامه ایجاد کند. این در src/app/app-routing.module.ts در دسترس خواهد بود.

همچنین از شما خواسته می شود که یک قالب شیوه نامه را انتخاب کنید. CSS را انتخاب کنید. Angular گزینه های سبک دیگری مانند SCSS، Sass، Less و Stylus را ارائه می دهد. CSS ساده تر است و به همین دلیل است که می خواهید از آن در اینجا استفاده کنید

 

Output

? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS 

 

نصب Dependencies

برای این برنامه به سه وابستگی نیاز دارید: Scully، ng-bootstrap و Font Awesome. اسکالی برنامه Angular را به یک برنامه ثابت تبدیل می کند. وابستگی های دیگر، Bootstrap و Font Awesome، ظاهر و احساس نمونه کارها را سفارشی می کنند. ng-bootstrap کامپوننت‌های Angular را با استفاده از Bootstrap ارائه می‌کند. این به ویژه مفید است زیرا همه اجزای وانیلی Bootstrap با Angular کار نمی کنند. بوت استرپ همچنین میزان استایلی را که باید به برنامه اضافه کنید کاهش می دهد زیرا قبلاً آن را برای شما فراهم کرده است. Font Awesome آیکون ها را عرضه می کند.

هنگامی که Scully را به عنوان یک وابستگی اضافه می کنید، شماتیک اولیه خود را اجرا می کند که تغییراتی را به برنامه شما اضافه می کند تا برای تولید سایت استاتیک آماده شود. از دایرکتوری پروژه خود، از این دستور برای اضافه کردن Scully به پروژه خود استفاده کنید:

ng add @scullyio/init@2.0.0

سپس با استفاده از این دستور ng-bootstrap را اضافه کنید.

ng add @ng-bootstrap/ng-bootstrap@9.1.3

آخرین وابستگی برای اضافه کردن Font Awesome است.

npm install –save @fortawesome/fontawesome-free@5.15.4

اکنون که وابستگی ها اضافه شده اند، آماده اضافه کردن پیکربندی هستید.

اضافه کردن پیکربندی

برای در دسترس قرار دادن Font Awesome برای برنامه، باید یک مرجع به CSS کوچک شده آن در فایل angular.json اضافه کنید. این فایل را می توان در پایه پروژه یافت. با استفاده از nano یا ویرایشگر متن مورد علاقه خود، این فایل را باز کنید:

nano angular.json

در فایل به دنبال بخش architect/build بگردید. این بخش پیکربندی دستور ng build را ارائه می دهد. شما مرجع کوچک شده Font Awesome CSS، node_modules/@fortawesome/fontawesome-free/css/all.min.css را به آرایه سبک ها اضافه می کنید. آرایه سبک ها تحت پروژه ها / نمونه کارها / معمار / ساخت / گزینه ها قرار دارد. خط هایلایت شده را به فایل خود اضافه کنید:

angular.json

{
  ...
  "projects": {
    "portfolio": {
      ...
      "architect": {
        "build": {
          ...
          "options": {
              ...
              "styles": [
                  "node_modules/bootstrap/dist/css/bootstrap.min.css",
                  "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
                  "src/styles.css"
              ],
          }
        },
        ...
      }
    }
  }
}

اکنون Font Awesome در دسترس خواهد بود.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، یک فونت جدید به پروژه اضافه خواهید کرد که می تواند به شخصی سازی ظاهر و احساس نمونه کارها شما کمک کند. می‌توانید با استفاده از فونت‌های Google که طیف وسیعی از فونت‌های موجود را ارائه می‌کند، فونت‌هایی را به پروژه Angular خود اضافه کنید. می توانید با استفاده از تگ پیوند به فونت های انتخاب شده در تگ head پیوند دهید.

در این آموزش از فونت Nunito استفاده خواهید کرد. src/index.html را باز کنید و خطوط مشخص شده در زیر را اضافه کنید:

src/index.html

...
<head>
  <meta charset="utf-8">
  <title>Portfolio</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200;400;800&display=swap" rel="stylesheet">
</head>
...

خطوط برجسته شده به فونت Nunito در فونت های گوگل پیوند دارند. شما آن را در سه وزن دریافت خواهید کرد: بسیار سبک، معمولی و بسیار پررنگ.

ذخیره کنید و فایل را ببندید.

افزودن بیو و داده های پروژه

کاری که انجام می دهید این است که فایل های JSON را ایجاد کنید که تمام داده هایی را که می خواهید در نمونه کار خود قرار دهید در خود نگه می دارد. جداسازی الگوها از داده ها، ایجاد تغییرات و افزودن چیزهای بیشتری را در آینده بدون دستکاری در برنامه آسان تر می کند.

با ایجاد یک پوشه json در src/assets شروع کنید.

mkdir src/assets/json

در پوشه json، دو فایل JSON ایجاد خواهید کرد: bio.json و فایل projects.json. bio.json نمایه ای را که می خواهید در سایت نمایش دهید نگه می دارد. projects.json لیستی از پروژه هایی است که می خواهید به نمایش بگذارید.

ساختار فایل bio.json شبیه به این خواهد بود:

src/assets/json/bio.json

{
    "firstName": "Jane",
    "lastName": "Doe",
    "intro": [ "paragraph 1", "paragraph 2" ],
    "about": [ "paragraph 1", "paragraph 2" ]
}

مقدمه یک مقدمه کوتاه است که در صفحه اصلی نمایش داده می شود. درباره نمایه گسترده تری است که در صفحه «درباره» نشان داده شده است.

برای این آموزش، می توانید از یک نمونه بیو استفاده کنید یا خودتان آن را سفارشی کنید. برای استفاده از نمونه بیو، bio.json را باز کنید و موارد زیر را اضافه کنید:

src/assets/json/bio.json

{
    "firstName": "Jane",
    "lastName": "Doe",
    "intro": [
        "I'm a software developer with a passion for web development. I am currently based somewhere in the world. My main focus is building fast, accessible, and beautiful websites that users enjoy.",
        "You can have a look at some of my work here."
    ],
    "about": [
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam aliquam auctor fringilla. Proin scelerisque lacinia nisl vel ultrices. Ut gravida finibus velit sit amet pulvinar. Nunc nisi arcu, pretium quis ultrices nec, volutpat sit amet nulla. Mauris semper elementum placerat. Aenean velit risus, aliquet quis lectus id, laoreet accumsan erat. Curabitur varius facilisis velit, et rutrum ligula mollis et. Sed imperdiet sit amet urna ut eleifend. Suspendisse consectetur velit nunc, at fermentum eros volutpat nec. Vivamus scelerisque nec turpis volutpat sagittis. Aenean eu sem et diam consequat euismod.",
        "Mauris dolor tellus, sagittis vel pellentesque sit amet, viverra in enim. Maecenas non lectus eget augue convallis iaculis mattis malesuada nisl. Suspendisse malesuada purus et luctus scelerisque. Cras hendrerit, eros malesuada blandit scelerisque, nulla dui gravida arcu, nec maximus nunc felis sit amet mauris. Donec lorem elit, feugiat sit amet condimentum quis, consequat id diam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras rutrum sodales condimentum. Aenean ultrices mi vel augue dapibus mattis. Donec ut ornare nisl. Curabitur feugiat pharetra dictum."
    ]
}

پس از اتمام ویرایش فایل را ذخیره کرده و ببندید.

فایل JSON دیگر، projects.json، ساختاری مشابه این خواهد داشت:

src/assets/json/projects.json

[
    {
        "name": "",
        "stack": {
            "name": "Vue.js",
            "iconClasses": "fab fa-vuejs"
        },
        "description": "",
        "sourceUrl": "",
        "previewUrl": "",
        "featured": false
    }
]

هر پروژه دارای یک نام، توضیحات، یک URL برای جایی که کد منبع آن میزبانی می شود، و یک URL پیش نمایش اگر در جایی مستقر شده باشد. اگر پروژه URL پیش‌نمایش ندارد، می‌توانید آن را حذف کنید.

آبجکت پشته برای نشان دادن زبان یا چارچوبی که پروژه از آن ساخته شده است استفاده می شود. بنابراین نام، نام زبان/فریم ورک خواهد بود و iconClasses کلاس‌های Font Awesome CSS برای نماد زبان/فریم‌ورک هستند. ویژگی برجسته نشان می دهد که آیا پروژه باید در صفحه اصلی نمایش داده شود یا خیر. اگر ویژگی روی false تنظیم شود، به جای نمایش در صفحه اصلی و «پروژه ها» فقط در صفحه «پروژه ها» نمایش داده می شود.

برای این آموزش، می توانید از چند پروژه نمونه استفاده کنید یا پروژه خود را اضافه کنید. برای استفاده از پروژه های نمونه، projects.json را باز کرده و موارد زیر را اضافه کنید:

src/assets/json/projects.json

[
    {
        "name": "Soduko",
        "stack": {
            "name": "Angular",
            "iconClasses": "fab fa-angular"
        },
        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "sourceUrl": "https://github.com",
        "previewUrl": "https://github.com",
        "featured": true
    },
    {
        "name": "E-commerce Store",
        "stack": {
            "name": "React",
            "iconClasses": "fab fa-react"
        },
        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "sourceUrl": "https://github.com",
        "previewUrl": "https://github.com",
        "featured": true
    },
    {
        "name": "Algorithm Visualization App",
        "stack": {
            "name": "Angular",
            "iconClasses": "fab fa-angular"
        },
        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "sourceUrl": "https://github.com",
        "previewUrl": "https://github.com",
        "featured": true
    },
    {
        "name": "Time Tracking CLI App",
        "stack": {
            "name": "Node.js",
            "iconClasses": "fab fa-node-js"
        },
        "description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
        "sourceUrl": "https://github.com",
        "previewUrl": "https://github.com",
        "featured": true
    }
]

ذخیره کنید و فایل را ببندید.

راه اندازی سرور

برای بررسی اینکه برنامه شما مطابق انتظار کار می کند، سرور ارائه شده توسط Angular CLI را با استفاده از این دستور اجرا کنید:

ng serve

این دستور برنامه را می سازد و به آن سرویس می دهد. اگر تغییری ایجاد کنید، آن را بازسازی می کند. پس از تکمیل، برنامه در http://localhost:4200/ ارائه خواهد شد.

مرورگر خود را باز کنید و به http://localhost:4200 بروید. شما باید یک صفحه نگهدارنده را ببینید که به شکل زیر است:

هر بار که تغییری را ذخیره می کنید باید خروجی مشابه این را ببینید:

✔ Browser application bundle generation complete.

Initial Chunk Files           | Names                      |      Size
vendor.js                     | vendor                     |   3.83 MB
styles.css                    | styles                     | 202.25 kB
polyfills.js                  | polyfills                  | 141.85 kB
main.js                       | main                       |  26.08 kB
runtime.js                    | runtime                    |   9.06 kB

                              | Initial Total              |   4.20 MB

Build at:  - Hash:  - Time: 13312ms

** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **

✔ Compiled successfully.

پس از تکمیل یک مرحله، بررسی کنید که ✔ با موفقیت کامپایل شده است. پیام موجود است اگر مشکلی وجود داشته باشد، دستور ng serve یک خطا را خروجی می دهد. وقتی این اتفاق افتاد، مرحله را طی کنید تا مطمئن شوید چیزی را از دست نداده اید یا اشتباهی مرتکب نشده اید. پس از تکمیل آموزش، صفحه اصلی نمونه کارها باید چیزی شبیه به این باشد:

در این مرحله، برنامه را تولید کرده و تمام وابستگی ها، دارایی ها و تنظیمات لازم را اضافه کرده اید. شما همچنین سرور ارائه شده توسط Angular CLI را راه اندازی کرده اید. در مرحله بعد ماژول هسته را ایجاد می کنید.

مرحله 2 – ایجاد ماژول هسته

در این آموزش، اپلیکیشنی که در حال ساخت آن هستید شامل سه ماژول است: هسته، وبلاگ و نمونه کارها. ساختار برنامه به صورت زیر خواهد بود:

src/app

src/app
├── blog
├── core
└── portfolio

ماژول وبلاگ برای صفحات فرود وبلاگ و صفحات پست وبلاگ است. ماژول اصلی شامل همه چیزهای اصلی برنامه است. اینها شامل مولفه هدر، خدمات داده و مدل های داده می شود. ماژول نمونه کارها همه صفحات نمونه کار شما را نگه می دارد: “درباره”، “پروژه ها” و صفحه اصلی.

در این مرحله ماژول هسته را تولید خواهید کرد. همچنین مؤلفه هدر، سرویس ها و مدل های داده را تولید و پر می کنید. هدر در بالای هر صفحه نمایش داده می شود و حاوی نام و منوی سایت است. مدل ها داده های پورتفولیو را ساختار می دهند. خدمات داده های نمونه کارها را واکشی می کنند.

ماژول اصلی باید به این صورت باشد:

src/app/core/

src/app/core
├── header
├── models
└── services

برای تولید ماژول هسته، دستور زیر را از ریشه پروژه اجرا کنید:

ng generate module core

این دستور ماژول هسته را در پوشه src / app / core اضافه می کند و فایل ماژول را در src / app / core / core.module.ts اضافه می کند.

فایل ماژول هسته ماژول اصلی و واردات آن را تعریف می کند. در فایل ماژول جدید ایجاد شده، باید چند import اضافه کنید تا از هدر و سرویس ها پشتیبانی کنید.

core.module.ts را باز کنید و خطوط برجسته شده را اضافه کنید (حتما کاما را بعد از وارد کردن CommonModule وارد کنید):

src/app/core/core.module.ts

...
import { RouterModule } from '@angular/router';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    RouterModule,
    NgbModule,
    HttpClientModule
  ]
})
...

این ماژول از HttpClientModule برای واکشی داده ها از فایل های JSON که قبلا ایجاد کرده اید استفاده می کند. همچنین از چند جزء ng-bootstrap از NgbModule و RouterModule برای مسیریابی استفاده خواهد کرد. همچنین باید آنها را به واردات CoreModule اضافه کنید.

پس از اتمام کار فایل را ذخیره کرده و ببندید.

تولید مدل های داده

در این بخش مدل های داده تولید می کنید. مدل‌های داده رابط‌هایی هستند که برای تعریف ساختار داده‌ها از فایل‌های JSON استفاده می‌کنید. آنها در سرویس ها و در بقیه اجزاء به عنوان انواع بازگشت و پارامتر استفاده خواهند شد. شما به دو مدل نیاز دارید: bio که ساختار داده های زیستی شما را تعریف می کند و پروژه که ساختار داده های پروژه شما را مشخص می کند.

src/app/core/models

src/app/core/models
├── bio.ts
└── project.ts

مدل Bio نمایانگر یک نمایه است در حالی که مدل پروژه پروژه ای برای نمایش است. شما هر دو مدل را با اجرای دستور زیر در ریشه پروژه تولید خواهید کرد:

for model in bio project ; do ng generate interface “core/models/${model}”; done

این دستور از طریق مسیرهای فایل حلقه می زند و آنها را به رابط تولید ng ارسال می کند که آنها را در پوشه src / app / core / models ایجاد می کند.

فایل مدل بیو اطلاعاتی را که می‌خواهید بیو شما حاوی آن باشد، مشخص می‌کند. در فایل src / app / core / models / bio.ts که ایجاد شده است، فیلدهایی را که در زیر برجسته شده اند اضافه کنید.

src/app/core/models/bio.ts

export interface Bio {
    firstName: string;
    lastName: string;
    about: string[];
    intro: string[];
}

در این بلوک کد، فیلدهای نام، نام خانوادگی، درباره و مقدمه را به مدل بیو اضافه کردید. دو فیلد اول از انواع رشته‌ها و دو فیلد آخر آرایه‌هایی از رشته‌ها هستند، زیرا ممکن است حاوی چند پاراگراف باشند.

ذخیره کنید و فایل را ببندید.

فایل پروژه ساختار یک پروژه را تعریف می کند. در اینجا، فیلدهایی را که می خواهید برای هر پروژه استفاده کنید فهرست می کنید. در فایل src / app / core / models / project.ts، خطوط برجسته شده را اضافه کنید.

src/app/core/models/project.ts

export interface Project {
    name: string;
    stack: { iconClasses: string, name: string };
    description: string;
    sourceUrl: string;
    previewUrl: string;
    featured?: boolean;
}

شما فیلدهایی را برای مدل پروژه اضافه کرده اید. هر پروژه دارای یک نام، توضیحات، یک URL برای کد منبع خود و یک URL پیش نمایش است اگر در جایی مستقر شده باشد. آبجکت پشته برای نشان دادن زبان یا چارچوب پروژه استفاده می شود. (نام نام زبان / فریمورک خواهد بود و iconClasses کلاس‌های Font Awesome CSS برای نماد زبان / فریمورک هستند.) ویژگی برجسته نشان می‌دهد که آیا پروژه باید در صفحه اصلی نمایش داده شود یا خیر. اگر ویژگی روی false تنظیم شده باشد، به جای صفحه اصلی و «پروژه‌ها» فقط در صفحه «پروژه‌ها» نمایش داده می‌شود.

پس از اتمام کار فایل را ذخیره کرده و ببندید.

در این قسمت مدل هایی را برای داده ها ایجاد کردید. در مرحله بعد، خدماتی را ایجاد خواهید کرد که داده های نمونه کارها را دریافت کرده و از این مدل ها استفاده می کنند.

تولید خدمات

سرویس‌هایی که در این بخش ایجاد می‌کنید، داده‌های فایل‌های JSON را که قبلاً ساخته‌اید واکشی می‌کنند. هنگامی که آنها این داده ها را واکشی کردند، اجزا می توانند این سرویس ها را فراخوانی کرده و داده ها را مصرف کنند. مدل ها به عنوان انواع برگشتی در این سرویس ها استفاده خواهند شد. مدل bio در سرویس bio و مدل پروژه در سرویس پروژه استفاده می شود. شما یک سرویس هدر اضافی اضافه خواهید کرد که به تصمیم گیری در مورد مسیرهایی که برای موارد موجود در هدر و سایر مؤلفه ها استفاده کنید کمک می کند. ماژول اصلی دارای سه سرویس است: BioService، HeaderService و ProjectsService.

src/app/core/services

src/app/core/services
├── bio.service.ts
├── header.service.ts
└── projects.service.ts

برای تولید این خدمات، این دستور را از دایرکتوری ریشه پروژه اجرا کنید:

for service in bio projects header; do ng generate service “core/services/${service}”; done

این دستور از طریق مسیرهای فایل حلقه می زند و آنها را به سرویس ng generate می دهد که آنها را در پوشه src / app / core / services ایجاد می کند.

سرویس بیو داده‌های زیستی شما را از فایل JSON بیو واکشی می‌کند. برای این کار، روشی برای واکشی این داده ها اضافه می کنید. فایل src / app / core / services / bio.service.ts را باز کنید و خطوط برجسته زیر را اضافه کنید:

src/app/core/services/bio.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Bio } from '../models/bio';

@Injectable({
  providedIn: 'root'
})
export class BioService {

  constructor(private http: HttpClient) { }

  getBio() {
   return this.http.get<Bio>('assets/json/bio.json');
  }
}

روش getBio در BioService بیوگرافی شما را از فایل assets / json / bio.json واکشی می کند. شما سرویس HttpClient را به سازنده آن تزریق می‌کنید و از آن در متد getBio () برای درخواست GET به فایل استفاده می‌کنید.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، HeaderService را تغییر خواهید داد. از سرویس هدر برای بررسی اینکه آیا مسیر فعلی صفحه اصلی است یا خیر استفاده می شود. روشی اضافه خواهید کرد که تعیین می کند صفحه فعلی صفحه اصلی است یا خیر. فایل src / app / core / services / header.service.ts را باز کنید و خطوط برجسته شده را اضافه کنید:

src/app/core/services/header.service.ts

import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter, map, startWith } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class HeaderService {

  constructor(private router: Router) { }

  isHome() {
    return this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
      map(event => {
        if (event instanceof NavigationEnd) {
          if (this.checkForHomeUrl(event.url)) {
            return true;
          }
        }

        return false;
      }),
      startWith(this.checkForHomeUrl(this.router.url))
    );
  }

  private checkForHomeUrl(url: string): boolean {
    return url.startsWith('/#') || url == '/';
  }
}

در HeaderService، روش isHome بررسی می کند که آیا صفحه فعلی که در آن هستید، صفحه اصلی است یا خیر. این برای پیمایش به یک لنگر و نمایش پروژه های برجسته در صفحه اصلی مفید است.

ذخیره کنید و فایل را ببندید.

در نهایت شما ProjectsService را تغییر خواهید داد. سرویس پروژه ها داده های پروژه را از فایل JSON پروژه ها واکشی می کند. روشی برای واکشی داده های پروژه اضافه خواهید کرد. فایل src / app / core / services / projects.service.ts را باز کنید و محتویات را به موارد زیر تغییر دهید:

src/app/core/services/projects.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { filter, mergeAll, toArray } from 'rxjs/operators';
import { Project } from '../models/project';

@Injectable({
  providedIn: 'root'
})
export class ProjectsService {

  constructor(private http: HttpClient) { }

  getProjects(featured?: boolean): Observable<Project[]> {
    let projects$ = this.http.get<Project[]>('assets/json/projects.json');

    if (featured) {
      return projects$.pipe(
        mergeAll(),
        filter(project => project.featured || false),
        toArray()
      );
    }

    return projects$;
  }
}

ProjectsService یک متد getProjects دارد که پروژه ها را دریافت و فیلتر می کند. پروژه ها را از فایل assets / json / projects.json دریافت می کند. شما سرویس HttpClient را به سازنده آن تزریق خواهید کرد و از آن در متد getProjects () برای درخواست GET به فایل استفاده خواهید کرد. با استفاده از پارامتر featured، می توانید انتخاب کنید که فقط پروژه های برجسته را برای اختصار برگردانید. زمانی که می خواهید پروژه های مهم را نشان دهید، در صفحه اصلی مفید است.

ذخیره کنید و فایل را ببندید.

در این بخش، سرویس‌های داده‌های زیستی و پروژه را اضافه کرده‌اید که داده‌های بیو و پروژه را از فایل‌های JSON و پروژه‌ها واکشی می‌کنند. شما همچنین یک سرویس هدر ایجاد کردید که بررسی می کند آیا صفحه فعلی صفحه اصلی است یا خیر. در قسمت بعدی یک هدر ایجاد می کنید که در بالای هر صفحه از نمونه کار شما نمایش داده می شود. از خدمات بیو و هدر استفاده خواهد کرد.

تولید هدر

جزء هدر در بالای همه صفحات نمایش داده می شود. این شامل نام شما و پیوندهایی به صفحات “درباره” و “پروژه ها” و همچنین وبلاگ است. از سرویس بیو و هدر در هدر استفاده خواهد شد. سرویس بیو داده های زیستی را به هدر ارائه می دهد. از سرویس هدر برای بررسی اینکه آیا صفحه فعلی صفحه اصلی است استفاده می شود و پیوندهایی را به بخش ها یا صفحات “درباره” و “پروژه ها” تنظیم می کند. با اجرای این دستور از ریشه پروژه آن را تولید خواهید کرد:

ng generate component core/header

جزء هدر در بالای هر صفحه نمایش داده می شود. از سرویس بیو برای دریافت نام و نام خانوادگی شما استفاده خواهد کرد. همچنین از سرویس هدر برای تعیین اینکه آیا صفحه فعلی صفحه اصلی است یا خیر استفاده می کند. با استفاده از این اطلاعات، پیوندهایی را به بخش‌ها یا صفحات «درباره» و «پروژه‌ها» تنظیم می‌کند.

در فایل header.component.ts، خدمات بیو و هدر را تزریق می‌کنید و یک ویژگی استایلی اضافه می‌کنید تا پاسخگویی مؤلفه در اندازه‌های مختلف صفحه نمایش را کنترل کند.

header.component.ts را باز کنید و خطوط هایلایت شده را اضافه کنید:

src/app/core/header/header.component.ts

import { Component } from '@angular/core';
import { BioService } from '../services/bio.service';
import { HeaderService } from '../services/header.service';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent {
  bio$ = this.bioService.getBio();
  isHome$ = this.headerService.isHome();

  menuItems = [
    { title: 'About Me', homePath: '/', fragment: 'about', pagePath: '/about' },
    { title: 'My Projects', homePath: '/', fragment: 'projects', pagePath: '/projects' },
    { title: 'My Blog', homePath: '/blog', fragment: '', pagePath: '/blog' }
  ];

  constructor(private bioService: BioService, private headerService: HeaderService) { }
}

در این فایل کامپوننت، دو سرویس را تزریق خواهید کرد: bioService برای دریافت نام شما از فایل bio JSON و headerService برای اینکه بفهمید صفحه نمایش داده شده در حال حاضر صفحه اصلی است یا خیر. دومی به شما امکان می دهد تصمیم بگیرید که آیا دکمه ها باید به یک صفحه جداگانه مانند / پروژه ها بروند یا لنگر اسکرول را مانند پروژه / # انجام دهند. menuItems شامل تمام موارد منو برای نمایش است. ویژگی‌های bio $ و isHome $ قابل مشاهده‌هایی از سرویس‌های فوق‌الذکر هستند.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، الگوی کامپوننت هدر را تغییر خواهید داد. اینجا جایی است که داده های واکشی شده از سرویس bio نمایش داده می شود. پیوندهایی به بخش‌ها یا صفحات «درباره» و «پروژه‌ها» نیز در اینجا اضافه می‌شوند. در فایل قالب src / app / core / header / header.component.html کد زیر را اضافه کنید.

src/app/core/header/header.component.html

<div class="d-flex min-vh-10 w-100 justify-content-center pb-3 pt-3 pr-4 pl-4">
    <div class="d-flex justify-content-start" *ngIf="bio$ | async as bio" routerLink="/">
        <h2 class="font-weight-bold">{{bio.firstName}}</h2>
        <h2 class="font-weight-light">{{bio.lastName}}</h2>
    </div>
    <div class="d-none d-md-flex flex-grow-1 justify-content-end align-items-start">
        <button type="button" class="ml-2 mr-2 btn btn-outline-dark border-0 font-weight-bold"
            *ngFor="let item of menuItems" [routerLink]="(isHome$ | async) ? item.homePath : item.pagePath"
            [fragment]="(isHome$ | async) ? item.fragment : ''">{{item.title}}</button>
    </div>
    <div class="d-flex d-md-none justify-content-end flex-grow-1">
        <div ngbDropdown class="d-inline-block" display="dynamic" container="body">
            <button class="btn btn-outline-dark border-0" ngbDropdownToggle>
                <i class="fas fa-lg fa-bars"></i>
            </button>
            <div ngbDropdownMenu class="dropdown-menu dropdown-menu-right">
                <button ngbDropdownItem *ngFor="let item of menuItems"
                    [routerLink]="(isHome$ | async) ? item.homePath : item.pagePath"
                    [fragment]="(isHome$ | async) ? item.fragment : ''">{{item.title}}</button>
            </div>
        </div>
    </div>
</div>

در قالب، نام های شما (bio.firstName و bio.lastName) با استفاده از داده های ویژگی bio نمایش داده می شود. بسته به اندازه صفحه، یک منوی کشویی یا فهرستی از دکمه‌ها از menuItems نشان داده می‌شود. لوله مستعار در الگو لغو اشتراک از موارد مشاهده‌پذیر را کنترل می‌کند. این الگو در طول این آموزش رعایت خواهد شد.

ذخیره کنید و فایل را ببندید.

هدر باید در تمام صفحات قابل مشاهده باشد. برای تحقق این امر، باید چند قدم بردارید. ابتدا، CoreModule باید HeaderComponent را صادر کند تا در دسترس باشد. برای صادر کردن آن، خطوط برجسته شده را به src / app / core / core.module.ts اضافه کنید. فراموش نکنید که کاما را بعد از آرایه واردات اضافه کنید.

src/app/core/core.module.ts

...
@NgModule({
  ...

  imports: [
    ...
  ],
  exports: [ HeaderComponent ]
})
...

برای اینکه هدر قابل مشاهده باشد، باید آن را به قالب AppComponent که در AppModule است نیز اضافه کنید. AppModule همچنین باید CoreModule را وارد کند تا به هدر دسترسی داشته باشد. این وظایف اضافی را در مرحله بعد تکمیل خواهید کرد.

در این مرحله، مدل هایی ایجاد کردید که داده های پورتفولیوی شما را سازماندهی می کند. شما همچنین خدماتی را برای واکشی داده های نمونه کارها با استفاده از مدل ها ایجاد کردید. علاوه بر این، یک سرویس هدر ساخته اید که به تصمیم گیری در مورد مسیرهایی که برای موارد سرصفحه استفاده کنید کمک می کند. در نهایت، شما یک جزء هدر ایجاد کردید تا در تمام صفحات نمونه کارها نمایش داده شود. در مرحله بعد، ماژول نمونه کارها را تولید می کنید که شامل تمام صفحات اولیه نمونه کار شما است. صفحات موجود در ماژول نمونه کارها از خدمات و مدل هایی که در این بخش ایجاد کرده اید، بیو و پروژه ها استفاده می کنند.

مرحله 3 – تولید ماژول نمونه کارها

در مرحله قبل، ماژول اصلی را ایجاد کردید که هدر را نگه می دارد و شامل تمام سرویس ها و مدل هایی است که برای واکشی داده های نمونه کارها استفاده خواهید کرد. در این مرحله ماژول نمونه کارها را تولید می کنید که شامل تمام صفحات ضروری نمونه کارها است. اینها شامل صفحه اصلی، “درباره” و “پروژه ها” است. در این مرحله از خدمات و مدل هایی که در ماژول اصلی ساخته اید برای ایجاد این صفحات استفاده خواهید کرد. همچنین مسیرهایی را برای هر یک از صفحات اضافه خواهید کرد.

صفحه اصلی خلاصه ای از نمایه شما را با استفاده از هدر و خدمات بیو نمایش می دهد. صفحه “درباره” یک نمایه عمیق تر است و از خدمات و مدل بیو استفاده می کند. صفحه “پروژه ها” پروژه های شما را با استفاده از خدمات و مدل پروژه ها برای نمایش پروژه های شما به نمایش می گذارد. در پایان این مرحله، ماژول نمونه کارها شما به صورت زیر ساختار می یابد:

src/app/portfolio

src/app/portfolio
├── about
├── home
└── projects

ابتدا دو ماژول تولید خواهید کرد: یک ماژول نمونه کارها و یک ماژول مسیریابی نمونه کارها. ماژول نمونه کارها شامل تمام صفحات اولیه نمونه کار شما است. ماژول مسیریابی پورتفولیو مسئول مسیریابی به این صفحات است.

برای تولید هر دو ماژول، این دستور را از ریشه پروژه اجرا کنید:

ng generate module portfolio –module app –routing –route portfolio

این دستور پوشه app / portfolio را ایجاد می کند و یک فایل ماژول در app / portfolio / portfolio.module.ts اضافه می کند. این مسیر را در app / src / app-routing.module.ts خواهید دید. پرچم مسیریابی — مشخص می کند که ماژول مسیریابی پورتفولیو تولید شود. این ماژول مسیریابی در app / portfolio / portfolio-routing.module.ts قرار خواهد گرفت.

پرچم –route یک مسیر با بارگذاری تنبل در ماژول برنامه ایجاد می کند، همانطور که توسط پرچم –module مشخص شده است. این مسیر را در app / src / app-routing.module.ts خواهید دید. همچنین یک مولفه نگهدارنده مکان را برای اهداف مسیریابی اضافه می کند که در بخش بعدی مورد بحث قرار می گیرد.

این ماژول نمونه کارها باید در مسیر / موجود باشد. این مستلزم آن است که پرچم –route را با یک رشته خالی، مانند –route = “. با این حال، ماژول تولید ng به رشته های خالی برای پرچم –route اجازه نمی دهد. بنابراین شما مجبور خواهید بود از یک مکان نگهدار، نمونه کار استفاده کنید. سپس این مکان‌نما را با یک رشته خالی در src/app/app-routing.module.ts جایگزین می‌کنید، که مسیریابی کل برنامه را انجام می‌دهد.

src / app / app-routing.module.ts را باز کنید و خطوط هایلایت شده را جایگزین کنید:

src/app/app-routing.module.ts

...
const routes: Routes = [
  {
    path: '',
    loadChildren: () => import('./portfolio/portfolio.module').then(m => m.PortfolioModule)
  }
];
...

این تضمین می کند که تمام صفحات در ماژول نمونه کارها با شروع از مسیر / در دسترس هستند.

ذخیره کنید و فایل را ببندید.

ایجاد صفحه اصلی

دستوری که ماژول پورتفولیو را ایجاد می کند یک PortfolioComponent نیز ایجاد می کند. این یک جزء نگهدارنده مکان است که هنگام تنظیم مسیریابی برای ماژول استفاده می شود. با این حال، نام مناسب‌تر برای این مؤلفه HomeComponent است. صفحه اصلی صفحه فرود نمونه کارها شما است. خلاصه ای از کل مجموعه شما خواهد داشت. این کار باعث می‌شود تا کاربران بدون نیاز به پیمایش به چندین صفحه، دیدی کلی از کار شما داشته باشند و خطر از دست دادن علاقه را کاهش می‌دهد.

برای تغییر نام این کامپوننت، ابتدا یک پوشه جدید برای قرار دادن آن ایجاد خواهید کرد. از ریشه پروژه، دستور زیر را اجرا کنید:

mkdir -p src/app/portfolio/home

در مرحله بعد، تمام فایل های PortfolioComponent را به این پوشه جدید منتقل می کنید.

mv src/app/portfolio/portfolio.component.* src/app/portfolio/home/

این دستور همه فایل‌ها را با نام‌هایی که با portfolio.component شروع می‌شوند، به داخل src/app/portfolio/home/folder منتقل می‌کند.

سپس نام portfolio.component * فایل ها را به home.component تغییر می دهید *.

find src/app/portfolio/home -name ‘portfolio*’ -exec bash -c ‘ mv $0 ${0/\portfolio./home.}’ {} \;

پس از اجرای دستورات بالا، به دلیل تغییر نام و مسیر کامپوننت، با خطاهایی مواجه خواهید شد. برای رفع این مشکل باید در چند فایل تغییراتی ایجاد کنید: ماژول مسیریابی نمونه کارها، ماژول نمونه کارها و فایل های مؤلفه خانگی. در این فایل ها، تمام نمونه های PortfolioComponent را به HomeComponent تغییر خواهید داد. همچنین مسیرها را از ./portfolio.component به ./home/home.component به روز خواهید کرد.

با باز کردن src / app / portfolio / portfolio-routing.module، که مسیریابی ماژول نمونه کارها را انجام می دهد، شروع کنید. تغییرات برجسته شده را انجام دهید:

src/app/portfolio/portfolio-routing.module

...
import { HomeComponent } from './home/home.component';

const routes: Routes = [{ path: '', component: HomeComponent }];
...

ذخیره کنید و فایل را ببندید.

سپس src / app / portfolio / portfolio.module.ts، فایل ماژول نمونه کارها را باز کنید. تغییرات برجسته شده را انجام دهید:

src/app/portfolio/portfolio.module.ts

...
import { HomeComponent } from './home/home.component';


@NgModule({
  declarations: [
    HomeComponent
  ],
  ...
})
...

ذخیره کنید و فایل را ببندید.

در نهایت، src / app / portfolio / home / home.component.ts، فایل کامپوننت خانه را باز کنید. تغییرات برجسته شده را انجام دهید:

src/app/portfolio/home/home.component.ts

...
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
...
}

ذخیره کنید و فایل را ببندید.

در این فایل‌ها، تمام نمونه‌های PortfolioComponent را به HomeComponent تغییر داده‌اید و مسیرها را برای اشاره به HomeComponent به‌روزرسانی کرده‌اید. پس از انجام همه این کارها، ماژول نمونه کارها باید به این شکل باشد.

src/app/portfolio

src/app/portfolio
├── home
│   ├── home.component.css
│   ├── home.component.html
│   └── home.component.ts
├── portfolio-routing.module.ts
└── portfolio.module.ts

اکنون نام ها و مسیرهای فایل های مؤلفه اصلی را به روز کرده اید.

در مرحله بعد، قالب کامپوننت خانه را با محتوا پر می کنید و به آن استایل می دهید. مولفه خانه صفحه اصلی نمونه کارها است و خلاصه مشخصات را نمایش می دهد. (این مؤلفه ای است که در بالا از جزء نمونه کارها به مؤلفه اصلی تغییر نام داده شد.) در این مؤلفه، باید داده های زیستی را برای نمایش واکشی کنید و برای اینکه صفحه در اندازه های مختلف صفحه نمایش پاسخگو باشد، استایلی به آن اضافه کنید.

src/app/portfolio/home/home.component.ts را باز کنید و کد را برای مطابقت با موارد زیر به روز کنید:

src/app/portfolio/home/home.component.ts

import { Component } from '@angular/core';
import { BioService } from '../../core/services/bio.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent {
  bio$ = this.bioService.getBio();

  respOptions = [
    { viewClasses: 'd-none d-md-flex', headingClass: 'display-3', useSmallerHeadings: false },
    { viewClasses: 'd-flex d-md-none', headingClass: '', useSmallerHeadings: true }
  ];

  constructor(private bioService: BioService) { }
}

صفحه اصلی نام شما و یک بیوگرافی کوتاه را نشان می دهد که از BioService که در اینجا تزریق می کنید بازیابی شده است. هنگامی که متد getBio آن را فراخوانی کردید، مشاهده پذیر حاصل در ویژگی bio$ ذخیره می شود. ویژگی respOptions پیکربندی را ذخیره می‌کند که به اطمینان از پاسخگو بودن نما کمک می‌کند.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، الگوی کامپوننت خانه را تغییر خواهید داد. این مسئول نمایش اطلاعات از سرویس bio در اندازه های مختلف صفحه نمایش پاسخگو است. نام خود، معرفی مختصری، و اجزای درباره و پروژه‌ها را اضافه می‌کنید که بعداً پوشش داده خواهد شد.

src/app/portfolio/home/home.component.html را باز کرده و کد زیر را اضافه کنید:

src/app/portfolio/home/home.component.html

<div class="d-flex flex-column justify-content-center align-items-center w-100" *ngIf="bio$ | async as bio">
    <div class="d-flex flex-column min-vh-95 justify-content-center align-items-center w-100">
        <div *ngFor="let options of respOptions" [ngClass]="options.viewClasses"
            class="flex-column justify-content-center align-items-start w-75">
            <h1 [ngClass]="options.headingClass" class="text-left">Hello, 👋. My name is <span
                    class="font-weight-bold">{{bio.firstName+'
                    '+bio.lastName}}.</span></h1>
            <div *ngFor="let par of bio.intro">
                <h2 class="text-left" *ngIf="!options.useSmallerHeadings">{{par}}</h2>
                <h5 class="text-left" *ngIf="options.useSmallerHeadings">{{par}}</h5>
            </div>
            <button class="mt-3 mb-5 btn btn-outline-dark" routerLink="/" fragment="projects">
                See My Work
                <i class="ml-1 fas fa-angle-right"></i>
            </button>
        </div>
    </div>

    <div class="d-none d-md-block mt-5"></div>
    <app-about id="about" class="mb-3"></app-about>

    <div class="d-none d-md-block mt-5"></div>
    <app-projects id="projects" class="mb-5"></app-projects>
</div>

در این الگو، نام‌های bio.firstName+ و +bio.lastName و همچنین یک مقدمه، bio.intro از بیو را نمایش می‌دهید. شما همچنین در مورد مؤلفه app-about و پروژه جزء برنامه-پروژه ها را نشان می دهید که در مرحله بعد تولید خواهید کرد.

src/app/portfolio/home/home.component.html

...
<app-about id="about" class="mb-3"></app-about>

...

<app-projects id="projects" class="mb-5"></app-projects>
...

در مرحله بعد، می توانید یک ظاهر طراحی برای مولفه خانه اضافه کنید. src/app/portfolio/home/home.component.css را باز کنید و این خطوط را اضافه کنید:

src/app/portfolio/home/home.component.css

.min-vh-95 {
    height: 95vh;
}

در اینجا شما یک استایل را به مؤلفه خانه اضافه می کنید تا بین محتوای اصلی صفحه اصلی و لبه های پنجره مرورگر فاصله وجود داشته باشد.

پس از تکمیل، صفحه اصلی به این شکل خواهد بود (در مرحله آخر می توانید پیش نمایش سایت را مشاهده کنید):

 

در این مرحله صفحه اصلی را ایجاد کردید که خلاصه ای از نمونه کارها را نمایش می دهد. در بخش بعدی، اجزای «درباره» و «پروژه» را تولید خواهید کرد. اینها در صفحه اصلی نمایش داده می شوند و به عنوان صفحات مستقل نیز استفاده می شوند.

ایجاد صفحات درباره و پروژه

به جای اینکه هر صفحه را به صورت جداگانه تولید کنید، می توانید یک فرمان را اجرا کنید تا صفحات باقی مانده «پروژه ها» و «درباره» را به یکباره بسازید. این کار را با اجرای دستور زیر از ریشه پروژه انجام می دهید:

for page in about projects; do ng generate component “portfolio/${page}”; done

این دستور از طریق نام هر صفحه حلقه زده و آنها را تولید می کند.

پر کردن صفحه درباره

صفحه “درباره” نمایه عمیق تری از شما نمایش می دهد. اطلاعات این صفحه از سرویس بیو بازیابی شده و از مدل بیو نیز استفاده می کند. این جزء در صفحه اصلی نمایش داده می شود. همچنین یک صفحه مستقل با مسیر خاص خود خواهد بود.

برای پر کردن صفحه «درباره» با بیو خود، فایل مؤلفه «درباره» را برای استفاده از سرویس بیو تغییر دهید. همچنین گزینه هایی را برای پاسخگویی صفحه در نمایشگرهای مختلف تنظیم خواهید کرد. src/app/portfolio/about/about.component.ts را باز کرده و خطوط هایلایت شده را اضافه کنید:

src/app/portfolio/about/about.component.ts

import { Component } from '@angular/core';
import { BioService } from '../../core/services/bio.service';

@Component({
  selector: 'app-about',
  templateUrl: './about.component.html',
  styleUrls: ['./about.component.css']
})
export class AboutComponent {
  bio$ = this.bioService.getBio();

  respOptions = [
    { viewClasses: 'd-none d-md-flex', headingClass: 'display-3', useSmallerHeadings: false },
    { viewClasses: 'd-flex d-md-none', headingClass: '', useSmallerHeadings: true }
  ];

  constructor(private bioService: BioService) { }
}

اطلاعات “درباره” از BioService می آید و پس از فراخوانی متد getBio آن، قابل مشاهده در ویژگی bio$ ذخیره می شود. respOptions با ارائه کلاس های CSS اختیاری برای اندازه های مختلف نمایش به پاسخگویی کمک می کند.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، الگوی صفحه “درباره” را تغییر می دهید تا بتوانید اطلاعات بازیابی شده از سرویس بیو را نمایش دهید. src/app/portfolio/about/about.component.html را باز کنید و خطوط زیر را اضافه کنید:

src/app/portfolio/about/about.component.html

<div class="d-flex justify-content-center vw-90 mx-auto" *ngIf="bio$ | async as bio">
    <div *ngFor="let options of respOptions" [ngClass]="options.viewClasses"
        class="flex-column align-items-center text-center w-75">
        <h1 [ngClass]="options.headingClass" class="mb-5"><span class="font-weight-bold">About</span> Me</h1>
        <div *ngFor="let par of bio.about">
            <h4 *ngIf="!options.useSmallerHeadings" class="mb-4">{{par}}</h4>
            <h5 *ngIf="options.useSmallerHeadings" class="mb-4">{{par}}</h5>
        </div>
    </div>
</div>

در این قالب، داده های موجود در bio$ observable را نمایش می دهید. بخش «درباره» اطلاعات را مرور می‌کنید و آن را به عنوان پاراگراف به صفحه «درباره» اضافه می‌کنید.

ذخیره کنید و فایل را ببندید.

پس از تکمیل، صفحه «درباره» به این شکل خواهد بود (در مرحله آخر می توانید پیش نمایش سایت را مشاهده کنید):

پر کردن صفحه پروژه ها

صفحه “پروژه ها” تمام پروژه های شما را که از سرویس پروژه ها بازیابی شده اند نشان می دهد. این کامپوننت در صفحه اصلی استفاده خواهد شد و همچنین یک صفحه مستقل خواهد بود. در صفحه اصلی همراه با مولفه “درباره” نمایش داده می شود. هنگامی که این مؤلفه در صفحه اصلی استفاده می شود، فقط پروژه های برجسته باید قابل مشاهده باشند. یک دکمه See More Projects وجود دارد که فقط در صفحه اصلی ظاهر می شود. وقتی روی آن کلیک کردید، به صفحه پروژه‌های فهرست کامل هدایت می‌شود.

برای پر کردن صفحه «پروژه‌ها»، فایل مؤلفه آن را برای دریافت پروژه‌ها از سرویس پروژه‌ها تغییر می‌دهید. همچنین از سرویس هدر برای تعیین اینکه آیا همه پروژه ها نمایش داده می شوند یا برجسته شده استفاده خواهید کرد. همچنین گزینه هایی را اضافه می کنید تا صفحه را در اندازه های مختلف صفحه نمایش پاسخگو کنید. src/app/portfolio/projects/projects.component.ts را باز کنید و خطوط هایلایت شده را اضافه کنید:

src/app/portfolio/projects/projects.component.ts

import { Component } from '@angular/core';
import { mergeMap } from 'rxjs/operators';
import { HeaderService } from '../../core/services/header.service';
import { ProjectsService } from '../../core/services/projects.service';

@Component({
  selector: 'app-projects',
  templateUrl: './projects.component.html',
  styleUrls: ['./projects.component.css']
})
export class ProjectsComponent {
  isHome$ = this.headerService.isHome();
  projects$ = this.isHome$.pipe(
    mergeMap(atHome => this.projectsService.getProjects(atHome))
  );

  respOptions = [
    { viewClasses: 'd-none d-md-flex', displayInColumn: false, useSmallerHeadings: false, titleClasses: 'display-3' },
    { viewClasses: 'd-flex d-md-none', displayInColumn: true, useSmallerHeadings: true, titleClasses: '' }
  ];

  constructor(private projectsService: ProjectsService, private headerService: HeaderService) { }
}

پروژه ها از ProjectsService می آیند. برای تعیین اینکه آیا صفحه فعلی صفحه اصلی است یا خیر از HeaderService استفاده خواهید کرد. شما از مقدار isHome$ برای تعیین اینکه آیا لیست کامل پروژه ها را واکشی کنید یا فقط پروژه های برجسته را تعیین کنید، استفاده خواهید کرد.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، الگوی اجزای پروژه را تغییر خواهید داد. با استفاده از پروژه‌هایی که از سرویس پروژه‌ها دریافت کرده‌اید، آنها را حلقه زده و در اینجا اضافه می‌کنید. شما اطلاعات اولیه در مورد هر پروژه را در یک کارت نمایش خواهید داد و پیوندهایی را به جایی که کد آنها میزبانی می شود و جایی که می توانید آنها را پیش نمایش کنید اضافه کنید.

src/app/portfolio/projects/projects.component.html را باز کرده و خطوط زیر را اضافه کنید:

src/app/portfolio/projects/projects.component.html

<div *ngFor="let options of respOptions" [ngClass]="options.viewClasses"
    class="flex-column align-items-center text-center vw-90 mx-auto">
    <h1 [ngClass]="options.titleClasses" class="mb-5"><span class="font-weight-bold">My</span> Projects</h1>
    <div class="d-flex vw-90"
        [ngClass]="{'justify-content-center flex-wrap': !options.displayInColumn, 'flex-column  align-items-center': options.displayInColumn}"
        *ngIf="projects$ | async as projects">
        <div *ngFor="let project of projects" class="card project-card m-3"
            [ngClass]="{'m-3': !options.displayInColumn, 'mb-3': options.displayInColumn}">
            <div class="card-body d-flex flex-column">
                <h5 class="card-title font-weight-bold text-left project-title" [title]="project.name">
                    {{project.name}}
                </h5>
                <h6 class="card-subtitle mb-2 font-weight-lighter text-left">
                    <i [ngClass]="project.stack.iconClasses"></i>
                    {{project.stack.name}}
                </h6>
                <p class="card-text text-left">
                    {{project.description}}
                </p>
                <div class="d-flex flex-row justify-content-start">
                    <a [href]="project.previewUrl" *ngIf="project.previewUrl" class="btn btn-dark mr-2">
                        <i class="fa-lg mr-1 far fa-eye"></i>
                        Preview
                    </a>
                    <a [href]="project.sourceUrl" *ngIf="project.sourceUrl" class="btn btn-dark">
                        <i class="fa-lg mr-1 fab fa-github-alt"></i>
                        Source
                    </a>
                </div>
            </div>
        </div>
    </div>
    <button *ngIf="isHome$ | async" routerLink="/projects" class="mt-3 btn btn-dark">
        See More Projects
        <i class="ml-1 fas fa-angle-right"></i>
    </button>
</div>

در اینجا شما هر پروژه را از پروژه $ به یک کارت اضافه می کنید. در کارت، نام پروژه (project.name)، پشته فناوری استفاده شده در آن (project.stack) و توضیح مختصری (project.description) از کارهایی که انجام می دهد را نمایش می دهید. همچنین پیوندهایی را به جایی که کد پروژه میزبانی شده است اضافه خواهید کرد. علاوه بر این، پیوندی به جایی که پروژه در صورت استقرار آن قابل اجرا باشد، اضافه می‌کنید. در نهایت، دکمه See More Projects وجود دارد که فقط در صفحه اصلی نمایش داده می شود. در صفحه اصلی، فقط پروژه های برجسته نمایش داده می شوند. هنگامی که این دکمه کلیک می شود، کاربر به لیست کاملی از پروژه ها هدایت می شود.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، با تغییر الگوی پروژه ها، به کارت های پروژه استایل می دهید. src/app/portfolio/projects/projects.component.css را باز کنید و خطوط زیر را اضافه کنید:

src/app/portfolio/projects/projects.component.css

.vw-20 {
    width: 20vw;
}

.project-card {
    width: 290px;
    height: 250px;
}

.project-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 20ch;
}

در اینجا، اندازه کارت پروژه و عناوین پروژه را تنظیم می کنید که کمی طولانی تر هستند.

پس از تکمیل، فهرست کامل صفحه «پروژه» به این شکل خواهد بود (در مرحله آخر می‌توانید پیش‌نمایش سایت را مشاهده کنید):

اضافه کردن بقیه مسیرهای نمونه کارها

برای دسترسی به هر صفحه، باید یک مسیر برای هر یک ایجاد کنید. شما اینها را در PortfolioRoutingModule اضافه خواهید کرد که مسیریابی PortfolioModule را انجام می دهد. صفحه “درباره” باید در /about و صفحه “پروژه ها” در /projects موجود باشد.

برای ایجاد مسیرها برای صفحات ماژول نمونه کارها، فایل ماژول مسیریابی پورتفولیو را که مسئول مسیریابی است، تغییر می دهید. src/app/portfolio/portfolio-routing.module.ts را باز کنید و خطوط هایلایت شده را اضافه کنید:

src/app/portfolio/portfolio-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { ProjectsComponent } from './projects/projects.component';
import { AboutComponent } from './about/about.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'projects', component: ProjectsComponent }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class PortfolioRoutingModule { }

در اینجا، با مشخص کردن مسیرهای اجزا و اضافه کردن آنها به آرایه مسیرها، مسیرها را به صفحات «درباره» و «پروژه‌ها» اضافه می‌کنید.

در این مرحله ماژول نمونه کارها را با ایجاد هر یک از سه صفحه آن و اضافه کردن مسیرها برای آنها تکمیل کردید. در مرحله بعد کامپوننت وبلاگ را تولید خواهید کرد.

مرحله 4 – ایجاد ماژول وبلاگ

در این مرحله، ماژول وبلاگ را که حاوی صفحات فرود و پست وبلاگ شما است، تولید می کنید. به جای اینکه وبلاگ را از ابتدا بسازید، از شماتیک اسکالی برای تنظیم تمام موارد مورد نیاز برای یک وبلاگ کارآمد استفاده خواهید کرد. شماتیک اسکالی ماژول را تولید می کند، یک ماژول مسیریابی برای مدیریت مسیریابی به وبلاگ اضافه می کند و یک جزء وبلاگ ایجاد می کند که یک پست وبلاگ را نمایش می دهد. مؤلفه وبلاگ پست هایی را که در فایل های علامت گذاری می نویسید نمایش می دهد. در مرحله بعد با ایجاد پست های وبلاگ جدید، محل این فایل های علامت گذاری را خواهید دید. هنگام رندر کردن وبلاگ، اسکالی نسخه‌های علامت‌گذاری شده پست‌های وبلاگی را که ایجاد کرده‌اید می‌گیرد و آنها را به صفحات HTML ثابت تبدیل می‌کند، که سریع‌تر به خوانندگان ارائه می‌شوند.

می‌توانید پشتیبانی وبلاگ را برای برنامه فعال کنید و با اجرای دستور زیر از ریشه پروژه، ماژول را ایجاد کنید:

ng generate @scullyio/init:blog

دستور بالا ماژول وبلاگ را در src/app/blog ایجاد می‌کند، یک پوشه وبلاگ در پایه پروژه می‌سازد، جایی که فایل‌های علامت‌گذاری وبلاگ در آن قرار می‌گیرند، یک مسیر تنبل برای ماژول در AppRoutingModule اضافه می‌کند و یک جزء وبلاگ در پایه آن ایجاد می‌کند. ماژول

در مرحله بعد، یک پوشه در ماژول ایجاد کنید که مؤلفه وبلاگ در آن قرار دارد.

mkdir src/app/blog/blog

برای انتقال کامپوننت وبلاگ به این پوشه، اجرا کنید:

mv src/app/blog/blog.component.* src/app/blog/blog/

این منجر به ساختار این ماژول وبلاگ می شود:

src/app/blog

src/app/blog
├── blog
│   ├── blog.component.css
│   ├── blog.component.html
│   ├── blog.component.spec.ts
│   └── blog.component.ts
├── blog-routing.module.ts
└── blog.module.ts

از آنجایی که این ماژول بازسازی شده است، برخی از مسیرها شکسته شده و نیاز به به روز رسانی دارند. دو فایل، blog-routing.module.ts و blog.module.ts، باید با مسیرهای جدید به BlogComponent به روز شوند.

blog-routing.module.ts را باز کنید و وارد کردن را مطابق شکل به روز کنید:

src/app/blog/blog-routing.module.ts

...
import { BlogComponent } from './blog/blog.component';
...

ذخیره کنید و فایل را ببندید.

بعد، blog.module.ts را باز کنید و وارد کردن را مطابق شکل به روز کنید:

src/app/blog/blog.module.ts

...
import { BlogComponent } from './blog/blog.component';
...

ذخیره کنید و فایل را ببندید.

در مرحله بعد، الگوی مولفه وبلاگ را اصلاح خواهید کرد. نقش مؤلفه وبلاگ نمایش یک پست وبلاگ است. این مؤلفه به حداقل ویرایش نیاز دارد زیرا شماتیک وبلاگ اسکالی قبلاً آن را پر کرده است. به ظرفی که محتوای پست وبلاگ را در خود جای می دهد، یک ظاهر طراحی می کنید. src/app/blog/blog/blog.component.html را باز کنید و محتوای boilerplate را با خطوط زیر جایگزین کنید:

src/app/blog/blog/blog.component.html

<div class="vw-70">
    <scully-content></scully-content>
</div>

استایلی که به الگو اضافه شده است باعث می‌شود که مولفه وبلاگ با فاصله بهتری در صفحه قرار گیرد. <scully-content></scully-content> محتوای وبلاگ علامت گذاری شده را ارائه می کند.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، با قرار دادن سرفصل‌ها در مرکز، استایل را تغییر می‌دهید، که ظاهر و احساس بهتری را برای مؤلفه وبلاگ ایجاد می‌کند. src/app/blog/blog/blog.component.css را باز کنید و محتوا را با این خطوط جایگزین کنید:

src/app/blog/blog/blog.component.css

h1, h2, h3, h4, h5, h6 {
  text-align: center;
  padding: 1rem;
}

ذخیره کنید و فایل را ببندید.

پس از تکمیل، وبلاگ به این شکل خواهد بود (در مرحله آخر می توانید پیش نمایش سایت را مشاهده کنید):

ایجاد صفحه فرود وبلاگ

اکنون که ماژول وبلاگ را ایجاد کرده اید و استایلی را به پست های وبلاگ اضافه کرده اید، صفحه فرود وبلاگ را ایجاد می کنید و یک استایل به صفحه فرود اضافه می کنید.

صفحه فرود وبلاگ همه پست های وبلاگ شما را فهرست می کند. با اجرای دستور زیر در ریشه پروژه می توانید آن را ایجاد کنید:

ng generate component blog/blog-landing

این به این ساختار منجر می شود:

src/app/blog

src/app/blog
├── blog
│   ├── blog.component.css
│   ├── blog.component.html
│   ├── blog.component.spec.ts
│   └── blog.component.ts
├── blog-landing
│   ├── blog-landing.component.css
│   ├── blog-landing.component.html
│   └── blog-landing.component.ts
├── blog-routing.module.ts
└── blog.module.ts

در مرحله بعد، فایل کامپوننت را برای صفحه فرود وبلاگ تغییر می‌دهید تا همه پست‌های وبلاگ فهرست شود. در اینجا تمام صفحاتی که دارای /blog/ در مسیر خود هستند را دریافت کرده و آنها را در یک لیست نمایش می دهید. همچنین گزینه هایی برای پاسخگو کردن صفحه در اندازه های مختلف صفحه اضافه خواهید کرد.

src/app/blog/blog-landing/blog-landing.component.ts را باز کنید و تغییرات زیر را اعمال کنید:

src/app/blog/blog-landing/blog-landing.component.ts

import { Component } from '@angular/core';
import { ScullyRoute, ScullyRoutesService } from '@scullyio/ng-lib';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-blog-landing',
  templateUrl: './blog-landing.component.html',
  styleUrls: ['./blog-landing.component.css']
})
export class BlogLandingComponent {
  links$ = this.scully.available$.pipe(
    map(routes => routes.filter((route: ScullyRoute) => route.route.startsWith('/blog/')))
  );

  respOptions = [
    { viewClasses: 'd-none d-md-flex', displayInColumn: false, titleClasses: 'display-3' },
    { viewClasses: 'd-flex d-md-none', displayInColumn: true, titleClasses: '' }
  ];

  constructor(private scully: ScullyRoutesService) { }
}

برای دریافت لیستی از تمام مسیرهای وبلاگ، از ScullyRoutesService استفاده خواهید کرد. قابل مشاهده $ موجود، تمام مسیرهایی را که توسط Scully ارائه شده و به عنوان منتشر شده علامت گذاری شده است، برمی گرداند. شما می توانید مشخص کنید که آیا یک پست وبلاگ منتشر شده است یا نه در فایل نشانه گذاری آن. (در مرحله بعدی به این موضوع پرداخته خواهد شد.) این قابل مشاهده همه مسیرها، از جمله مسیرهای موجود در نمونه کارها را برمی گرداند. بنابراین شما فقط مسیرهای حاوی پیشوند /blog/ را فیلتر خواهید کرد. مسیرهای وبلاگ توسط ویژگی links$ نگهداری می شود. ویژگی respOptions به پاسخگویی کمک می کند.

ذخیره کنید و فایل را ببندید.

در مرحله بعد، الگوی صفحه فرود وبلاگ را تغییر می دهید تا همه پست های وبلاگ موجود را در کارت لیست کرده و به آنها پیوند دهید. عنوان وبلاگ را نیز در خود دارد. src/app/blog/blog-landing/blog-landing.component.html را باز کنید و خطوط زیر را اضافه کنید:

src/app/blog/blog-landing/blog-landing.component.html

<div *ngFor="let options of respOptions" [ngClass]="options.viewClasses"
    class="flex-column align-items-center text-center vw-90 mx-auto">
    <h1 [ngClass]="options.titleClasses" class="mb-5"><span class="font-weight-bold">Jane's</span> Blog</h1>
    <div [ngClass]="{'justify-content-center flex-wrap': !options.displayInColumn,  'flex-column align-items-center': options.displayInColumn}"
        class="d-flex vw-90">
        <div *ngFor="let page of links$ | async" class="card post-card m-3">
            <div class="card-img-top bg-dark">
                <i class="far fa-newspaper fa-4x m-5 text-white"></i>
            </div>
            <div class="card-body d-flex flex-column">
                <h5 class="card-title post-title" [title]="page.title">{{page.title}}</h5>
                <p class="card-text post-description flex-grow-1">{{page.description}}</p>
                <a [routerLink]="page.route" class="btn btn-outline-dark align-self-center">
                    <i class="fa-lg mr-1 far fa-eye"></i>
                    Read
                </a>
            </div>
        </div>
    </div>
</div>

در این الگو، تمام پست‌های وبلاگی را که توسط سرویس روتر اسکالی برگردانده شده است، مرور خواهید کرد. برای هر پست وبلاگ، یک کارت اضافه می کنید. در هر کارت عنوان پست وبلاگ و توضیحات نمایش داده می شود. همچنین یک لینک اضافه شده است که می توانید روی آن کلیک کنید تا به پست وبلاگ بروید.

ذخیره کنید و فایل را ببندید.

در نهایت، یک استایل به قالب فرود وبلاگ اضافه خواهید کرد. به کارت های پروژه ای که به صفحه اضافه می شوند استایل می دهد. src/app/blog/blog-landing/blog-landing.component.css را باز کنید و خطوط زیر را اضافه کنید:

src/app/blog/blog-landing/blog-landing.component.css

.post-card {
    width: 290px;
    height: 360px;
}

.post-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 20ch;
}

ذخیره کنید و فایل را ببندید.

پس از تکمیل (و پس از افزودن پست های وبلاگ)، صفحه فرود وبلاگ به این شکل خواهد بود (در مرحله آخر می توانید پیش نمایش سایت را مشاهده کنید):

افزودن مسیر فرود بلاگ

برای دسترسی به صفحه فرود وبلاگ در مسیر /blog، باید یک مسیر برای آن در BlogRoutingModule اضافه کنید. بدون افزودن این، برای برنامه در دسترس نخواهد بود. src/app/blog/blog-routing.module.ts را باز کنید و خطوط هایلایت شده را اضافه کنید:

src/app/blog/blog-routing.module.ts

...
import { BlogLandingComponent } from './blog-landing/blog-landing.component';

const routes: Routes = [
  { path: '', component: BlogLandingComponent },
  { path: ':slug', component: BlogComponent },
  { path: '**', component: BlogComponent }
];
...

در اینجا شما مسیر BlogLandingComponent را به آرایه مسیرها اضافه کردید. این باعث می شود که در مسیر /blog قابل دسترسی باشد.

ذخیره کنید و فایل را ببندید.

در این مرحله، یک ماژول وبلاگ ایجاد کردید که شامل دو صفحه است: یک صفحه پست وبلاگ و یک صفحه فرود وبلاگ. شما یک سبک به این صفحات اضافه کردید و مسیر فرود وبلاگ را اضافه کردید تا صفحه فرود در مسیر وبلاگ / قابل دسترسی باشد. در مرحله بعد، پست های جدید وبلاگ را اضافه خواهید کرد.

مرحله 5 – اضافه کردن پست های جدید وبلاگ

در این مرحله از Scully برای ایجاد پست های وبلاگ جدید که در صفحه فرود وبلاگ نمایش داده می شوند استفاده خواهید کرد. با Scully، می توانید فایل های علامت گذاری ایجاد کنید که به عنوان پست های وبلاگ شما خدمت می کنند. مؤلفه وبلاگی که در مرحله قبل ایجاد کردید، نسخه علامت گذاری شده یک پست وبلاگ را می خواند و سپس آن را نمایش می دهد. Markdown نوشتن محتوای وبلاگ با فرمت غنی را به سرعت و به راحتی آسان می کند. Scully این فایل‌ها را ایجاد می‌کند و پوشه‌هایی را نیز اضافه می‌کند تا آنها را برای شما در خود جای دهد. همچنین ابرداده مانند عنوان و توضیحات را به هر پست اضافه می کند. برخی از ابرداده ها برای تعیین نحوه نمایش یک پست استفاده می شود. بعداً، از Scully برای تولید نسخه‌های صفحه HTML ایستا از این پست‌های وبلاگ علامت‌گذاری شده استفاده خواهید کرد.

قبل از اینکه بتوانید یک پست ایجاد کنید، باید یک نام بیاورید. برای این آموزش، یک پست با عنوان “پست وبلاگ 1” ایجاد خواهید کرد. شما این نام را با استفاده از پرچم –name از ریشه پروژه به دستور زیر ارائه می دهید.

ng generate @scullyio/init:post –name=”Blog Post 1″

خروجی شبیه به این خواهد بود:

 

Output

? What's the target folder for this post? blog
    ✅️ Blog ./blog/blog-post-1.md file created
CREATE blog/blog-post-1.md (103 bytes)

با این کار یک فایل /blog/blog-post-1.md در ریشه پروژه ایجاد می شود. محتویات فایل مشابه این خواهد بود:

blog/blog-post-1.md

---
title: Blog Post 1
description: blog description
published: false
---

# Blog Post 1

هنگامی که محتوایی را به پست وبلاگ خود اضافه کردید و از آن راضی بودید، می توانید محتوای منتشر شده را به درست تغییر دهید و هنگامی که سایت را ارائه می کنید در صفحه فرود وبلاگ ظاهر می شود. برای مشاهده پست هایی که هنوز منتشر نشده اند، می توانید از ویژگی Slug استفاده کنید.

به عنوان مثال، فرض کنید این slug را اضافه کرده اید:

blog/blog-post-1.md

---
title: Blog Post 1
description: blog description
published: true
slug: alternate-url-for-blog-post-1
---

# Blog Post 1

هنگامی که سرور را اجرا می کنید، می توانید این پست را در https://localhost:1668/blog/alternate-url-for-blog-post-1 مشاهده کنید. با این حال، این پست منتشر نشده در صفحه فرود وبلاگ نشان داده نمی شود مگر اینکه به عنوان منتشر شده علامت گذاری شود: درست است. هنگامی که مسیرهای اسکالی را ایجاد می کنید، همانطور که در مرحله بعد خواهید دید، اسکالی یک اسلاگ برای همه پست های منتشر نشده شما اضافه می کند تا مجبور نباشید.

برای افزودن محتوا به پست خود، بعد از عنوان شروع کنید. تمام محتوای پست باید در علامت گذاری باشد. در اینجا نمونه ای از محتوایی است که می توانید در پست علامت گذاری که ایجاد کرده اید استفاده کنید:

/blog/blog-post-1.md

---
title: Blog Post 1
description: Your first blog post
published: true
---

# Blog Post 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vitae tempor erat, eget accumsan lorem. Ut id sem id massa mattis dictum ullamcorper vitae massa. In luctus neque lectus, quis dictum tortor elementum sit amet. Mauris non lacinia nisl. Nulla tristique arcu quam, quis posuere diam elementum nec. Curabitur in mi ut purus bibendum interdum ut sit amet orci. Duis aliquam tristique auctor. Suspendisse magna magna, pellentesque vitae aliquet ac, sollicitudin faucibus est. Integer semper finibus leo, eget placerat enim auctor quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Sed aliquam nibh in mi convallis mattis nec ac mi. Nam sed sagittis purus.

پس از اتمام، فایل را ذخیره کرده و ببندید.

با اجرای زیر می توانید پست های دیگری ایجاد کنید:

ng generate @scullyio/init:post –name=”Blog Post 2″
ng generate @scullyio/init:post –name=”Blog Post 3″

این دستورات دو فایل علامت گذاری دیگر را در پوشه /blog/ با نام هایی که شما اختصاص داده اید ایجاد می کند. می توانید مانند پست اول فایل های تولید شده را با محتوای نمونه بالا پر کنید.

در این مرحله، شما اولین پست وبلاگ اسکالی خود را ایجاد کردید. مرحله زیر تغییراتی را که باید برای تکمیل برنامه انجام دهید را پوشش می دهد.

مرحله 6 – فعال کردن Anchor Scrolling و پاک کردن الگوی مؤلفه برنامه

آخرین کاری که باید قبل از پیش‌نمایش برنامه انجام دهید، فعال کردن لنگر اسکرول، اضافه کردن استایل سراسری، و تمیز کردن app.component.html است.

در صفحه اصلی، زمانی که یک بازدیدکننده روی موارد موجود در هدر کلیک می کند، باید به بخش های خاص در همان صفحه هدایت شوند. برای انجام این کار، باید انکر اسکرول را در اپلیکیشن Angular فعال کنید. انجام همه این تغییرات اسکرول به بخش های صفحه اصلی را ممکن می کند.

ابتدا فایل ماژول را برای ماژول مسیریابی برنامه تغییر می دهید. این ماژول مسئول مسیریابی در کل برنامه است. در اینجا اسکرول لنگر را فعال خواهید کرد. src/app/app-routing.module.ts را باز کنید و قسمت برجسته شده را اضافه کنید:

src/app/app-routing.module.ts

...
@NgModule({
  imports: [RouterModule.forRoot(routes, { anchorScrolling: 'enabled' })],
  exports: [RouterModule]
})
...

آخرین کاری که باید قبل از پیش‌نمایش برنامه انجام دهید، فعال کردن لنگر اسکرول، اضافه کردن استایل سراسری، و تمیز کردن app.component.html است.

در صفحه اصلی، زمانی که یک بازدیدکننده روی موارد موجود در هدر کلیک می کند، باید به بخش های خاص در همان صفحه هدایت شوند. برای انجام این کار، باید انکر اسکرول را در اپلیکیشن Angular فعال کنید. انجام همه این تغییرات اسکرول به بخش های صفحه اصلی را ممکن می کند.

ابتدا فایل ماژول را برای ماژول مسیریابی برنامه تغییر می دهید. این ماژول مسئول مسیریابی در کل برنامه است. در اینجا اسکرول لنگر را فعال خواهید کرد. src/app/app-routing.module.ts را باز کنید و قسمت برجسته شده را اضافه کنید:

از آنجایی که به این محتوای نگهدارنده در پورتفولیوی خود نیاز نخواهید داشت، آن را حذف خواهید کرد.

برای حذف کد متغیر ایجاد شده از صفحه اصلی، src/app/app.component.html را باز کنید و محتوای آن را با خطوط زیر جایگزین کنید:

src/app/app.component.html

<div class="d-flex flex-column h-100 w-100">
    <app-header></app-header>
    <div class="d-flex flex-column flex-grow-1 align-items-center justify-content-center">
        <router-outlet></router-outlet>
    </div>
</div>

در این فایل، app-header، کامپوننت هدر را اضافه می‌کنید و یک div کانتینری در اطراف خروجی روتر قرار می‌دهید تا صفحات مسیریابی شده در زیر آن نمایش داده شوند.

در مرحله بعد، باید مطمئن شوید که AppModule به app-header دسترسی دارد. از آنجایی که app-header در ماژول دیگری وجود دارد، App Module در حال حاضر به آن دسترسی ندارد. شما باید CoreModule را به عنوان import به src/app/app.module.ts اضافه کنید زیرا CoreModule دسترسی به مولفه هدر را فراهم می کند. app.module.ts را باز کنید و import را همانطور که در زیر مشخص شده است اضافه کنید.

src/app/app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ScullyLibModule } from '@scullyio/ng-lib';
import { CoreModule } from './core/core.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ScullyLibModule,
    CoreModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

ایجاد این تغییر تضمین می کند که AppModule به app-header دسترسی دارد.

در نهایت، با تغییر src/styles.css، تغییراتی در استایل کلی برنامه ایجاد خواهید کرد. چندین مؤلفه در سراسر برنامه از استایل موجود در این فایل استفاده می کنند. این به ظاهر و احساس کلی برنامه کمک می کند و از تکرار جلوگیری می کند زیرا استایل در همه اجزاء مورد استفاده مجدد قرار می گیرد.

قبل از اجرای سایت، src/styles.css را باز کرده و خطوط زیر را اضافه کنید:

src/styles.css

html, body {
    width: 100%;
    height: 100%;
}

body {
    font-family: 'Nunito', Arial, Verdana, Geneva, Tahoma, sans-serif;
    background: white;
    background-image: radial-gradient(lightgray 5.5%, transparent 0);
    background-size: 30px 30px;
}

.vw-90 {
    width: 90vw;
}

.vw-80 {
    width: 80vw;
}

.vw-70 {
    width: 80vw;
}

.min-vh-10 {
    min-height: 10vh;
}

در این فایل، اطمینان حاصل می کنید که html و بدنه ارتفاع و عرض تمام صفحه را می گیرند. شما همچنین Nunito را فونت پیش‌فرض قرار می‌دهید و کلاس‌های سبک مختلفی را برای تنظیم عرض و ارتفاع در آن قرار می‌دهید.

در این مرحله، اسکرول لنگر را فعال کردید، استایل کلی را اضافه کردید و قالب مؤلفه برنامه را پاکسازی کردید. در مرحله بعد، سایت را می سازید، مسیرهای Scully را رندر می کنید و نمونه کارها را سرویس می دهید.

مرحله 7 – پیش نمایش سایت استاتیک

اکنون که تمام تغییرات کد لازم را انجام داده اید، می توانید نمونه کارها را با Scully پیش نمایش کنید. این شامل ساخت سایت شما، تولید مسیرهای اسکالی و سپس ارائه نسخه ثابت سایت می شود. در این مرحله، اسکالی برنامه Angular شما را از قبل در یک سایت استاتیک رندر می کند و سروری را برای سرویس دهی به برنامه Angular و نمونه کارها استاتیک ارائه می دهد.

قبل از اینکه اسکالی بتواند نمونه کارها را از قبل رندر کند، باید آن را بسازید.

ng build

این دستور پورتفولیو شما را به dist/portfolio کامپایل می کند.

خروجی شبیه به این خواهد بود:

Compiling @angular/core : es2015 as esm2015
Compiling @angular/common : es2015 as esm2015
Compiling @angular/platform-browser : es2015 as esm2015
Compiling @angular/router : es2015 as esm2015
Compiling @angular/platform-browser-dynamic : es2015 as esm2015
Compiling @angular/common/http : es2015 as esm2015
Compiling @angular/forms : es2015 as esm2015
Compiling @scullyio/ng-lib : es2015 as esm2015
Compiling @ng-bootstrap/ng-bootstrap : es2015 as esm2015
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.

Initial Chunk Files           | Names                      |      Size
vendor.js                     | vendor                     |   3.49 MB
styles.css                    | styles                     | 202.25 kB
polyfills.js                  | polyfills                  | 141.85 kB
main.js                       | main                       |  24.91 kB
runtime.js                    | runtime                    |   9.06 kB

                              | Initial Total              |   3.86 MB

Lazy Chunk Files              | Names                      |      Size
portfolio-portfolio-module.js | portfolio-portfolio-module |  34.19 kB
blog-blog-module.js           | blog-blog-module           |  15.28 kB

Build at:  - Hash:  - Time: 29012ms

وقتی ساخت کامل شد، اجرا کنید:

npx scully

اسکالی کل نمونه کارها را با طی کردن هر مسیر و ایجاد یک index.html جداگانه برای هر یک از آنها از قبل رندر می کند. نمونه کار از پیش رندر شده در dist/static قرار خواهد گرفت. این پوشه باید شبیه این باشد. (برخی فایل ها برای وضوح حذف شده اند.)

dist/static

dist/static
├── about
│   └── index.html
├── assets
├── blog
│   ├── angular-unit-testing
│   │   └── index.html
│   ├── create-a-blog-using-vue.js
│   │   └── index.html
│   ├── how-to-create-a-twitter-bot
│   │   └── index.html
│   └── index.html
├── index.html
└── projects
    └── index.html

توجه کنید که چگونه هر مسیر فایل index.html جداگانه خود را دارد.

برای پیش نمایش سایت استاتیک، اجرا کنید:

npm run scully:serve

این دستور یک سرور Scully استاتیک را در http://localhost:1668/ راه اندازی می کند و نمونه کارها استاتیک شما را ارائه می دهد. (زمانی که پیش نمایش سایت خود را به پایان رساندید، می توانید سرور را با Ctrl + C در ترمینالی که سرور در آن اجرا می کند، بکشید.)

scully.portfolio.config.ts

import { ScullyConfig } from '@scullyio/scully';
export const config: ScullyConfig = {
  projectRoot: "./src",
  projectName: "portfolio",
  outDir: './dist/static',
  routes: {
    '/blog/:slug': {
      type: 'contentFolder',
      slug: {
        folder: "./blog"
      }
    },
  },
  puppeteerLaunchOptions: {args: ['--no-sandbox', '--disable-setuid--sandbox']}
};

صفحه اصلی http://localhost:4200 باید به این صورت باشد:

در این مرحله، شما اپلیکیشن Angular خود را ساخته اید، آن را از قبل در یک سایت استاتیک رندر کرده و با استفاده از Scully به آن سرویس داده اید.

نتیجه

در این آموزش، شما یک برنامه نمونه کارها Angular را تولید و پیکربندی کردید. شما همچنین یک ماژول اصلی برای مدیریت داده های نمونه کارها و نگه داشتن اجزای اصلی برنامه ایجاد کردید. علاوه بر این، شما یک ماژول نمونه کارها متشکل از صفحات ضروری ساخته اید که بیوگرافی، پروژه ها و مشخصات شما را به نمایش می گذارد. شما یک ماژول وبلاگ از صفحات فرود و پست وبلاگ خود ساخته اید. در نهایت، شما نمونه کارها Angular خود را با استفاده از Scully به یک سایت ثابت تبدیل کردید.

هنوز کارهای زیادی برای انجام دادن با نمونه کارها وجود دارد. می توانید صفحاتی را برای نشان دادن مهارت ها و مقالاتی که نوشته اید اضافه کنید. همچنین می توانید یک صفحه تماس اضافه کنید تا افراد بتوانند با شما در تماس باشند. اگر تعاملات سخنرانی، یک کانال آموزشی ویدیویی، یک پادکست یا سخنرانی در کنفرانس دارید، می توانید صفحاتی برای نشان دادن آنها ایجاد کنید.

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

 

برچسب‌ها:Angular 11Jamstack PortfolioScullyاتصال به سرور مجازی لینوکسخرید سرورراه اندازی برنامه Angularراه اندازی سرورسرورسرور مجازینصب Dependencies

  • behnam gol mohamadi
  • ۰
  • ۰

 نحوه کار با فایل های فشرده در Node.js

ورود به سایت

 

معرفی

کار با فایل ها یکی از کارهای رایج در بین توسعه دهندگان است. با افزایش حجم فایل های شما، فضای قابل توجهی روی هارد دیسک شما اشغال می شود. دیر یا زود ممکن است لازم باشد فایل ها را به سرورهای دیگر منتقل کنید یا چندین فایل را از دستگاه محلی خود به سیستم عامل های مختلف آپلود کنید. برخی از این پلتفرم ها محدودیت اندازه فایل دارند و فایل های بزرگ را نمی پذیرند. برای حل این مشکل، می توانید فایل ها را در یک فایل ZIP گروه بندی کنید. فایل ZIP یک فرمت آرشیو است که فایل ها را با الگوریتم فشرده سازی بدون اتلاف فشرده و فشرده می کند. الگوریتم می تواند داده ها را بدون از دست دادن داده ها بازسازی کند. در Node.js، می توانید از ماژول adm-zip برای ایجاد و خواندن آرشیوهای ZIP استفاده کنید.

در این آموزش از ماژول adm-zip برای فشرده سازی، خواندن و از حالت فشرده خارج کردن فایل ها استفاده خواهید کرد. ابتدا چندین فایل را با استفاده از adm-zip در یک آرشیو ZIP ترکیب می‌کنید. سپس محتویات بایگانی ZIP را فهرست می کنید. پس از آن، یک فایل را به یک بایگانی ZIP موجود اضافه می‌کنید و در نهایت، یک بایگانی ZIP را در یک فهرست استخراج می‌کنید.

پیش نیازها

برای دنبال کردن این آموزش، شما نیاز دارید:

  • نصب Node.js روی محیط محلی یا سرور شما
  • آشنایی با نحوه نوشتن یک برنامه Node.js
  • درک اولیه از برنامه نویسی ناهمزمان در جاوا اسکریپت.
  • آشنایی با نحوه کار با فایل ها در Node.js.

مرحله 1 – راه اندازی پروژه

در این مرحله، دایرکتوری پروژه خود را ایجاد کرده و adm-zip را به عنوان یک وابستگی نصب می‌کنید. این دایرکتوری جایی است که شما فایل های برنامه خود را نگه می دارید. همچنین دایرکتوری دیگری حاوی فایل های متنی و تصویر ایجاد خواهید کرد. شما این فهرست را در بخش بعدی بایگانی خواهید کرد.

با دستور زیر یک دایرکتوری به نام zip_app ایجاد کنید:

  • mkdir zip_app

با دستور cd به پوشه جدید ایجاد شده بروید:

cd zip_app

در داخل دایرکتوری، یک فایل package.json برای مدیریت وابستگی های پروژه ایجاد کنید:

npm init -y

گزینه -y یک فایل پیش فرض package.json ایجاد می کند.

بعد، adm-zip را با دستور npm install نصب کنید:

npm install adm-zip

پس از اجرای دستور، npm adm-zip را نصب کرده و فایل package.json را به روز می کند.

سپس یک دایرکتوری به نام test ایجاد کنید و وارد آن شوید:

mkdir test && cd test

در این دایرکتوری شما سه فایل متنی ایجاد کرده و یک تصویر را دانلود خواهید کرد. این سه فایل با محتوای ساختگی پر می شوند تا اندازه فایل آنها بزرگتر شود. این به نشان دادن فشرده سازی ZIP هنگام بایگانی این فهرست کمک می کند.

file1.txt را ایجاد کنید و با استفاده از دستور زیر آن را با محتوای ساختگی پر کنید:

yes “dummy content” | head -n 100000 > file1.txt

دستور yes محتوای ساختگی رشته را به طور مکرر ثبت می کند. با استفاده از دستور pipe |، خروجی را از دستور yes ارسال می کنید تا به عنوان ورودی دستور head استفاده شود. دستور head بخشی از ورودی داده شده را در خروجی استاندارد چاپ می کند. گزینه -n تعداد خطوطی که باید در خروجی استاندارد نوشته شود را مشخص می کند. در نهایت، خروجی سر را با استفاده از > به فایل جدید file1.txt هدایت می‌کنید.

یک فایل دوم با رشته “محتوای ساختگی” تکرار شده 300000 خط ایجاد کنید:

yes “dummy content” | head -n 300000 > file2.txt

فایل دیگری با رشته محتوای ساختگی که 600000 خط تکرار شده است ایجاد کنید:

yes “dummy content” | head -n 600000 > file3.txt

در نهایت، یک تصویر را با استفاده از curl در دایرکتوری دانلود کنید:

curl -O https://assets.vpsgol.net/how-to-process-images-in-node-js-with-sharp/underwater.png

با دستور زیر به دایرکتوری اصلی پروژه برگردید:

cd ..

.. شما را به دایرکتوری والد که zip_app است منتقل می کند.

اکنون دایرکتوری پروژه را ایجاد کرده اید، adm-zip را نصب کرده اید و یک دایرکتوری با فایل ها برای بایگانی ایجاد کرده اید. در مرحله بعدی، یک دایرکتوری را با استفاده از ماژول adm-zip بایگانی خواهید کرد.

مرحله 2 – ایجاد یک آرشیو ZIP

در این مرحله از adm-zip برای فشرده سازی و بایگانی دایرکتوری که در قسمت قبل ایجاد کرده اید استفاده می کنید.

برای بایگانی دایرکتوری، ماژول adm-zip را وارد کرده و از روش addLocalFolder() ماژول برای اضافه کردن دایرکتوری به شی ZIP ماژول adm-zip استفاده می کنید. پس از آن، از متد writeZip() ماژول برای ذخیره آرشیو در سیستم محلی خود استفاده خواهید کرد.

یک فایل جدید createArchive.js در ویرایشگر متن دلخواه خود ایجاد و باز کنید. این آموزش از nano، یک ویرایشگر متن خط فرمان استفاده می کند:

nano createArchive.js

سپس، در ماژول adm-zip در فایل createArchive.js خود نیاز دارید:

zip_app/createArchive.js

const AdmZip = require("adm-zip");

ماژول adm-zip کلاسی را ارائه می دهد که حاوی متدهایی برای ایجاد آرشیو ZIP است.

از آنجایی که در طول فرآیند بایگانی با فایل‌های بزرگ مواجه می‌شوید، ممکن است تا زمانی که بایگانی ZIP ذخیره نشود، رشته اصلی را مسدود کنید. برای نوشتن کد غیر مسدود کننده، یک تابع ناهمزمان برای ایجاد و ذخیره یک آرشیو ZIP تعریف می کنید.

در فایل createArchive.js خود، کد هایلایت شده زیر را اضافه کنید:

zip_app/createArchive.js

const AdmZip = require("adm-zip");

async function createZipArchive() {
  const zip = new AdmZip();
  const outputFile = "test.zip";
  zip.addLocalFolder("./test");
  zip.writeZip(outputFile);
  console.log(`Created ${outputFile} successfully`);
}

createZipArchive();

 

createZipArchive یک تابع ناهمزمان است که یک آرشیو ZIP از یک دایرکتوری مشخص ایجاد می کند. چیزی که آن را ناهمزمان می کند، کلمه کلیدی async است که قبل از برچسب تابع تعریف کرده اید. در داخل تابع، نمونه‌ای از ماژول adm-zip ایجاد می‌کنید که روش‌هایی را ارائه می‌کند که می‌توانید برای خواندن و ایجاد آرشیو استفاده کنید. هنگامی که یک نمونه ایجاد می کنید، adm-zip یک ZIP درون حافظه ایجاد می کند که در آن می توانید فایل ها یا دایرکتوری ها را اضافه کنید.

در مرحله بعد، نام بایگانی را تعریف کرده و آن را در متغیر outputDir ذخیره می کنید. برای افزودن دایرکتوری آزمایشی به آرشیو درون حافظه، متد addLocalFolder() را از adm-zip با مسیر دایرکتوری به عنوان آرگومان فراخوانی می کنید.

پس از اضافه شدن دایرکتوری، شما متد writeZip() را از adm-zip با متغیری حاوی نام آرشیو ZIP فراخوانی می کنید. متد writeZip() آرشیو را در دیسک محلی شما ذخیره می کند.

پس از انجام این کار، console.log() را فراخوانی کنید تا ثبت کنید که فایل ZIP با موفقیت ایجاد شده است.

در نهایت، تابع createZipArchive() را فراخوانی می کنید.

قبل از اجرای فایل، کد را در یک بلوک try…catch بپیچید تا خطاهای زمان اجرا را مدیریت کنید:

zip_app/createArchive.js

const AdmZip = require("adm-zip");

async function createZipArchive() {
  try {
    const zip = new AdmZip();
    const outputFile = "test.zip";
    zip.addLocalFolder("./test");
    zip.writeZip(outputFile);
    console.log(`Created ${outputFile} successfully`);
  } catch (e) {
    console.log(`Something went wrong. ${e}`);
  }
}

createZipArchive();

در داخل بلوک try، کد سعی می کند یک بایگانی ZIP ایجاد کند. در صورت موفقیت آمیز بودن، تابع ()createZipArchive با پرش از بلوک catch خارج می شود. اگر ایجاد یک بایگانی ZIP باعث خطا شود، اجرا به بلوک catch پرش می‌کند و خطا را در کنسول ثبت می‌کند.

با CTRL+X فایل را در نانو ذخیره کرده و از آن خارج شوید. برای ذخیره تغییرات، y را وارد کنید و با فشار دادن ENTER در ویندوز یا کلید RETURN در مک، فایل را تأیید کنید.

فایل createArchive.js را با استفاده از دستور node اجرا کنید:

node createArchive.js

خروجی زیر را دریافت خواهید کرد:

 

Output

Created test.zip successfully

محتویات دایرکتوری را فهرست کنید تا ببینید آیا آرشیو ZIP ایجاد شده است یا خیر:

ls

خروجی زیر را دریافت خواهید کرد که آرشیو را در میان مطالب نشان می دهد:

 

Output

createArchive.js  node_modules  package-lock.json
package.json  test  test.zip

با تأیید اینکه بایگانی ZIP ایجاد شده است، بایگانی ZIP و اندازه فایل دایرکتوری آزمایشی را با هم مقایسه می کنید تا ببینید فشرده سازی کار می کند یا خیر.

اندازه دایرکتوری تست را با استفاده از دستور du بررسی کنید:

du -h test

پرچم -h به du دستور می دهد که اندازه فهرست را در قالبی قابل خواندن توسط انسان نشان دهد.

پس از اجرای دستور، خروجی زیر را دریافت خواهید کرد:

 

Output

15M test

سپس، اندازه فایل بایگانی test.zip را بررسی کنید:

du -h test.zip

دستور du خروجی زیر را ثبت می کند:

 

Output

760K    test.zip

همانطور که می بینید، ایجاد فایل ZIP اندازه دایرکتوری را از 15 مگابایت (مگابایت) به 760 کیلوبایت (KB) کاهش داده است، که یک تفاوت بزرگ است. فایل ZIP قابل حمل تر و اندازه کوچکتر است.

اکنون که یک بایگانی ZIP ایجاد کردید، آماده فهرست کردن محتویات در یک فایل ZIP هستید.

مرحله 3 – فهرست کردن فایل ها در آرشیو ZIP

در این مرحله، با استفاده از adm-zip، تمام فایل‌های موجود در آرشیو ZIP را می‌خوانید و فهرست می‌کنید. برای انجام این کار، ماژول adm-zip را با مسیر آرشیو ZIP خود نمونه سازی می کنید. سپس متد ()getEntries ماژول را فراخوانی می کنید که آرایه ای از اشیاء را برمی گرداند. هر شی اطلاعات مهمی در مورد یک آیتم در آرشیو ZIP دارد. برای فهرست کردن فایل‌ها، روی آرایه تکرار می‌کنید و از شی به نام فایل دسترسی پیدا می‌کنید و آن را در کنسول وارد می‌کنید.

readArchive.js را در ویرایشگر متن دلخواه خود ایجاد و باز کنید:

nano readArchive.js

در readArchive.js خود، کد زیر را برای خواندن و فهرست کردن محتویات یک بایگانی ZIP اضافه کنید:

zip_app/readArchive.js

const AdmZip = require("adm-zip");

async function readZipArchive(filepath) {
  try {
    const zip = new AdmZip(filepath);

    for (const zipEntry of zip.getEntries()) {
      console.log(zipEntry.toString());
    }
  } catch (e) {
    console.log(`Something went wrong. ${e}`);
  }
}

readZipArchive("./test.zip");

ابتدا به ماژول adm-zip نیاز دارید.

در مرحله بعد، تابع readZipArchive() را تعریف می کنید که یک تابع ناهمزمان است. در داخل تابع، یک نمونه از adm-zip با مسیر فایل ZIP که می‌خواهید بخوانید ایجاد می‌کنید. مسیر فایل توسط پارامتر filepath ارائه می شود. adm-zip فایل را می خواند و آن را تجزیه می کند.

پس از خواندن بایگانی، یک عبارت for…of تعریف می کنید که روی اشیاء در آرایه ای تکرار می شود که متد getEntries() از adm-zip هنگام فراخوانی آن را برمی گرداند. در هر تکرار، شی به متغیر zipEntry اختصاص داده می شود. در داخل حلقه، شما شی را به رشته ای تبدیل می کنید که شی را با استفاده از متد Node.js toString() نشان می دهد، سپس با استفاده از متد console.log() آن را در کنسول وارد می کنید.

در نهایت، تابع readZipArchive() را با مسیر فایل آرشیو ZIP به عنوان آرگومان فراخوانی می کنید.

فایل خود را ذخیره کرده و از آن خارج شوید، سپس فایل را با دستور زیر اجرا کنید:

node readArchive.js

خروجی مشابه موارد زیر را دریافت خواهید کرد (ویرایش شده برای اختصار):

 

Output

{
    "entryName": "file1.txt",
    "name": "file1.txt",
    "comment": "",
    "isDirectory": false,
    "header": {
        ...
    },
    "compressedData": "<27547 bytes buffer>",
    "data": "<null>"
}
...

کنسول چهار شی را ثبت می کند. سایر اشیاء ویرایش شده اند تا آموزش مختصر بماند.

هر فایل در بایگانی با یک شی شبیه به آنچه در خروجی قبلی است نشان داده می شود. برای دریافت نام فایل برای هر فایل، باید به ویژگی name دسترسی داشته باشید.

در فایل readArchive.js خود، کد هایلایت شده زیر را برای دسترسی به هر نام فایل اضافه کنید:

zip_app/readArchive.js

const AdmZip = require("adm-zip");

async function readZipArchive(filepath) {
  try {
    const zip = new AdmZip(filepath);

    for (const zipEntry of zip.getEntries()) {
      console.log(zipEntry.name);
    }
  } catch (e) {
    console.log(`Something went wrong. ${e}`);
  }
}

readZipArchive("./test.zip");

ویرایشگر متن خود را ذخیره کرده و از آن خارج شوید. حالا با دستور node دوباره فایل را اجرا کنید:

node readArchive.js

با اجرای فایل خروجی زیر حاصل می شود:

 

Output

file1.txt
file2.txt
file3.txt
underwater.png

اکنون خروجی نام فایل هر فایل را در آرشیو ZIP ثبت می کند.

اکنون می توانید هر فایل را در یک آرشیو ZIP بخوانید و فهرست کنید. در بخش بعدی، فایلی را به آرشیو ZIP موجود اضافه می‌کنید.

مرحله 4 – افزودن یک فایل به یک بایگانی موجود

در این مرحله، یک فایل ایجاد می‌کنید و بدون استخراج آن، آن را به بایگانی ZIP که قبلا ایجاد کرده‌اید، اضافه می‌کنید. ابتدا، با ایجاد یک نمونه adm-zip، آرشیو ZIP را می خوانید. دوم، شما از متد ()addFile ماژول برای اضافه کردن فایل در ZIP استفاده می کنید. در نهایت، بایگانی ZIP را در سیستم محلی ذخیره خواهید کرد.

یک فایل file4.txt با محتوای ساختگی که 600000 خط تکرار شده است ایجاد کنید:

yes “dummy content” | head -n 600000 > file4.txt

updateArchive.js را در ویرایشگر متن خود ایجاد و باز کنید:

nano updateArchive.js

در ماژول adm-zip و ماژول fs که به شما امکان می دهد با فایل های موجود در فایل updateArchive.js خود کار کنید، نیاز دارید:

const AdmZip = require("adm-zip");
const fs = require("fs").promises;

شما نیاز به نسخه مبتنی بر وعده از نسخه ماژول fs دارید که به شما امکان می دهد کدهای ناهمزمان بنویسید. هنگامی که شما یک متد fs را فراخوانی می کنید، یک وعده برمی گرداند.

سپس در فایل updateArchive.js خود، کد برجسته شده زیر را برای افزودن یک فایل جدید به بایگانی ZIP اضافه کنید:

zip_app/updateArchive.js

const AdmZip = require("adm-zip");
const fs = require("fs").promises;

async function updateZipArchive(filepath) {
  try {
    const zip = new AdmZip(filepath);

    content = await fs.readFile("./file4.txt");
    zip.addFile("file4.txt", content);
    zip.writeZip(filepath);
    console.log(`Updated ${filepath} successfully`);
  } catch (e) {
    console.log(`Something went wrong. ${e}`);
  }
}

updateZipArchive("./test.zip");

updateZipArchive یک تابع ناهمزمان است که یک فایل را در سیستم فایل می خواند و آن را به یک ZIP موجود اضافه می کند. در تابع، شما یک نمونه از adm-zip را با مسیر فایل آرشیو ZIP در مسیر فایل به عنوان پارامتر ایجاد می کنید. در مرحله بعد، متد readFile() ماژول fs را برای خواندن فایل در سیستم فایل فراخوانی می کنید. متد readFile() یک وعده را برمی‌گرداند که با کلمه کلیدی await حل می‌کنید (wait فقط در توابع ناهمزمان معتبر است). پس از حل شدن، متد یک شی بافر را برمی گرداند که حاوی محتویات فایل است.

در مرحله بعد، متد addFile() را از adm-zip فراخوانی می کنید. این روش دو آرگومان می گیرد. آرگومان اول نام فایلی است که می خواهید به آرشیو اضافه کنید و آرگومان دوم شی بافر حاوی محتویات فایلی است که متد readFile() می خواند.

پس از آن، متد writeZip ماژول adm-zip را برای ذخیره و نوشتن تغییرات جدید در آرشیو ZIP فراخوانی می‌کنید. پس از انجام این کار، متد console.log() را برای ثبت یک پیام موفقیت آمیز فراخوانی می کنید.

در نهایت، تابع updateZipArchive() را با مسیر فایل آرشیو Zip به عنوان آرگومان فراخوانی می کنید.

فایل خود را ذخیره کرده و از آن خارج شوید. فایل updateArchive.js را با دستور زیر اجرا کنید:

node updateArchive.js

خروجی را به این صورت خواهید دید:

 

Output

Updated ./test.zip successfully

اکنون، تأیید کنید که آرشیو ZIP حاوی فایل جدید است. فایل readArchive.js را اجرا کنید تا محتویات آرشیو ZIP را با دستور زیر فهرست کنید:

node readArchive.js

خروجی را به این صورت خواهید دید:

 

Output

Updated ./test.zip successfully

اکنون، تأیید کنید که آرشیو ZIP حاوی فایل جدید است. فایل readArchive.js را اجرا کنید تا محتویات آرشیو ZIP را با دستور زیر فهرست کنید:

node readArchive.js

خروجی زیر را دریافت خواهید کرد:

file1.txt
file2.txt
file3.txt
file4.txt
underwater.png

این تایید می کند که فایل به ZIP اضافه شده است.

اکنون که می توانید یک فایل را به یک بایگانی موجود اضافه کنید، بایگانی را در بخش بعدی استخراج خواهید کرد.

مرحله 5 – استخراج یک بایگانی فشرده

در این مرحله، تمام محتویات یک بایگانی ZIP را می خوانید و در یک دایرکتوری استخراج می کنید. برای استخراج بایگانی ZIP، adm-zip را با مسیر فایل بایگانی نمونه‌سازی می‌کنید. پس از آن، متد ()extractAllTo ماژول را با نام دایرکتوری که می‌خواهید محتوای ZIP استخراج‌شده شما در آن قرار گیرد، فراخوانی می‌کنید.

ExtractArchive.js را در ویرایشگر متن خود ایجاد و باز کنید:

nano extractArchive.js

در ماژول adm-zip و ماژول مسیر در فایل extractArchive.js خود نیاز دارید:

zip_app/extractArchive.js

const AdmZip = require("adm-zip");
const path = require("path");

ماژول مسیر روش های مفیدی را برای برخورد با مسیرهای فایل ارائه می دهد.

هنوز در فایل extractArchive.js خود، کد هایلایت شده زیر را برای استخراج آرشیو اضافه کنید:

zip_app/extractArchive.js

const AdmZip = require("adm-zip");
const path = require("path");

async function extractArchive(filepath) {
  try {
    const zip = new AdmZip(filepath);
    const outputDir = `${path.parse(filepath).name}_extracted`;
    zip.extractAllTo(outputDir);

    console.log(`Extracted to "${outputDir}" successfully`);
  } catch (e) {
    console.log(`Something went wrong. ${e}`);
  }
}

extractArchive("./test.zip");

ExtractArchive() یک تابع ناهمزمان است که پارامتری حاوی مسیر فایل بایگانی ZIP را می گیرد. در داخل تابع، adm-zip را با مسیر فایل بایگانی ZIP ارائه شده توسط پارامتر filepath، نمونه سازی می کنید.

بعد، شما یک الگو را به معنای واقعی کلمه تعریف می کنید. در داخل مکان‌نمای تحت اللفظی الگو (${})، متد parse() را از ماژول path با مسیر فایل فراخوانی می‌کنید. متد parse() یک شی را برمی گرداند. برای دریافت نام فایل ZIP بدون پسوند فایل، ویژگی name را به شیئی که متد parse() برمی گرداند اضافه می کنید. هنگامی که نام بایگانی برگردانده شد، الگو به معنای واقعی کلمه مقدار را با رشته _extracted درون یابی می کند. سپس مقدار در متغیر outputDir ذخیره می شود. این نام دایرکتوری استخراج شده خواهد بود.

در مرحله بعد، متد ExtractAllTo ماژول adm-zip را با نام دایرکتوری ذخیره شده در outputDir برای استخراج محتویات در دایرکتوری فراخوانی می کنید. پس از آن، برای ثبت یک پیام موفقیت آمیز، console.log() را فراخوانی می کنید.

در نهایت، تابع extractArchive() را با مسیر آرشیو ZIP فراخوانی می کنید.

فایل خود را ذخیره کنید و از ویرایشگر خارج شوید، سپس فایل extractArchive.js را با دستور زیر اجرا کنید:

node extractArchive.js

خروجی زیر را دریافت می کنید:

 

Output

Extracted to "test_extracted" successfully

تأیید کنید که دایرکتوری حاوی محتویات ZIP ایجاد شده است:

ls

خروجی زیر را دریافت خواهید کرد:

 

Output

createArchive.js   file4.txt   package-lock.json
readArchive.js  test.zip        updateArchive.js
extractArchive.js  node_modules  package.json
test           test_extracted

اکنون به دایرکتوری حاوی محتویات استخراج شده بروید:

cd test_extracted

فهرست مطالب در دایرکتوری:

ls

خروجی زیر را دریافت خواهید کرد:

 

Output

file1.txt  file2.txt  file3.txt  file4.txt  underwater.png

اکنون می توانید ببینید که دایرکتوری دارای تمام فایل هایی است که در دایرکتوری اصلی بودند.

شما اکنون محتوای آرشیو ZIP را در یک فهرست استخراج کرده اید.

نتیجه

در این آموزش، شما یک بایگانی ZIP ایجاد کردید، محتویات آن را فهرست کردید، یک فایل جدید به آرشیو اضافه کردید و تمام محتوای آن را با استفاده از ماژول adm-zip در یک فهرست استخراج کردید. این به عنوان پایه خوبی برای کار با آرشیوهای ZIP در Node.js خواهد بود.

 

https://vpsgol.net/product/vps-germany/

 

https://vpsgol.net/product/vps-usa/

 

https://vpsgol.net/product/vps-france/

 

https://vpsgol.net/product/vps-canada/

 

https://vpsgol.net/product/vps-poland/

 

https://vpsgol.net/product/vps-netherlands/

 

https://vpsgol.net/product/vps-england/

 

برچسب‌ها:Node.jsپلتفرم جاواجاواخرید سرور مجازیسرورسرور مجازیفشرده سازی در Node.jsنصب Node.js

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه به اشتراک گذاری داده ها بین Docker Container و Host

ورود به سایت

معرفی

به طور کلی ، Docker containers زودگذر هستند و درست به اندازه ای طول می کشد که دستور صادر شده در containers کامل شود. به طور پیش فرض ، هر گونه داده ایجاد شده در داخل ظرف فقط از داخل containers و فقط در حین کار در دسترس است.

از حجم های Docker می توان برای اشتراک فایل بین سیستم host و Docker container استفاده کرد. به عنوان مثال ، فرض کنید شما می خواهید از تصویر رسمی Docker Nginx استفاده کنید و یک کپی دائمی از پرونده های log Nginx برای تجزیه و تحلیل بعدی نگه دارید. به طور پیش فرض ، تصویر nginx Docker به پوشه/var/log/nginx داخل Docker Nginx container وارد می شود. به طور معمول از طریق سیستم فایل میزبان قابل دسترسی نیست.

در این آموزش ، نحوه دسترسی داده ها از Docker containers به دستگاه host را بررسی می کنیم.

پیش نیازها

برای پیگیری این مقاله ، به یک سرور اوبونتو 18.04 با موارد زیر نیاز دارید:

  • یک non-root user با امتیازات sudo ، به دنبال راه اندازی سرور اولیه با راهنمای اوبونتو 18.04.
  • Docker با دستورالعمل های مرحله 1 و مرحله 2 نحوه نصب و استفاده از Docker در اوبونتو 18.04 نصب شده است.

اگر با Docker تازه کار هستید ، سری Docker Ecosystem نمای کلی مفاهیم کلیدی را ارائه می دهد.

مرحله 1 – اتصال حجم

دستور زیر یک پوشه به نام nginxlogs در فهرست اصلی کاربر فعلی شما ایجاد کرده و آن را به/var/log/nginx در ظرف متصل می کند:

docker run –name=nginx -d -v ~/nginxlogs:/var/log/nginx -p 5000:80 nginx

بیایید کمی وقت بگذاریم تا این دستور را با جزئیات بررسی کنیم:

  • –name = nginx ، container را نامگذاری می کند تا بتوانیم راحت تر به آن مراجعه کنیم.
  • -d فرآیند را جدا کرده و در پس زمینه اجرا می کند. در غیر این صورت ، ما فقط یک پیام خالی Nginx را مشاهده می کنیم و تا زمانی که Nginx را نکشیم ، نمی توانیم از این ترمینال استفاده کنیم.
  • v ~/nginxlogs:/var/log/nginx یک حجم bindmount ایجاد می کند که فهرست/var/log/nginx را از داخل ظرف Nginx به فهرست ~/nginxlogs در دستگاه میزبان پیوند می دهد. داکر از a: برای تقسیم مسیر میزبان از مسیر ظرف استفاده می کند و مسیر میزبان همیشه اول است.
  • -p 5000: 80 یک پورت رو به جلو ایجاد می کند. Nginx container به طور پیش فرض روی پورت 80 گوش می دهد. این پرچم پورت ظرف 80 را به پورت 5000 در سیستم میزبان ترسیم می کند.
  • nginx مشخص می کند که container باید از تصویر Nginx ساخته شود ، که دستور nginx -g “daemon off” را برای شروع Nginx صادر می کند.

مرحله 2 – دسترسی به داده ها در میزبان

ما در حال حاضر یک نسخه از Nginx را داریم که در داخل Docker container روی دستگاه ما اجرا می شود و پورت 5000 دستگاه میزبان ما مستقیماً به آن نسخه از پورت 80 Nginx ترسیم می شود.

آدرس را در مرورگر وب با استفاده از آدرس IP یا نام میزبان سرور خود و شماره پورت بارگذاری کنید: http: // your_server_ip: 5000. باید ببینی:

جالبتر اینکه اگر در فهرست ~/nginxlogs در host جستجو کنیم ، access.log ایجاد شده توسط container’s nginx را مشاهده می کنیم که درخواست ما را نشان می دهد:

cat ~/nginxlogs/access.log

این باید چیزی شبیه به این نشان دهد:

 

Output

203.0.113.0 - - [11/Jul/2018:00:59:11 +0000] "GET / HTTP/1.1" 200 612 "-"
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36" "-"

در صورت ایجاد هرگونه تغییر در پوشه ~/nginxlogs ، می توانید آنها را از داخل Docker container در زمان واقعی نیز مشاهده کنید.

نتیجه

در این آموزش ما نحوه ایجاد یک حجم داده Docker برای به اشتراک گذاری اطلاعات بین یک container و سیستم host file را نشان دادیم. این در محیط های توسعه مفید است ، جایی که برای اشکال زدایی دسترسی به گزارش ها ضروری است. برای کسب اطلاعات بیشتر در مورد به اشتراک گذاری داده های مداوم بین ظروف ، به نحوه اشتراک گذاری داده ها بین Docker Containers نگاه کنید.

 

برچسب‌ها:

  • behnam gol mohamadi
  • ۰
  • ۰

چگونه یک ماژول سفارشی Terraform بسازیم

ورود به سایت

معرفی

ماژول های Terraform به شما امکان می دهد منابع متمایز زیرساخت خود را در یک منبع واحد و یکپارچه گروه بندی کنید. می توانید بعداً با سفارشی سازی های احتمالی ، بدون تکرار تعاریف منابع در هر زمان که به آنها نیاز دارید ، مجدداً از آنها استفاده کنید ، که برای پروژه های بزرگ با ساختارهای پیچیده مفید است. می توانید نمونه های ماژول را با استفاده از متغیرهای ورودی که تعریف کرده اید و همچنین با استفاده از خروجی ها اطلاعات را از آنها استخراج کنید. علاوه بر ایجاد ماژول های سفارشی خود ، می توانید از ماژول های از پیش ساخته شده که به طور عمومی در رجیستری Terraform منتشر شده اند نیز استفاده کنید. توسعه دهندگان می توانند با استفاده از ورودی هایی مانند ماژول هایی که ایجاد می کنید از آنها استفاده کرده و آنها را سفارشی کنند ، اما کد منبع آنها در ابر ذخیره شده و از ابر خارج می شود.

در این آموزش ، ماژول Terraform را ایجاد می کنید که چندین قطره را در پشت Load Balancer برای افزونگی راه اندازی می کند. شما همچنین از ویژگی های for_each و count حلقه زبان پیکربندی Hashicorp (HCL) برای استقرار چندین نمونه سفارشی ماژول به طور همزمان استفاده خواهید کرد.

ساختار و مزایای ماژول

در این بخش ، یاد می گیرید که ماژول ها چه مزایایی را به همراه دارند ، معمولاً کجا در پروژه قرار می گیرند و چگونه باید ساختار یابند.

ماژول های سفارشی Terraform برای محصور کردن اجزای متصل شده که اغلب در پروژه های بزرگتر مورد استفاده قرار می گیرند ، ایجاد می شوند. آنها مستقل هستند و فقط منابع ، متغیرها و ارائه دهندگان مورد نیاز خود را جمع می کنند.

ماژول ها معمولاً در یک پوشه مرکزی در ریشه پروژه ، هر کدام در زیر پوشه مربوطه در زیر ذخیره می شوند. به منظور حفظ یک جداسازی تمیز بین ماژول ها ، همیشه آنها را به گونه ای طراحی کنید که دارای یک هدف واحد باشند و اطمینان حاصل کنید که هرگز شامل زیرمجموعه ها نیستند.

وقتی می بینید که ماژول ها را با استفاده از سفارشی سازی های نادر تکرار می کنید ، از طرح های منابع خود ایجاد کنید مفید است. بسته بندی یک منبع واحد به عنوان یک ماژول می تواند اضافی باشد و به تدریج سادگی معماری کلی را حذف می کند.

برای پروژه های کوچک توسعه ای و آزمایشی ، استفاده از ماژول ها ضروری نیست زیرا در این موارد پیشرفت چندانی ندارند. ماژول ها با قابلیت سفارشی سازی خود ، عنصر اصلی پروژه های پیچیده ساختار یافته هستند. توسعه دهندگان به دلیل مزایای قابل توجه در جلوگیری از تکرار کد ، از ماژول ها برای پروژه های بزرگتر استفاده می کنند. ماژول ها همچنین مزیتی را ارائه می دهند که تعاریف فقط نیاز به اصلاح در یک مکان دارند ، که سپس در بقیه زیرساخت ها منتشر می شود.

سپس ماژول ها را در پروژه های Terraform خود تعریف ، استفاده و سفارشی کنید.

ایجاد یک ماژول

در این بخش ، شما چند قطره و Load Balancer را به عنوان منابع Terraform تعریف کرده و آنها را در یک ماژول قرار می دهید. شما همچنین می توانید ماژول حاصل را با استفاده از ورودی های ماژول سفارشی کنید.

ماژول را در دایرکتوری به نام droplet-lb ، در زیر دایرکتوری به نام modules ذخیره می کنید. با فرض اینکه در فهرست راهنمای terraform-modules که به عنوان بخشی از پیش نیازها ایجاد کرده اید هستید ، هر دو را همزمان اجرا کنید:

mkdir -p modules/droplet-lb

آرگومان -p به mkdir دستور می دهد تا همه دایرکتوری ها را در مسیر ارائه شده ایجاد کند.

به آن بروید:

cd modules/droplet-lb

همانطور که در قسمت قبل اشاره شد ، ماژول ها شامل منابع و متغیرهایی هستند که از آنها استفاده می کنند. با شروع از Terraform 0.13 ، آنها همچنین باید تعاریفی از ارائه دهندگان مورد استفاده خود داشته باشند. ماژول ها نیازی به پیکربندی خاصی ندارند تا توجه داشته باشید که کد نشان دهنده یک ماژول است ، زیرا Terraform هر فهرست شامل کد HCL را به عنوان یک ماژول ، حتی فهرست اصلی پروژه ، در نظر می گیرد.

متغیرهای تعریف شده در یک ماژول به عنوان ورودی های آن نشان داده می شوند و می توانند در تعاریف منابع برای سفارشی سازی آنها استفاده شوند. ماژولی که ایجاد می کنید دارای دو ورودی است: تعداد Droplets برای ایجاد و نام گروه آنها. ایجاد و باز کردن برای ویرایش فایلی به نام variables.tf که در آن متغیرها را ذخیره می کنید:

nano variables.tf

خطوط زیر را اضافه کنید:

modules/droplet-lb/variables.tf

variable "droplet_count" {}
variable "group_name" {}

ذخیره کنید و فایل را ببندید.

شما تعریف Droplet را در فایلی با نام droplets.tf ذخیره خواهید کرد. ایجاد و باز کردن آن برای ویرایش:

nano droplets.tf

خطوط زیر را اضافه کنید:

modules/droplet-lb/droplets.tf

resource "vpsgol_droplet" "droplets" {
  count  = var.droplet_count
  image  = "ubuntu-20-04-x64"
  name   = "${var.group_name}-${count.index}"
  region = "fra1"
  size   = "s-1vcpu-1gb"
}

برای پارامتر count که مشخص می کند چند نمونه از منبع را ایجاد کنید ، از متغیر droplet_count استفاده می کنید. مقدار آن زمانی مشخص می شود که ماژول از کد اصلی پروژه فراخوانی شود. نام هر یک از Droplets های مستقر متفاوت خواهد بود ، که با افزودن فهرست قطره فعلی به نام گروه ارائه شده ، به آن می رسید. استقرار Droplets در منطقه fra1 خواهد بود و اوبونتو 20.04 را اجرا خواهند کرد.

پس از اتمام کار ، فایل را ذخیره و ببندید.

با Droplets که اکنون تعریف شده است ، می توانید به ایجاد Load Balancer بروید. شما تعریف منابع آن را در فایلی با نام lb.tf ذخیره خواهید کرد. با اجرای آن ، آن را برای ویرایش ایجاد کرده و باز کنید:

nano lb.tf

تعریف منابع آن را اضافه کنید:

modules/droplet-lb/lb.tf

resource "vpsgol_loadbalancer" "www-lb" {
  name   = "lb-${var.group_name}"
  region = "fra1"

  forwarding_rule {
    entry_port     = 80
    entry_protocol = "http"

    target_port     = 80
    target_protocol = "http"
  }

  healthcheck {
    port     = 22
    protocol = "tcp"
  }

  droplet_ids = [
    for droplet in vpsgol_droplet.droplets:
      droplet.id
  ]
}

شما Load Balancer را با نام گروه در نام آن تعریف می کنید تا قابل تشخیص باشد. شما آن را به همراه Droplets در منطقه fra1 مستقر می کنید. دو بخش بعدی پورت ها و پروتکل های هدف و نظارت را مشخص می کند.

بلوک droplet_ids برجسته ، شناسه Droplets را که باید توسط Load Balancer مدیریت شود ، می گیرد. از آنجا که چند قطره وجود دارد ، و تعداد آنها از قبل مشخص نیست ، شما از حلقه for برای عبور از مجموعه Droplets (vpsgol_droplet.droplets) و گرفتن شناسه آنها استفاده می کنید. شما حلقه for را با پرانتز ([]) احاطه می کنید تا مجموعه حاصل یک لیست باشد.

اکنون Droplet ، Load Balancer و متغیرها را برای ماژول خود تعریف کرده اید. شما باید الزامات ارائه دهنده را مشخص کنید ، مشخص کنید که ماژول از کدام ارائه دهندگان استفاده می کند ، از جمله نسخه آنها و جایی که آنها واقع شده اند. از آنجا که Terraform 0.13 است ، ماژول ها باید به صراحت منابع ارائه دهندگان غیر Hashicorp مورد استفاده خود را مشخص کنند. این به این دلیل است که آنها آنها را از پروژه اصلی به ارث نمی برند.

الزامات ارائه دهنده را در فایلی با نام provider.tf ذخیره خواهید کرد. با اجرای آن آن را برای ویرایش ایجاد کنید:

nano provider.tf

ماژول ها همچنین از خروجی ها پشتیبانی می کنند که می توانید از آنها برای استخراج اطلاعات داخلی در مورد وضعیت منابع خود استفاده کنید. شما یک خروجی تعریف می کنید که آدرس IP Load Balancer را نشان می دهد و آن را در فایلی با نام outputs.tf ذخیره می کنید. آن را برای ویرایش ایجاد کنید:

nano outputs.tf

تعریف زیر را اضافه کنید:

modules/droplet-lb/outputs.tf

output "lb_ip" {
  value = vpsgol_loadbalancer.www-lb.ip
}

این خروجی آدرس IP Load Balancer را بازیابی می کند. ذخیره کنید و فایل را ببندید.

ماژول droplet-lb از لحاظ عملکردی کامل است و آماده استقرار است. شما آن را از کد اصلی ، که در ریشه پروژه ذخیره می کنید ، صدا می زنید. ابتدا ، با دوبار بالا رفتن از فهرست پرونده خود به آن بروید:

cd ../..

سپس ، برای ویرایش فایلی به نام main.tf ایجاد و باز کنید ، که در آن از ماژول استفاده می کنید:

nano main.tf

خطوط زیر را اضافه کنید:

main.tf

module "groups" {
  source = "./modules/droplet-lb"

  droplet_count = 3
  group_name    = "group1"
}

output "loadbalancer-ip" {
  value = module.groups.lb_ip
}

در این اعلان ماژول droplet-lb را که در فهرست راهنمای تعیین شده به عنوان منبع قرار دارد فرا می خوانید. شما ورودی ارائه شده ، droplet_count و group_name را که روی group1 تنظیم شده است پیکربندی می کنید تا بعداً بتوانید بین نمونه ها تشخیص دهید.

از آنجا که خروجی IP Load Balancer در یک ماژول تعریف شده است ، هنگام اعمال پروژه به طور خودکار نشان داده نمی شود. راه حل این مسئله ایجاد خروجی دیگری است که مقدار آن را بازیابی می کند (loadbalancer_ip). پس از اتمام کار فایل را ذخیره و ببندید.

با راه اندازی اولیه ماژول را راه اندازی کنید:

terraform init

خروجی به صورت زیر خواهد بود:

 

Output

Initializing modules...
- groups in modules/droplet-lb

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of vpsgol/vpsgol from the dependency lock file
- Using previously-installed vpsgol/vpsgol v2.10.1

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

می توانید برنامه ریزی پروژه را امتحان کنید تا ببینید Terraform با اجرای چه اقداماتی انجام می دهد:

terraform plan -var “do_token=${DO_PAT}”

خروجی مشابه این خواهد بود:

 

Output

...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.groups.vpsgol_droplet.droplets[0] will be created
  + resource "vpsgol_droplet" "droplets" {
...
      + name                 = "group1-0"
...
    }

  # module.groups.vpsgol_droplet.droplets[1] will be created
  + resource "vpsgol_droplet" "droplets" {
...
      + name                 = "group1-1"
...
    }

  # module.groups.vpsgol_droplet.droplets[2] will be created
  + resource "vpsgol_droplet" "droplets" {
...
      + name                 = "group1-2"
...
    }

  # module.groups.vpsgol_loadbalancer.www-lb will be created
  + resource "vpsgol_loadbalancer" "www-lb" {
...
      + name                     = "lb-group1"
...
    }

Plan: 4 to add, 0 to change, 0 to destroy.
...

این خروجی نشان می دهد که Terraform سه قطره ایجاد می کند ، به نام های group1-0 ، group1-1 و group1-2 ، و همچنین یک Load Balancer به نام group1-lb ایجاد می کند ، که ترافیک به سه قطره را از و خارج مدیریت می کند.

با اجرای پروژه می توانید پروژه را روی ابر اعمال کنید:

terraform apply -var “do_token=${DO_PAT}”

در صورت درخواست بله را وارد کنید. خروجی تمام اقدامات را نشان می دهد و آدرس IP Load Balancer نیز نشان داده می شود:

 

Output

module.groups.vpsgol_droplet.droplets[1]: Creating...
module.groups.vpsgol_droplet.droplets[0]: Creating...
module.groups.vpsgol_droplet.droplets[2]: Creating...
...
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Outputs:

loadbalancer-ip = ip_address

از آنجا که در مرحله بعد پیکربندی را به طور قابل توجهی تغییر می دهید ، منابع اجرا شده را با اجرای زیر از بین ببرید:

terraform destroy -var “do_token=${DO_PAT}”

در صورت درخواست بله را وارد کنید. خروجی به این صورت خاتمه می یابد:

 

Output

...
Destroy complete! Resources: 4 destroyed.

در این مرحله ، ماژولی ایجاد کرده اید که شامل تعدادی Droplets و Load Balancer است که به طور خودکار برای مدیریت ترافیک ورودی و خروجی آنها پیکربندی می شود. اکنون می توانید چندین نمونه از یک ماژول را از یک کد با استفاده از for_each و count استفاده کنید.

استقرار موارد متعدد ماژول

در این بخش ، از count و for_each برای استقرار چندین بار ماژول droplet-lb ، با سفارشی سازی استفاده خواهید کرد.

با استفاده از شمارش

یک راه برای استقرار چند نمونه از یک ماژول به طور همزمان این است که تعداد آنها را به پارامتر count منتقل کنید ، که به طور خودکار برای هر ماژول در دسترس است. main.tf را برای ویرایش باز کنید:

nano main.tf

با حذف تعریف خروجی موجود ، آن را به شکل زیر تغییر دهید:

main.tf

module "groups" {
  source = "./modules/droplet-lb"

  count  = 3

  droplet_count = 3
  group_name    = "group1-${count.index}"
}

با تنظیم شمارش روی 3 ، به Terraform دستور می دهید که ماژول را سه بار ، هر کدام با نام گروهی متفاوت ، مستقر کند. پس از اتمام کار ، فایل را ذخیره و ببندید.

برنامه ریزی استقرار با اجرای:

terraform plan -var “do_token=${DO_PAT}”

خروجی طولانی خواهد بود و به شکل زیر خواهد بود:

 

Output

...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.groups[0].vpsgol_droplet.droplets[0] will be created
...
  # module.groups[0].vpsgol_droplet.droplets[1] will be created
...
  # module.groups[0].vpsgol_droplet.droplets[2] will be created
...
  # module.groups[0].vpsgol_loadbalancer.www-lb will be created
...
  # module.groups[1].vpsgol_droplet.droplets[0] will be created
...
  # module.groups[1].vpsgol_droplet.droplets[1] will be created
...
  # module.groups[1].vpsgol_droplet.droplets[2] will be created
...
  # module.groups[1].vpsgol_loadbalancer.www-lb will be created
...
  # module.groups[2].vpsgol_droplet.droplets[0] will be created
...
  # module.groups[2].vpsgol_droplet.droplets[1] will be created
...
  # module.groups[2].vpsgol_droplet.droplets[2] will be created
...
  # module.groups[2].vpsgol_loadbalancer.www-lb will be created
...

Plan: 12 to add, 0 to change, 0 to destroy.
...

Terraform در خروجی توضیح می دهد که هر یک از سه نمونه ماژول دارای سه Droplet و Load Balancer مربوط به آنها خواهد بود.

استفاده از for_each

هنگامی که به سفارشی سازی پیچیده تر نیاز دارید ، یا زمانی که تعداد موارد به داده های شخص ثالث (اغلب به صورت نقشه ارائه می شود) که هنگام نوشتن کد مشخص نیست ، می توانید از for_each برای ماژول ها استفاده کنید.

اکنون نقشه ای را تعریف می کنید که نام گروه ها را با تعداد Droplet جفت می کند و موارد قطره ای-lb را مطابق آن مستقر می کند. main.tf را برای ویرایش با اجرا باز کنید:

nano main.tf

فایل را اصلاح کنید تا به این شکل درآید:

main.tf

variable "group_counts" {
  type    = map
  default = {
    "group1" = 1
    "group2" = 3
  }
}

module "groups" {
  source   = "./modules/droplet-lb"
  for_each = var.group_counts

  droplet_count = each.value
  group_name    = each.key
}

شما ابتدا نقشه ای به نام group_counts تعریف می کنید که حاوی چند قطره است که یک گروه معین باید داشته باشد. سپس ، ماژول droplet-lb را فرا می خوانید ، اما مشخص می کنید که حلقه for_each باید در var.group_counts ، نقشه ای که قبلاً تعریف کرده اید ، عمل کند. droplet_count each.value ، مقدار جفت فعلی ، که تعداد Droplets برای گروه فعلی است را می گیرد. group_name نام گروه را دریافت می کند.

پس از اتمام کار فایل را ذخیره و ببندید.

سعی کنید پیکربندی را با اجرای زیر اعمال کنید:

terraform plan -var “do_token=${DO_PAT}”

در خروجی اقدامات Terraform برای ایجاد دو گروه با Droplets و Load Balancers خود شرح داده می شود:

 

Output

...
Terraform used the selected providers to generate the following execution plan. Resource actions are
indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # module.groups["group1"].vpsgol_droplet.droplets[0] will be created
...
  # module.groups["group1"].vpsgol_loadbalancer.www-lb will be created
...
  # module.groups["group2"].vpsgol_droplet.droplets[0] will be created
...
  # module.groups["group2"].vpsgol_droplet.droplets[1] will be created
...
  # module.groups["group2"].vpsgol_droplet.droplets[2] will be created
...
  # module.groups["group2"].vpsgol_loadbalancer.www-lb will be created
...

در این مرحله ، شما از count و for_each برای استقرار چندین نمونه سفارشی از یک ماژول از یک کد استفاده کرده اید.

نتیجه

در این آموزش ، ماژول های Terraform را ایجاد و به کار گرفته اید. شما از ماژول ها برای گروه بندی منابع مرتبط منطقی با هم استفاده کردید و آنها را به منظور استقرار چندین نمونه مختلف از یک تعریف کد مرکزی سفارشی کردید. شما همچنین از خروجی ها برای نشان دادن ویژگی های منابع موجود در ماژول استفاده کردید.

 

برچسب‌ها:

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از تم ها در Gatsby

ورود به سایت

معرفی

Gatsby 1.0 در سال 2017 منتشر شد و از آن زمان به بعد ویژگی های جدید خود را همچنان حفظ می کند ، در حالی که قابلیت سفارشی سازی بالا را به عنوان یک تولید کننده سایت استاتیک حفظ می کند. ویژگی های افزوده شده به شکل افزونه ها ، API های جدید ، ابزارهای کمکی و گزینه های پیکربندی است. هر یک از این ویژگی ها را می توان به صورت جداگانه استفاده کرد و سفارشی کرد یا با هم ترکیب کرد تا موارد خاص استفاده را اعمال کند. با این حال ، از آنجا که بسیاری از سایت ها از ترکیب ویژگی ها و تنظیمات یکسانی بهره می برند ، Gatsby تم های Gatsby را معرفی کرد.

تم ها در Gatsby به طور خاص به افزونه هایی اشاره می کنند که به عنوان مجموعه ای از گزینه های پیکربندی ، عملکرد و/یا عناصر رابط کاربر (UI) عمل می کنند. تفکیک ویژگی های به اشتراک گذاشته شده در موضوعات حفظ شده باعث می شود سایت شما به روزتر باشد و همچنین به شما اجازه می دهد زمان کمتری را برای پیکربندی سایت خود صرف کنید و زمان بیشتری را برای توسعه محتوا اختصاص دهید.

در این آموزش ، شما تم Gatsby را برای انتشار پست های وبلاگ نصب ، پیکربندی و استفاده می کنید: gatsby-theme-blog. این افزونه چندین ویژگی مانند پشتیبانی از MDX و برجسته سازی کد را در یک بسته مناسب قرار می دهد. در طول دوره آموزشی ، روند استفاده از این موضوع خاص Gatsby را دنبال می کنید ، که می توانید آن را به طور کلی در موضوعات اعمال کنید.

هر مرحله شما را در قسمت مهمی از استفاده از تم های Gatsby راهنمایی می کند و در پایان خواهید دید که چگونه می توان این فرآیند را روی هر موضوع Gatsby که در آینده می خواهید استفاده کنید ، اعمال کنید.

پیش نیازها

قبل از شروع کار ، چند مورد را که لازم دارید در اینجا آورده ایم:

  • نصب محلی Node.js برای اجرای Gatsby و ایجاد سایت شما. روش نصب بر اساس سیستم عامل متفاوت است ، اما vpsgol دارای راهنمای Ubuntu 20.04 و macOS است و همیشه می توانید آخرین نسخه را در صفحه بارگیری رسمی Node.js پیدا کنید.
  • آشنایی با جاوا اسکریپت برای کار در Gatsby. زبان جاوا اسکریپت یک مبحث گسترده است ، اما یک نقطه شروع خوب نحوه کدگذاری ما در سری جاوا اسکریپت است.
  • یک پروژه جدید Gatsby ، داربست از gatsby-starter-default. برای ساخت یک پروژه جدید Gatsby از ابتدا ، می توانید به مرحله 1 آموزش نحوه راه اندازی اولین وب سایت Gatsby مراجعه کنید.

این آموزش روی Node.js v14.16.1 ، npm v6.14.12 ، Gatsby v3.11.1 و gatsby-theme-blog v3.0.0 آزمایش شده است.

مرحله 1 – پیدا کردن و نصب یک تم

اگرچه این آموزش با استفاده از یک موضوع خاص ، gatsby-theme-blog ، شما را راهنمایی می کند ، اما هر مرحله به طور کلی در مورد موضوعات Gatsby نیز کاربرد دارد. این امر در مورد اولین مرحله نیز صدق می کند: یافتن موضوعی که می خواهید استفاده کنید و نصب آن با npm.

Gatsby به نویسندگان افزونه و موضوع درباره نحوه انتشار بسته هایGatsby خود راهنمایی می کند ، که پیدا کردن موضوعی متناسب با نیازهای شما را آسان تر می کند. به توسعه دهندگان تم دستور داده می شود که بسته های موضوعی خود را با gatsby و gatsby-theme به عنوان کلمات کلیدی برچسب گذاری کنند ، که سپس توسط رجیسترهای بسته (جایی که فایلها در واقع میزبانی می شوند) اسکن شده و قابل جستجو می شوند.

این آموزش موارد استفاده از ساخت سایت دارای Gatsby با زیر بخش وبلاگ را دنبال می کند. شما به عنوان توسعه دهنده به دنبال موضوعی برای افزودن پشتیبانی از MDX ، برجسته سازی کد و موارد دیگر هستید. گرچه Gatsby مرورگر افزونه خود را دارد ، اما در واقع لیست های خود را از رجیستری npm خارج می کند ، بنابراین اولین قدم شما این است که جستجوی خود را مستقیماً در موتور جستجوی رجیستری npm شروع کنید. با استفاده از ورودی جستجوی کلمات کلیدی وبلاگ: gatsby-theme ، نتایج خود را تنها به آن افزونه هایی که دارای کلمه کلیدی gatsby-theme هستند محدود می کنید ، همانطور که در تصویر زیر نشان داده شده است:

در این آموزش ، شما از gatsby-theme-blog استفاده می کنید ، بنابراین آن بسته را انتخاب کنید. با انتخاب gatsby-theme-blog به عنوان موضوعی که قصد نصب آن را دارید ، قسمت بعدی این مرحله این است که در واقع آن را به همراه وابستگی های آن نصب کنید. به پروژه موجود Gatsby بروید و دستور زیر را در فهرست اجرا کنید:

npm install gatsby-theme-blog

پس از اتمام نصب وابستگی ها ، پیامی مشابه زیر مشاهده خواهید کرد:

 

Output

...
+ gatsby-theme-blog@3.0.0
added 262 packages from 181 contributors and audited 2391 packages in 49.706s

اکنون که تم و وابستگی های آن را در پروژه خود نصب کرده اید ، وقت آن است که به بارگیری و پیکربندی تم در پروژه Gatsby خود بپردازید.

مرحله 2 – بارگیری و پیکربندی تم

اکنون که تم شما نصب شده است ، می توانید از آن در سایت خود استفاده کرده و آن را بر اساس نیاز خود تغییر دهید. در Gatsby ، راه اندازی اولیه و پیکربندی تم اصلی با ویرایش فایل پیکربندی ریشه ، gatsby-config.js انجام می شود. در این مرحله ، فایل پیکربندی را ویرایش می کنید تا در گزینه مورد نظر خود در تم خود بارگذاری شود.

فایل پیکربندی gatsby-config.js را در ویرایشگر دلخواه خود باز کنید ، سپس موارد زیر را اضافه کنید:

gatsby-config.js

module.exports = {
  plugins: [
    ...
    `gatsby-plugin-image`,
    {
      resolve: 'gatsby-theme-blog',
      options: {
        basePath: '/posts',
        contentPath: `md/posts`,
      }
    },
    `gatsby-transformer-sharp`,
    ...
  ]
}

در این کد پیکربندی ، دو تنظیم مهم وجود دارد که از مقادیر سفارشی برای آنها استفاده می کنید. موضوع از گزینه basePath برای تنظیم آدرس وبلاگ استفاده می کند و contentPath به موضوع می گوید که کجا فایلهای Markdown را برای انتشار به عنوان پست وبلاگ پیدا کنید. استفاده از مقدار md/posts برای contentPath به این معنی است که فایلهای Markdown شما باید در فهرست md/posts قرار داشته باشند.

پس از افزودن این کد ، فایل پیکربندی خود را ذخیره کنید.

موضوع gatsby-theme-blog تنظیمات بیشتری را ارائه می دهد ، که در فایل README gatsby-theme-blog ثبت شده است. از آنجا که هر موضوع Gatsby متفاوت است ، مهمترین قسمت این مرحله مراجعه به مستندات موضوع انتخابی شما و پیروی از راهنمایی های دقیق ارائه شده در آن است.

شما اکنون تم را طوری تنظیم کرده اید که از طریق فایل پیکربندی Gatsby بارگیری و به دلخواه پیکربندی شود. گام بعدی این است که برخی از قابلیت های جدیدی را که به سایت شما اضافه می کند ، در طول راه آزمایش کنید.

مرحله 3 – آزمایش عملکرد

همانطور که تم شما اکنون نصب ، پیکربندی و بارگذاری شده است ، اکنون می توانید آن را در سایت خود پیاده سازی کنید. این مرحله نحوه امتحان برخی از قابلیت های جدید همراه با موضوع و پیش نمایش نتایج را پوشش می دهد.

شما MDX ، برجسته سازی کد و پشتیبانی پردازش Markdown از gatsby-theme-blog را با یک فایل پست وبلاگ جدید آزمایش خواهید کرد. ابتدا ، شما باید پوشه ای را برای نگهداری فایل ها ایجاد کنید ، که باید با تنظیم محتوای مسیر md/post هایی که در مرحله شماره 2 استفاده کرده اید مطابقت داشته باشد. شما می توانید این فهرست را به صورت دستی در مرورگر فایل خود ایجاد کنید یا با اجرای این دستور در ریشه پروژه Gatsby خود ، آن را در ترمینال خود ایجاد کنید:

mkdir -p ./md/posts

در مرحله بعد ، یک فایل خالی MDX ، my-first-post.mdx ایجاد کنید که حاوی محتوای پست جدید شما باشد. دوباره می توانید این را به صورت دستی یا در ترمینال ایجاد کنید:

touch ./md/posts/my-first-post.mdx

حالا فایل خالی MDX را باز کرده و کد زیر را به آن اضافه کنید:

md/posts/my-first-post.mdx

---
title: Learning Gatsby Themes and Trying MDX
slug: /posts/gatsby-theme-learning
date: 2021-08-16
excerpt: A post about learning Gatsby themes and trying out some MDX.
---

## Welcome!

This is a post where I plan to share my journey learning Gatsby Themes, and to try out some MDX.

## Resources

<ul>
{[
    {
        link: 'https://www.gatsbyjs.com/',
        text: 'Gatsby Website',
        note: 'Official Website for Gatsby'
    },
    {
        link: 'https://www.gatsbyjs.com/docs/themes/',
        text: 'Gatsby Theme Documentation',
        note: 'Documentation for Gatsby Theme usage and development'
    },
    {
        link: 'https://www.vpsgol.com/community/tutorial_series/how-to-create-static-web-sites-with-gatsby-js',
        text: 'vpsgol - "How To Create Static Web Sites with Gatsby.js"',
        note: 'A vpsgol tutorial series on using Gatsby JS'
    }
].map(item => (
    <li key={item.link}>
        <a href={item.link} target="_blank">{item.text}</a>
        <ul>
            <li>{item.note}</li>
        </ul>
    </li>
))}
</ul>

## Code Sample

To try out code highlighting in this theme, here is a snippet of JavaScript code. This code won't run in your browser; it is for visual use only.

در بالای فایل ، قسمتی که توسط — محصور شده است مجموعه ای از جفت های کلید-مقدار است که frontmatter نامیده می شود. همه موضوعات از کلیدهای یکسانی استفاده نمی کنند و آنهایی که در پست خود استفاده می کنید از بین کلیدهای مورد استفاده gatsby-theme-blog با دقت انتخاب شده اند. شما یک عنوان سفارشی ، راه حل (مسیر URL) ، تاریخ انتشار و گزیده ای (پیش نمایش متن برای نمایش در صفحه فهرست پست ها) را تعریف کرده اید.

تمام متنی که از دستور جلو پیروی می کند ، بدنه پست می شود و با خوش آمدید شما شروع می شود! بخش. دو علامت هش (##) قبل از متن عنوان به Markdown می گویند که این یک عنوان سطح 2 است که برای بخش منابع نیز استفاده می شود.

در بخش منابع ، اولین استفاده خود را از آنچه MDX را از Markdown معمولی متمایز می کند ، استفاده می کنید: استفاده از نحو JSX React برای جاسازی اجزای React که با Markdown شما ادغام شده و به یک صفحه واحد تبدیل می شوند. در پست خود ، از JSX برای تبدیل مجموعه ای از منابع درباره Gatsby به لیست پیوندهای HTML استفاده می کنید.

سرانجام ، برای آزمایش ویژگی برجسته سازی نحو کد همراه با gatsby-theme-blog ، یک بلوک Markdown Fidden Code Block در انتهای فایل اضافه کنید:

md/posts/my-first-post.mdx

```js
function saySomething(name) {
    console.log(`Hello ${name}!`);
    console.log(`Isn't learning about Gatsby fun?!`);
}
saySomething('Arthur');
```

در این حالت از backticks سه گانه برای نشان دادن مرزهای شروع و توقف کد استفاده می شود.

پس از اتمام ویرایش پست جدید ، فایل MDX را ذخیره و ببندید.

برای مشاهده این پست به عنوان یک بیننده ، با آزمایش تمام ویژگی های افزونه تم ، دستور زیر را اجرا کنید:

npm run develop

پس از آماده شدن ، Gatsby CLI از شما می خواهد که پروژه خود را در مرورگر وب خود باز کنید ، که می توانید با رفتن به localhost: 8000 این کار را انجام دهید. برای مشاهده صفحه فهرست وبلاگ جدید ، از localhost: 8000/posts دیدن کنید و برای مشاهده این پست جدید ، به localhost بروید: 8000/posts/gatsby-theme-learning/. پست وبلاگ به شکل زیر خواهد بود:

شما به تازگی برخی از قابلیت هایی را که تم تازه نصب شده شما ارائه می دهد آزمایش کرده اید و نتایج تلاش های خود را در یک مرورگر وب مشاهده کرده اید. برای بسیاری از کاربران ، این ممکن است تمام نیازهای آنها را پوشش دهد ، اما برای سفارشی سازی بیشتر ، مرحله بعدی مفهوم Gatsby به نام سایه را بررسی می کند که به شما امکان می دهد قطعات یک موضوع را نادیده بگیرید.

مرحله 4 – استفاده از سایه (اختیاری)

در این مرحله از آموزش ، شما قبلاً یک تم شخص ثالث را در Gatsby نصب کرده و پیکربندی کرده اید. پیکربندی در gatsby-config.js انجام شد و محدود به گزینه هایی بود که ناشر موضوع برای سفارشی سازی آنها انتخاب کرده بود. اگر نیاز به سفارشی سازی یک موضوع فراتر از این گزینه ها دارید ، از یک مفهوم Gatsby به نام سایه استفاده می کنید ، که در این مرحله این کار را انجام می دهید.

اصطلاح سایه زنی به تمرین لغو یا گسترش یک فایل تم داخلی با تغییرات دلخواه شما اشاره دارد. برای کسانی که با وردپرس آشنا هستند ، این شبیه مفهوم تم کودک است.

با تم های Gatsby ، هر فایلی در کد منبع تم می تواند تحت سایه قرار گیرد ، از روش هایی که بر روی گره Gatsby و ایجاد فایل تأثیر می گذارد تا عناصر و طرح های UI. برای وبلاگ خود ، یک فایل کامپوننت React به نام bio-content.js را تحت سایه قرار دهید تا نحوه نمایش بیوگرافی وبلاگ شما در زیر هر پست سفارشی شود. با سایه انداختن این یک فایل ، بر ظاهر هر پست وبلاگی که از طریق افزونه gatsby-theme-blog می گذرد تأثیر می گذارید.

اولین قدم برای ایجاد سایه این است که یک پوشه در فهرست src خود با نام دقیق افزونه تم مورد نظر خود ایجاد کنید. می توانید این کار را به صورت دستی یا با ترمینال انجام دهید:

mkdir src/gatsby-theme-blog

برای هر فایل خاصی در تم که می خواهید سایه داشته باشد ، مرحله بعدی ایجاد یک پرونده با همان نام و ساختار دایرکتوری مشابه در موضوع است. از آنجا که قصد دارید جزء زیستی موجود را کمی تغییر دهید ، می توانید با کپی کردن فایل موجود به عنوان نقطه شروع ، با دستور cp (copy) در زمان خود صرفه جویی کنید.

mkdir -p src/gatsby-theme-blog/components
cp node_modules/gatsby-theme-blog/src/components/bio-content.js src/gatsby-theme-blog/components/bio-content.js

اکنون فایل تازه کپی شده را باز کرده و تغییرات زیر را انجام دهید:

src/gatsby-theme-blog/components/bio-content.js

import React, { Fragment } from "react"

const BioContent = () => (
  <Fragment>
    <p>Content by vpsgol</p>
    <p>License Info:</p>
    <p
      style={{
        margin: "10px 20px",
        padding: 8,
        backgroundColor: "#0069ff",
        color: "white",
        borderRadius: 12,
      }}
    >
      This work is licensed under a Creative Commons
      Attribution-NonCommercial-ShareAlike 4.0 International License.
    </p>
  </Fragment>
)

export default BioContent

این فایل را ذخیره و ببندید ، زیرا اکنون ویرایش فایل سایه را انجام داده اید.

در این فایل ، شما فایل اصلی bio-content.js را تحت سایه قرار داده اید ، و متن نویسنده را با نام نویسنده و اطلاعات مجوز جایگزین کرده اید. شما این کار را با جایگزینی JSX برگردانده شده توسط کامپوننت BioContent React انجام داده اید. کد style = {{}} نمونه ای از CSS درون خطی است که از آن برای افزودن رنگ و فاصله به فراخوان مجوز استفاده کرده اید.

با اجرای مجدد npm run در ترمینال خود ، سرور توسعه Gatsby را راه اندازی می کنید و می توانید تغییرات را در همه پست های وبلاگ خود پیش نمایش کنید:

با استفاده از سایه زدن Gatsby ، شما فقط یک موضوع شخص ثالث Gatsby را فراتر از پیکربندی استاندارد تغییر داده اید و در لغو و افزونه های سفارشی خود مخلوط شده اید.

نتیجه

با دنبال کردن مراحل این آموزش ، اکنون یک سایت Gatsby دارید که از یک موضوع منتشر شده برای جمع آوری اجزای متعدد و قطعات عملکرد بسته به عنوان یک وابستگی واحد استفاده می کند. به لطف این قابلیت بسته بندی شده ، اکنون به روز رسانی سایت شما آسان تر است و علیرغم داشتن ویژگی های اضافی ، می تواند پیکربندی و کد راه اندازی بسیار کمتری داشته باشد. شما همچنین آموخته اید که چگونه از سایه برای سفارشی کردن تم های Gatsby در سطح عمیق تری بر اساس فایل استفاده کنید و قفل لایه دیگری از قابلیت توسعه را باز کنید.

اگرچه این آموزش یک موضوع خاص را پوشش می دهد ، اما مفاهیم و رویکردهایی که به آن اشاره می شود به طور کلی در موضوعات Gatsby کاربرد دارد. برای اطلاعات بیشتر در مورد موضوعات Gatsby ، به اسناد رسمی Gatsby نگاه کنید. اگر مایل به مطالعه بیشتر در مورد Gatsby هستید ، بقیه نحوه ایجاد وب سایت های استاتیک با سری Gatsby.js را بررسی کنید.

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه راه اندازی WireGuard در Rocky Linux 8

ورود به سایت

 

معرفی

WireGuard یک شبکه خصوصی مجازی سبک (VPN) است که از اتصالات IPv4 و IPv6 پشتیبانی می کند. VPN به شما امکان می دهد شبکه های غیرقابل اعتماد را مانند یک شبکه خصوصی پشت سر بگذارید. این به شما این آزادی را می دهد که از طریق تلفن هوشمند یا لپ تاپ خود با خیال راحت و ایمن به اینترنت متصل شوید ، وقتی به یک شبکه غیرقابل اعتماد متصل هستید ، مانند WiFi در هتل یا کافی شاپ.

رمزگذاری WireGuard برای ایجاد یک تونل رمزگذاری شده بین خود به کلیدهای عمومی و خصوصی برای همکاران متکی است. هر نسخه از WireGuard از مجموعه رمزنگاری خاصی برای اطمینان از سادگی ، امنیت و سازگاری با همسالان استفاده می کند.

در مقایسه ، سایر نرم افزارهای VPN مانند OpenVPN و IPSec از امنیت لایه انتقال (TLS) و گواهینامه ها برای احراز هویت و ایجاد تونل های رمزگذاری شده بین سیستم ها استفاده می کنند. نسخه های مختلف TLS شامل پشتیبانی از صدها مجموعه و الگوریتم رمزنگاری مختلف است ، و در حالی که این امر انعطاف پذیری بالایی را برای پشتیبانی از مشتریان مختلف امکان پذیر می کند ، همچنین پیکربندی VPN ای را که از TLS وقت گیرتر ، پیچیده تر و مستعد خطا است ، ایجاد می کند.

در این آموزش ، شما WireGuard را روی سرور Rocky Linux 8 راه اندازی می کنید و سپس دستگاه دیگری را پیکربندی می کنید تا با استفاده از هر دو اتصال IPv4 و IPv6 (که معمولاً به عنوان اتصال دو پشته نامیده می شود) به آن به صورت همتا متصل شود. همچنین می توانید نحوه هدایت ترافیک اینترنتی همتا را از طریق سرور WireGuard در پیکربندی دروازه ، علاوه بر استفاده از VPN برای یک تونل peer-to-peer رمزگذاری شده ، یاد بگیرید.

برای اهداف این آموزش ، ما سیستم Rocky Linux 8 دیگری را به عنوان همکار (که به آن مشتری نیز گفته می شود) در سرور WireGuard پیکربندی می کنیم. آموزش های بعدی این مجموعه نحوه نصب و اجرای WireGuard را در سیستم ها و دستگاه های Windows ، macOS ، Android و iOS توضیح می دهد.

پیش نیازها

برای پیگیری این آموزش ، شما نیاز دارید:

  • یک سرور Rocky Linux 8 با یک کاربر sudo غیر روت و فایروال فعال است. برای تنظیم این ، می توانید راه اندازی سرور اولیه ما را با آموزش Rocky Linux 8 دنبال کنید. ما در این راهنما از این به عنوان سرور WireGuard یاد می کنیم.
  • شما به یک ماشین مشتری نیاز دارید که از آن برای اتصال به سرور WireGuard خود استفاده کنید. در این آموزش ما به این دستگاه به عنوان WireGuard Peer اشاره می کنیم. برای اهداف این آموزش ، توصیه می شود از دستگاه محلی خود به عنوان WireGuard Peer استفاده کنید ، اما در صورت تمایل می توانید از سرورهای راه دور یا تلفن های همراه به عنوان مشتری استفاده کنید. اگر از سیستم از راه دور استفاده می کنید ، حتماً در قسمت های بعدی این آموزش ، تمام قسمت های اختیاری را دنبال کنید ، در غیر این صورت ممکن است خود را از سیستم خارج کنید.
  • برای استفاده از WireGuard با IPv6 ، همچنین باید اطمینان حاصل کنید که سرور شما پیکربندی شده است تا از این نوع ترافیک پشتیبانی کند. اگر می خواهید پشتیبانی IPv6 را با WireGuard فعال کنید و از قطره vpsgol استفاده می کنید ، لطفاً به این صفحه مستندات نحوه فعال کردن IPv6 در Droplets مراجعه کنید. هنگام ایجاد Droplet یا پس از آن با استفاده از دستورالعمل های آن صفحه ، می توانید پشتیبانی IPv6 را اضافه کنید.

مرحله 1 – نصب WireGuard و ایجاد یک جفت کلید

اولین قدم در این آموزش نصب WireGuard روی سرور شماست. برای شروع ، باید دو مخزن نرم افزار اضافی به فهرست بسته سرور خود ، epel و elrepo اضافه کنید. برای نصب آنها دستور زیر را اجرا کنید. توجه داشته باشید اگر در این جلسه برای اولین بار است که از sudo استفاده می کنید ، از شما خواسته می شود که رمز عبور کاربر sudo خود را ارائه دهید:

sudo dnf install elrepo-release epel-release

اکنون که سرور شما می تواند به مخازن موجود در بسته های WireGuard دسترسی پیدا کند ، WireGuard را با استفاده از دستورات زیر نصب کنید:

sudo dnf install kmod-wireguard wireguard-tools

اکنون که WireGuard را نصب کرده اید ، گام بعدی ایجاد تعمیر کلید خصوصی و عمومی برای سرور است. برای ایجاد کلیدها از دستورات wg genkey و wg pubkey استفاده می کنید و سپس کلید خصوصی را به فایل پیکربندی WireGuard اضافه می کنید.

از آنجا که شما در حال ایجاد یک کلید خصوصی هستید که برای رمزگذاری ترافیک در سرور WireGuard شما استفاده می شود ، مجوزهای پیش فرض اعمال شده بر روی پرونده های جدید باید قبل از ایجاد این فایل به طور موقت به یک مقدار محدود کننده تغییر کند. باید با استفاده از دستور umask مجوزهای پیش فرض را برای فایل های تازه ایجاد شده تنظیم کنید.

از دستور umask زیر برای اطمینان از ایجاد دایرکتوری ها و فایل های جدید  با مجوزهای محدود خواندن و نوشتن استفاده کنید:

umask 077

umask 077 اطمینان می دهد که فقط صاحب یک دایرکتوری می تواند در آن وارد شود و فقط صاحب یک فایل می تواند آن را بخواند یا بنویسد. مجدداً توجه داشته باشید که وقتی از پوسته خود خارج می شوید و دوباره وارد سیستم می شوید ، umask شما به مقدار پیش فرض 022 بازنشانی می شود ، که به شما اجازه می دهد فایل های جدیدی را که در سیستم ایجاد شده است بخوانید.

حالا می توانید با استفاده از دستور زیر کلید خصوصی را برای WireGuard ایجاد کنید:

wg genkey | sudo tee /etc/wireguard/private.key

شما باید یک خط خروجی کدگذاری base64 دریافت کنید که کلید خصوصی است. یک کپی از خروجی نیز در فایل /etc/wireguard/private.key برای مرجع بعدی توسط قسمت tee فرمان ذخیره می شود. کلید خصوصی خروجی را با دقت یادداشت کنید زیرا بعداً در این بخش باید آن را به فایل پیکربندی WireGuard اضافه کنید.

مرحله بعدی ایجاد کلید عمومی مربوطه است که از کلید خصوصی گرفته شده است. برای ایجاد فایل کلید عمومی از دستور زیر استفاده کنید:

sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

این دستور شامل سه فرمان جداگانه است که با استفاده از | اپراتور :

  • sudo cat /etc/wireguard/private.key: این دستور فایل کلید خصوصی را می خواند و آن را به جریان خروجی استاندارد منتقل می کند.
  • wg pubkey: فرمان دوم خروجی فرمان اول را به عنوان ورودی استاندارد خود می گیرد و برای تولید یک کلید عمومی پردازش می کند.
  • sudo tee /etc/wireguard/public.key: آخرین فرمان خروجی فرمان تولید کلید عمومی را می گیرد و آن را به پرونده ای با نام /etc/wireguard/public.key هدایت می کند.

هنگامی که فرمان را اجرا می کنید ، مجدداً یک خط خروجی کد شده base64 دریافت خواهید کرد ، که کلید عمومی سرور WireGuard شما است. آن را در جایی برای مرجع کپی کنید ، زیرا باید کلید عمومی را در هر همتایی که به سرور متصل می شود ، توزیع کنید.

مرحله 2 – انتخاب آدرس های IPv4 و IPv6

در قسمت قبل WireGuard را نصب کردید و یک جفت کلید ایجاد کردید که برای رمزگذاری ترافیک به و از سرور استفاده می شود. در این بخش ، یک فایل پیکربندی برای سرور ایجاد می کنید و WireGuard را تنظیم می کنید تا هنگام راه اندازی مجدد سرور به طور خودکار راه اندازی شود. شما همچنین آدرس های IPv4 و IPv6 خصوصی را برای استفاده با سرور WireGuard و همسالان خود تعریف خواهید کرد.

اگر قصد دارید از هر دو آدرس IPv4 و IPv6 استفاده کنید ، هر دو این بخش را دنبال کنید. در غیر این صورت ، دستورالعمل های مربوط به بخش مناسب VPN را برای نیازهای شبکه خود دنبال کنید.

مرحله 2 (الف) – انتخاب محدوده IPv4

اگر از سرور WireGuard خود با همتایان IPv4 استفاده می کنید ، سرور نیاز به طیف وسیعی از آدرس های IPv4 خصوصی دارد که برای مشتریان و رابط تونل آن استفاده می شود. شما می توانید طیف وسیعی از آدرس های IP را از بلوک های آدرس رزرو شده زیر انتخاب کنید (اگر می خواهید درباره نحوه تخصیص این بلوک ها از مشخصات RFC 1918 بیشتر بدانید):

  • 10.0.0.0 to 10.255.255.255 (10/8 prefix)
  • 172.16.0.0 to 172.31.255.255 (172.16/12 prefix)
  • 192.168.0.0 to 192.168.255.255 (192.168/16 prefix)

برای اهداف این آموزش ، از 10.8.0.0/24 به عنوان یک بلوک آدرس IP از اولین محدوده IP های رزرو شده استفاده خواهیم کرد. این محدوده تا 255 اتصال مختلف مختلف را امکان پذیر می کند ، و به طور کلی نباید آدرس های متداخل یا متناقض با سایر محدوده های IP خصوصی داشته باشد. اگر این محدوده مثال با شبکه های شما سازگار نیست ، می توانید طیف وسیعی از آدرس هایی را انتخاب کنید که با پیکربندی شبکه شما کار می کند.

سرور WireGuard از یک آدرس IP واحد برای آدرس IPv4 تونل خصوصی خود استفاده می کند. ما از 10.8.0.1/24 در اینجا استفاده می کنیم ، اما از هر آدرسی در محدوده 10.8.0.1 تا 10.8.0.255 می توان استفاده کرد. اگر از چیزی متفاوت از 10.8.0.1/24 استفاده می کنید ، آدرس IP مورد نظر خود را یادداشت کنید. شما این آدرس IPv4 را به فایل پیکربندی که در مرحله 3 تعریف کرده اید – ایجاد پیکربندی سرور WireGuard اضافه می کنید

مرحله 2 (ب) – انتخاب محدوده IPv6

اگر از WireGuard با IPv6 استفاده می کنید ، باید پیشوند آدرس منحصر به فرد IPv6 محلی منحصر به فرد را بر اساس الگوریتم RFC 4193 ایجاد کنید. آدرس هایی که با WireGuard استفاده می کنید با یک رابط مجازی تونل مرتبط خواهند بود. برای ایجاد یک پیشوند تصادفی و منحصر به فرد IPv6 در بلوک رزرو شده fd00 ::/8 آدرسهای خصوصی IPv6 ، باید چند مرحله را تکمیل کنید.

طبق RFC ، راه توصیه شده برای به دست آوردن یک پیشوند IPv6 منحصر به فرد این است که زمان روز را با یک مقدار شناسایی منحصر به فرد از یک سیستم مانند شماره سریال یا شناسه دستگاه ترکیب کنید. سپس این مقادیر هش شده و کوتاه می شوند و در نتیجه مجموعه ای از بیت ها را می توان به عنوان آدرس منحصر به فرد در بلوک IP های خصوصی fd00 ::/8 رزرو شده استفاده کرد.

برای شروع تولید محدوده IPv6 برای سرور WireGuard ، یک علامت زمان 64 بیتی را با استفاده از ابزار date با دستور زیر جمع آوری کنید:

date +%s%N

از سال 1970-01-01 00:00:00 UTC ترکیبی با هم ، عددی مانند زیر دریافت خواهید کرد ، که تعداد ثانیه ها (٪ s در دستور date) و نانو ثانیه (٪ N) است:

 

Output

1628101352127592197

مقدار را برای استفاده بعداً در این بخش در جایی ثبت کنید. در مرحله بعد ، مقدار id-machine برای سرور خود را از فایل/var/lib/dbus/machine-id کپی کنید. این شناسه مختص سیستم شماست و تا زمانی که سرور وجود دارد نباید تغییر کند.

cat /var/lib/dbus/machine-id

خروجی مانند موارد زیر را دریافت خواهید کرد:

 

/var/lib/dbus/machine-id

20086c25853947c7aeee2ca1ea849d7d

اکنون باید زمان بندی را با machine-id ترکیب کرده و مقدار حاصل را با استفاده از الگوریتم SHA-1 هش کنید. دستور از قالب زیر استفاده می کند:

printf <timestamp><machine-id> | sha1sum

دستور جایگزین را در timestamp و مقادیر هویت ماشین خود اجرا کنید:

printf 162810135212759219720086c25853947c7aeee2ca1ea849d7d | sha1sum

مقدار هش مانند موارد زیر را دریافت خواهید کرد:

 

Output

4f267c51857d6dc93a0bca107bca2f0d86fac3bc  -

توجه داشته باشید که خروجی دستور sha1sum بصورت هگزا دسیمال است ، بنابراین خروجی از دو کاراکتر برای نشان دادن یک بایت داده استفاده می کند. به عنوان مثال 4f و 26 در خروجی مثال دو بایت اول داده های هش شده هستند.

الگوریتم موجود در RFC فقط به حداقل 40 بیت یا 5 بایت خروجی هش شده نیاز دارد. از دستور cut برای چاپ 5 بایت رمزگذاری شده هگزا دسیمال از هش استفاده کنید:

printf 4f267c51857d6dc93a0bca107bca2f0d86fac3bc | cut -c 31-

آرگومان -c به دستور cut می گوید که فقط مجموعه مشخصی از کاراکترها را انتخاب کنید. آرگومان 31 به cut می گوید که همه کاراکترها را از موقعیت 31 تا انتهای خط ورودی چاپ کنید.

شما باید خروجی مانند موارد زیر را دریافت کنید:

 

Output

0d86fac3bc

در این خروجی مثال ، مجموعه بایت ها عبارتند از: 0d 86 fa c3 bc.

اکنون می توانید پیشوند شبکه IPv6 منحصر به فرد خود را با افزودن 5 بایت ایجاد شده با پیشوند fd بسازید و هر 2 بایت را با یک: colon برای خوانایی جدا کنید. از آنجا که هر زیر شبکه در پیشوند منحصر به فرد شما می تواند در مجموع 18،446،744،073،709،551،616 آدرس IPv6 احتمالی را در خود جای دهد ، می توانید برای سادگی زیر شبکه را به اندازه استاندارد 64 /محدود کنید.

با استفاده از بایت هایی که قبلاً با اندازه زیر شبکه /64 ایجاد شده بود ، پیشوند به شرح زیر خواهد بود:

 

Unique Local IPv6 Address Prefix

fd0d:86fa:c3bc::/64

این محدوده fd0d: 86fa: c3bc ::/64 چیزی است که شما برای اختصاص آدرس IP جداگانه به واسط های تونل WireGuard خود در سرور و همکاران استفاده خواهید کرد. برای اختصاص IP برای سرور ، 1 را پس از نویسه های نهایی :: اضافه کنید. آدرس حاصله fd0d: 86fa: c3bc :: 1/64 خواهد بود. همسالان می توانند از هر IP در محدوده استفاده کنند ، اما به طور معمول هر بار که یک همتا اضافه می کنید ، مقدار را به یک افزایش می دهید ، به عنوان مثال fd0d: 86fa: c3bc :: 2/64. IP را یادداشت کرده و پیکربندی WireGuard Server را در قسمت بعدی این آموزش انجام دهید.

مرحله 3 – ایجاد پیکربندی سرور WireGuard

قبل از ایجاد پیکربندی سرور WireGuard ، به اطلاعات زیر نیاز دارید:

  1. مطمئن شوید که کلید خصوصی موجود در مرحله 1 را دارید – نصب WireGuard و ایجاد یک جفت کلید.
  2. اگر از WireGuard با IPv4 استفاده می کنید ، به آدرس IP ای که در مرحله 2 (a) برای سرور انتخاب کرده اید نیاز دارید – انتخاب محدوده IPv4 ، که در این مثال 10.8.0.1/24 است.
  3. اگر از WireGuard با IPv6 استفاده می کنید ، به آدرس IP سروری که در مرحله 2 (ب) ایجاد کرده اید – انتخاب محدوده IPv6) نیاز دارید. در این مثال IP fd0d: 86fa: c3bc :: 1/64 است.

هنگامی که کلید خصوصی و آدرس IP مورد نیاز را دارید ، یک فایل پیکربندی جدید با استفاده از vi یا ویرایشگر دلخواه خود با اجرای دستور زیر ایجاد کنید:

sudo vi /etc/wireguard/wg0.conf

خطوط زیر را به فایل اضافه کنید و کلید خصوصی خود را به جای مقدار مشخص شده base64_encoded_private_key_goes_here و آدرس (های) IP در خط آدرس جایگزین کنید. اگر می خواهید WireGuard در پورت دیگری در دسترس باشد ، می توانید خط ListenPort را تغییر دهید.

i را فشار دهید تا vi وارد حالت درج شود و سپس خطوط زیر را اضافه کنید:

 

/etc/wireguard/wg0.conf

[Interface]
PrivateKey = base64_encoded_private_key_goes_here
Address = 10.8.0.1/24, fd0d:86fa:c3bc::1/64
ListenPort = 51820
SaveConfig = true

خط SaveConfig تضمین می کند که وقتی رابط WireGuard خاموش می شود ، هرگونه تغییر در فایل پیکربندی ذخیره می شود.

پس از اتمام اعمال تغییرات ، ESC و سپس: wq را فشار دهید تا تغییرات را در فایل بنویسید و خارج شوید. شما در حال حاضر پیکربندی اولیه سرور را دارید که می توانید بسته به نحوه استفاده از سرور WireGuard VPN خود ، بر اساس آن اقدام کنید.

مرحله 4 – تنظیم پیکربندی شبکه WireGuard Server

اگر از WireGuard برای اتصال همتای خود به سرور WireGuard استفاده می کنید تا فقط به خدمات روی سرور دسترسی داشته باشید ، نیازی به تکمیل این بخش ندارید. اگر می خواهید ترافیک اینترنت WireGuard Peer خود را از طریق سرور WireGuard هدایت کنید ، باید با دنبال کردن این بخش از آموزش ، ارسال IP را پیکربندی کنید.

برای پیکربندی حمل و نقل ، فایل /etc/sysctl.conf را با استفاده از vi یا ویرایشگر دلخواه خود باز کنید:

sudo vi /etc/sysctl.conf

اگر از IPv4 با WireGuard استفاده می کنید ، خط زیر را در پایین فایل اضافه کنید:

/etc/sysctl.conf

net.ipv4.ip_forward=1

اگر از IPv6 با WireGuard استفاده می کنید ، این خط را در پایین فایل اضافه کنید:

/etc/sysctl.conf

net.ipv6.conf.all.forwarding=1

اگر از IPv4 و IPv6 استفاده می کنید ، مطمئن شوید که هر دو خط را وارد کرده اید. پس از اتمام کار فایل را ذخیره و ببندید.

برای خواندن فایل و بارگذاری مقادیر جدید برای جلسه ترمینال فعلی خود ، دستور زیر را اجرا کنید:

sudo sysctl -p

 

Output

net.ipv6.conf.all.forwarding = 1
net.ipv4.ip_forward = 1

اکنون سرور WireGuard شما می تواند ترافیک ورودی را از دستگاه مجازی اترنت VPN به سرورهای دیگر و از آنجا به اینترنت عمومی هدایت کند. استفاده از این پیکربندی به شما امکان می دهد تمام ترافیک وب را از WireGuard Peer خود از طریق آدرس IP سرور خود مسیریابی کنید و آدرس IP عمومی مشتری شما به طور م hiddenثر پنهان می شود.

با این حال ، قبل از اینکه ترافیک از طریق سرور شما به درستی هدایت شود ، باید برخی از قوانین فایروال را پیکربندی کنید.

مرحله 5 – پیکربندی فایروال سرور WireGuard

در این بخش پیکربندی WireGuard Server را ویرایش می کنید تا قوانین فایروال cmd فایروال را اضافه کنید که باعث می شود ترافیک به سمت سرور و کلاینت ها به درستی مسیریابی شود. مانند بخش قبل ، اگر از WireGuard VPN خود برای اتصال دستگاه به دستگاه برای دسترسی به منابع محدود شده برای VPN خود استفاده می کنید ، این مرحله را رد کنید.

برای افزودن قوانین فایروال به سرور WireGuard ، برخی از قوانین دائمی را ایجاد می کنید که از پیکربندی صحیح سرور در هنگام راه اندازی مجدد اطمینان حاصل می کند. برای دسترسی به سرویس WireGuard در پورت UDP 51820 موارد زیر را اجرا کنید:

sudo firewall-cmd –zone=public –add-port=51820/udp –permanent

در مرحله بعد باید دستگاه wg0 را به منطقه داخلی اضافه کنید ، که به ترافیک رابط VPN اجازه می دهد تا به رابط های دیگر در سرور WireGuard برسد. اگر از سرور به عنوان دروازه VPN برای تمام ترافیک اینترنت Peer استفاده می کنید ، این تنظیم بسیار مهم است. اگر در آینده تونل های WireGuard بیشتری به سرور خود اضافه می کنید ، حتماً دستگاه های آنها را به منطقه داخلی یا مورد اطمینان نیز اضافه کنید.

برای افزودن رابط wg0 به منطقه داخلی موارد زیر را اجرا کنید:

sudo firewall-cmd –zone=internal –add-interface=wg0 –permanent

در نهایت ، اگر از سرور WireGuard به عنوان دروازه VPN استفاده می کنید ، باید یک قانون ماسکراس را به منطقه عمومی اضافه کنید. Masquerading برای بازنویسی ترافیکی که در یک رابط داخلی وارد می شود (در این مورد wg0) استفاده می شود تا به نظر برسد که مستقیماً از آدرس های عمومی IPv4 یا IPv6 سرور WireGuard سرچشمه می گیرد.

دستورات زیر را برای فعال کردن مخفی سازی ، جایگزینی در محدوده شبکه IPv4 و IPv6 خود به جای مقادیر برجسته ، اجرا کنید:

sudo firewall-cmd –zone=public –add-rich-rule=’rule family=ipv4 source address=10.8.0.0/24 masquerade’ –permanent
sudo firewall-cmd –zone=public –add-rich-rule=’rule family=ipv6 source address=fd0d:86fa:c3bc::/64 masquerade’ –permanent

اکنون فایروال را مجدداً بارگذاری کنید تا تغییرات اعمال شده و از دائمی بودن آنها اطمینان حاصل کنید:

sudo firewall-cmd –reload

اکنون می توانید وضعیت کل مناطق عمومی ، داخلی یا سایر فایروال ها را بررسی کنید تا با اجرای دستور زیر از وجود قوانین اطمینان حاصل کنید. جایگزین منطقه ای که می خواهید به جای نام عمومی برجسته شده آن را بررسی کنید:

sudo firewall-cmd –zone=public –list-all

خروجی مانند موارد زیر را دریافت خواهید کرد:

 

Output

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0 eth1
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 51820/udp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
    rule family="ipv4" source address="10.8.0.0/24" masquerade
    rule family="ipv6" source address="fd0d:86fa:c3bc::/64" masquerade

مقادیر برجسته شده حاکی از قاعده ای است که اجازه می دهد ترافیک UDP در پورت 51820 موجود باشد و مخفی سازی برای هر یک از شبکه های ذکر شده فعال است.

همچنین می توانید با استفاده از دستور زیر تأیید کنید که قانون ارسال داخلی وجود دارد:

sudo firewall-cmd –zone=internal –list-interfaces

در صورت وجود قانون ، خروجی مشابه زیر دریافت خواهید کرد:

 

Output

wg0

سرور WireGuard شما پیکربندی شده است تا بتواند ترافیک VPN را به درستی مدیریت کند ، از جمله حمل و نقل و نقاب برای همسالان. با رعایت قوانین فایروال ، می توانید سرویس WireGuard را برای گوش دادن به ارتباطات همتا راه اندازی کنید.

مرحله 6 – راه اندازی سرور WireGuard

WireGuard را می توان پیکربندی کرد تا با استفاده از اسکریپت wg-quick خود به عنوان یک سرویس systemd اجرا شود. در حالی که می توانید به صورت دستی از دستور wg برای ایجاد تونل در هر زمان که می خواهید از VPN استفاده کنید استفاده کنید ، انجام این کار یک فرآیند دستی است که تکراری و مستعد خطا می شود. در عوض ، می توانید از systemctl برای مدیریت تونل با کمک اسکریپت wg-quick استفاده کنید.

استفاده از سرویس systemd به این معنی است که می توانید WireGuard را برای راه اندازی در هنگام راه اندازی پیکربندی کنید تا بتوانید در هر زمان که سرور در حال اجرا است به VPN خود متصل شوید. برای انجام این کار ، سرویس wg-quick را برای تونل wg0 که با افزودن آن به systemctl تعریف کرده اید ، فعال کنید:

sudo systemctl enable wg-quick@wg0.service

توجه داشته باشید که فرمان نام تونل wg0 را به عنوان بخشی از نام سرویس مشخص می کند. این نام به فایل پیکربندی /etc/wireguard/wg0.conf مربوط می شود. این رویکرد برای نامگذاری به این معنی است که می توانید هر تعداد دلخواه که از سرور خود استفاده می کنید تونل VPN جداگانه ایجاد کنید. هر تونل می تواند شامل IPv4 ، IPv6 و تنظیمات فایروال مشتری باشد.

حالا سرویس را شروع کنید:

sudo systemctl start wg-quick@wg0.service

با دستور زیر بررسی کنید که سرویس WireGuard فعال است. شما باید خروجی را فعال (در حال اجرا) ببینید:

sudo systemctl status wg-quick@wg0.service

 

Output

● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
   Loaded: loaded (/usr/lib/systemd/system/wg-quick@.service; enabled; vendor preset: disabled)
   Active: active (exited) since Fri 2021-09-17 19:58:14 UTC; 6 days ago
     Docs: man:wg-quick(8)
           man:wg(8)
           https://www.wireguard.com/
           https://www.wireguard.com/quickstart/
           https://git.zx2c4.com/wireguard-tools/about/src/man/wg-quick.8
           https://git.zx2c4.com/wireguard-tools/about/src/man/wg.8
 Main PID: 22924 (code=exited, status=0/SUCCESS)
    Tasks: 0 (limit: 11188)
   Memory: 0B
   CGroup: /system.slice/system-wg\x2dquick.slice/wg-quick@wg0.service

Sep 17 19:58:14 wg0 systemd[1]: Starting WireGuard via wg-quick(8) for wg0...
Sep 17 19:58:14 wg0 wg-quick[22924]: [#] ip link add wg0 type wireguard
Sep 17 19:58:14 wg0 wg-quick[22924]: [#] wg setconf wg0 /dev/fd/63
Sep 17 19:58:14 wg0 wg-quick[22924]: [#] ip -4 address add 10.8.0.1/24 dev wg0
Sep 17 19:58:14 wg0 wg-quick[22924]: [#] ip -6 address add fd0d:86fa:c3bc::1/64 dev wg0
Sep 17 19:58:14 wg0 wg-quick[22924]: [#] ip link set mtu 1420 up dev wg0
Sep 17 19:58:14 wg0 systemd[1]: Started WireGuard via wg-quick(8) for wg0.

توجه کنید که چگونه خروجی دستورات ip را که برای ایجاد دستگاه مجازی wg0 استفاده می شود نشان می دهد و آدرس IPv4 و IPv6 را که به فایل پیکربندی اضافه کرده اید به آن اختصاص می دهد. اگر می خواهید پیکربندی دستی VPN را پیکربندی کنید ، می توانید از این قوانین برای عیب یابی تونل استفاده کنید ، یا با خود دستور wg.

با سرور پیکربندی و اجرا ، گام بعدی این است که دستگاه مشتری خود را به صورت WireGuard Peer پیکربندی کرده و به سرور WireGuard متصل شوید.

مرحله 7 – پیکربندی WireGuard Peer

پیکربندی یک همتای WireGuard مشابه راه اندازی WireGuard Server است. هنگامی که نرم افزار سرویس گیرنده را نصب کردید ، یک جفت کلید عمومی و خصوصی ایجاد می کنید ، در مورد آدرس IP یا آدرس برای همتای خود تصمیم می گیرید ، یک فایل پیکربندی برای همتا تعریف می کنید و سپس با استفاده از اسکریپت wg-quick تونل را راه اندازی می کنید.

با ایجاد یک جفت کلید و پیکربندی با استفاده از مراحل زیر ، می توانید هر تعداد همکار که دوست دارید به VPN خود اضافه کنید. اگر چندین VPN را به VPN اضافه می کنید ، حتماً آدرس IP خصوصی آنها را پیگیری کنید تا از برخورد جلوگیری شود.

برای پیکربندی WireGuard Peer ، مطمئن شوید که بسته WireGuard را با استفاده از دستورات dnf زیر نصب کرده اید. در اجرای همکار WireGuard:

sudo dnf install elrepo-release epel-release
sudo dnf install kmod-wireguard wireguard-tools

ایجاد جفت کلید WireGuard Peer’s Key

در مرحله بعد ، باید جفت کلید را در همتا با استفاده از مراحل مشابهی که در سرور استفاده می کنید ایجاد کنید. از دستگاه محلی یا سرور راه دور خود که به عنوان همکار عمل می کند ، دستور زیر را برای تنظیم umask روی 077 اجرا کنید:

umask 077

اکنون می توانید با استفاده از دستور زیر کلید خصوصی را برای همتا ایجاد کنید:

wg genkey | sudo tee /etc/wireguard/private.key

مجدداً یک خط خروجی کد شده base64 دریافت خواهید کرد که کلید خصوصی است. یک نسخه از خروجی نیز در /etc/wireguard/private.key ذخیره می شود. کلید خصوصی خروجی را با دقت یادداشت کنید زیرا بعداً در این بخش باید آن را به فایل پیکربندی WireGuard اضافه کنید.

سپس برای ایجاد فایل کلید عمومی از دستور زیر استفاده کنید:

sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

مجدداً یک خط خروجی کد شده base64 دریافت خواهید کرد که کلید عمومی WireGuard Peer شما است. آن را در جایی برای مرجع کپی کنید ، زیرا برای ایجاد یک اتصال رمزگذاری شده ، باید کلید عمومی را در سرور WireGuard توزیع کنید.

ایجاد فایل پیکربندی WireGuard Peer

اکنون که یک جفت کلید دارید ، می توانید یک فایل پیکربندی برای همتای خود ایجاد کنید که حاوی تمام اطلاعات مورد نیاز برای ایجاد ارتباط با سرور WireGuard باشد.

برای فایل پیکربندی به چند قطعه اطلاعات نیاز دارید:

  • base64 کلید خصوصی را که در همتا ایجاد کرده اید رمزگذاری کرد.
  • محدوده آدرس IPv4 و IPv6 که در سرور WireGuard تعریف کرده اید.
  • base64 کلید عمومی را از سرور WireGuard رمزگذاری کرد.
  • آدرس IP عمومی و شماره پورت سرور WireGuard. معمولاً این آدرس IPv4 خواهد بود ، اما اگر سرور شما دارای آدرس IPv6 است و دستگاه سرویس گیرنده شما دارای اتصال IPv6 به اینترنت است ، می توانید به جای IPv4 از این آدرس استفاده کنید.

با تمام این اطلاعات موجود ، یک فایل /etc/wireguard/wg0.conf جدید در دستگاه WireGuard Peer با استفاده از vi یا ویرایشگر دلخواه خود باز کنید:

sudo vi /etc/wireguard/wg0.conf

خطوط زیر را به فایل اضافه کنید و در صورت لزوم داده های مختلف را در قسمت های برجسته جایگزین کنید:

 

/etc/wireguard/wg0.conf

[Interface]
PrivateKey = base64_encoded_peer_private_key_goes_here
Address = 10.8.0.2/24
Address = fd0d:86fa:c3bc::2/64

[Peer]
PublicKey = base64_encoded_server_public_key_goes_here
AllowedIPs = 10.8.0.0/24, fd0d:86fa:c3bc::/64
Endpoint = 203.0.113.1:51820

 

توجه کنید که چگونه اولین خط آدرس از آدرس IPv4 از زیر شبکه 10.8.0.0/24 که قبلاً انتخاب کرده اید استفاده می کند. این آدرس IP می تواند هر چیزی در زیر شبکه باشد مگر اینکه با IP سرور متفاوت باشد. افزایش آدرس ها به میزان 1 در هر بار افزودن یک همتا به طور کلی ساده ترین راه برای تخصیص IP است.

به همین ترتیب ، توجه کنید که خط دوم آدرس چگونه از آدرس IPv6 از زیر شبکه ای که قبلاً ایجاد کرده اید استفاده می کند و آدرس سرور را یک بر یک افزایش می دهد. باز هم ، اگر تصمیم دارید از آدرس دیگری استفاده کنید ، هر IP موجود در محدوده معتبر است.

بخش قابل توجه دیگر فایل آخرین خط AllowedIPs است. این دو محدوده IPv4 و IPv6 به همکاران دستور می دهند فقط در صورتی ترافیک از طریق VPN ارسال کنند که سیستم مقصد دارای آدرس IP در هر محدوده باشد. با استفاده از دستورالعمل AllowedIPs ، می توانید VPN را بر روی همتا محدود کنید تا فقط به سایر خدمات و خدمات مشابه در VPN متصل شود ، یا می توانید تنظیماتی را انجام دهید که تمام ترافیک VPN را تونل گذاری کرده و از سرور WireGuard به عنوان دروازه استفاده کنید.

اگر فقط از IPv4 استفاده می کنید ، محدوده fd0d: 86fa: c3bc ::/64 (شامل کاما) را حذف کنید. برعکس ، اگر فقط از IPv6 استفاده می کنید ، فقط پیشوند fd0d: 86fa: c3bc ::/64 را وارد کنید و محدوده 10.8.0.0/24 IPv4 را کنار بگذارید.

در هر دو مورد ، اگر می خواهید تمام ترافیک همسالان خود را از طریق VPN ارسال کنید و از سرور WireGuard به عنوان دروازه ای برای همه ترافیک استفاده کنید ، می توانید از 0.0.0.0/0 ، که نشان دهنده کل فضای آدرس IPv4 است ، و :: /0 برای کل فضای آدرس IPv6.

(اختیاری) پیکربندی یک همتا برای مسیریابی تمام ترافیک در تونل

اگر تصمیم گرفته اید تمام ترافیک همکاران خود را از طریق تونل با استفاده از مسیرهای 0.0.0.0/0 یا ::/0 مسیریابی کنید و همتا یک سیستم از راه دور است ، باید مراحل این بخش را تکمیل کنید. اگر همتای شما یک سیستم محلی است ، بهتر است از این بخش صرف نظر کنید.

برای همسالان از راه دور که از طریق SSH یا پروتکل دیگری با استفاده از آدرس IP عمومی به آنها دسترسی پیدا می کنید ، باید برخی قوانین اضافی را به فایل wg0.conf همتا اضافه کنید. این قوانین تضمین می کند که شما هنوز می توانید از خارج از تونل به سیستم متصل شوید. در غیر این صورت ، هنگامی که تونل ایجاد می شود ، تمام ترافیکی که معمولاً در رابط شبکه عمومی انجام می شود ، به درستی جهت دور زدن رابط تونل wg0 هدایت نمی شوند و منجر به یک سیستم از راه دور می شود.

ابتدا باید آدرس IP ای را که سیستم به عنوان دروازه پیش فرض خود استفاده می کند ، تعیین کنید. دستور ip route زیر را اجرا کنید:

ip route list table main default

خروجی مانند موارد زیر را دریافت خواهید کرد:

 

Output

default via 203.0.113.1 dev eth0 proto static

به آدرس IP برجسته 203.0.113.1 درگاه برای استفاده بعدی و eth0 دستگاه توجه کنید. ممکن است نام دستگاه شما متفاوت باشد. اگر چنین است ، آن را به جای eth0 در دستورات زیر جایگزین کنید.

سپس با بررسی دستگاه با دستور نشان دادن آدرس IP آدرس عمومی سیستم را بیابید:

ip -brief address show eth0

خروجی مانند موارد زیر را دریافت خواهید کرد:

 

Output

eth0             UP             203.0.113.5/20 10.20.30.40/16 2604:a880:400:d1::3d3:6001/64 fe80::68d5:beff:feff:974c/64

در این خروجی مثال ، IP برجسته 203.0.113.5 (بدون دنباله /20) آدرس عمومی است که به دستگاه eth0 اختصاص داده شده است که باید به پیکربندی WireGuard اضافه کنید.

اکنون فایل /etc/wireguard/wg0.conf WireGuard Peer را با vi یا ویرایشگر دلخواه خود باز کنید.

sudo vi /etc/wireguard/wg0.conf

قبل از خط [Peer] ، 4 خط زیر را اضافه کنید:

PostUp = ip rule add table 200 from 203.0.113.5
PostUp = ip route add table 200 default via 203.0.113.1
PreDown = ip rule delete table 200 from 203.0.113.5
PreDown = ip route delete table 200 default via 203.0.113.1

[Peer]
. . .

این خطوط یک قانون مسیریابی سفارشی ایجاد می کنند و یک مسیر سفارشی اضافه می کنند تا اطمینان حاصل شود که ترافیک عمومی به سیستم از دروازه پیش فرض استفاده می کند.

  • PostUp = ip rule add table 200 from 203.0.113.5 – این فرمان یک قاعده ایجاد می کند که هنگام ورود IP با آدرس عمومی 203.0.113.5 سیستم ، هرگونه ورودی مسیریابی در جدول شماره 200 را بررسی می کند.
  • PostUp = ip route add table 200 default by 203.0.113.1 – این دستور اطمینان می دهد که هر ترافیکی که توسط جدول 200 پردازش می شود ، به جای رابط WireGuard ، از دروازه 203.0.113.1 برای مسیریابی استفاده می کند.
  • خطوط PreDown هنگام خاموش شدن تونل ، قانون و مسیر سفارشی را حذف می کند.

اگر تمام ترافیک همکاران خود را از طریق VPN مسیریابی می کنید ، مطمئن شوید که در sysctl و firewall-cmd درست در سرور WireGuard در مرحله 4-تنظیم پیکربندی شبکه WireGuard سرور و مرحله 5-پیکربندی فایروال سرور WireGuard پیکربندی کرده اید.

(اختیاری) پیکربندی حل کننده های DNS WireGuard Peer

اگر از سرور WireGuard به عنوان یک دروازه VPN برای همه ترافیک همکاران خود استفاده می کنید ، باید خطی را به بخش [رابط] اضافه کنید که حل کننده های DNS را مشخص می کند. اگر این تنظیم را اضافه نکنید ، ممکن است درخواست های DNS شما توسط VPN محافظت نشود ، یا ممکن است به ارائه دهنده خدمات اینترنت شما یا سایر اشخاص ثالث فاش شود.

اگر فقط از WireGuard برای دسترسی به منابع در شبکه VPN یا پیکربندی peer-to-peer استفاده می کنید ، می توانید این بخش را رد کنید.

برای افزودن حل کننده های DNS به پیکربندی همکار خود ، ابتدا تعیین کنید سرور WireGuard شما از کدام سرورهای DNS استفاده می کند. دستور زیر را در سرور WireGuard اجرا کنید ، اگر نام دستگاه اترنت خود را به جای eth0 جایگزین کنید اگر متفاوت از این مثال باشد:

cat /etc/resolv.conf

شما باید خروجی مانند موارد زیر را دریافت کنید:

 

Output

; Created by cloud-init on instance boot automatically, do not edit.
;
nameserver 67.207.67.2
nameserver 67.207.67.3

آدرس های IP خروجی راه حل های DNS هستند که سرور از آنها استفاده می کند. بسته به نیاز خود می توانید از همه یا همه آنها یا فقط IPv4 یا IPv6 استفاده کنید. حل کننده هایی را که استفاده می کنید یادداشت کنید.

در مرحله بعد باید حل کننده های انتخابی خود را به فایل پیکربندی WireGuard Peer اضافه کنید. دوباره به WireGuard Peer برگردید ، فایل /etc/wireguard/wg0.conf را با استفاده از vi یا ویرایشگر دلخواه باز کنید:

sudo vi /etc/wireguard/wg0.conf

قبل از خط [Peer] موارد زیر را اضافه کنید:

DNS = 67.207.67.2 67.207.67.3

[Peer]
. . .

باز هم ، بسته به اولویت یا الزامات شما برای IPv4 و IPv6 ، می توانید لیست را با توجه به نیاز خود ویرایش کنید.

در مرحله بعد ، سرویس حل شده با سیستم را در Peer فعال و راه اندازی کنید تا وقتی تونل ایجاد شد ، حل کننده های DNS Peer به روز شود:

sudo systemctl enable systemd-resolved

اگر Rocky Linux و احتمالاً سایر توزیع های مشتق از RedHat مانند CentOS یا Fedora در حال اجرا هستند ، باید سیستم همتای خود را در این مرحله راه اندازی مجدد کنید. اگر آن را راه اندازی مجدد نکنید ، فایل /etc/resolv.conf هنگام راه اندازی تونل به دلیل اشکالی در برنامه های systemd-حل شده یا ابزارهای حفاظتی ، مجوزهای صحیح را تنظیم نمی کند. WireGuard Peer را با دستور زیر راه اندازی مجدد کنید:

sudo reboot

با وجود همه این تنظیمات حل کننده DNS و راه اندازی مجدد همکار ، اکنون آماده هستید که کلید عمومی همکار را به سرور اضافه کنید و سپس تونل WireGuard را روی همتا راه اندازی کنید.

مرحله 8 – افزودن کلید عمومی Peer به سرور WireGuard

قبل از اتصال همتا به سرور ، مهم است که کلید عمومی همتا را به سرور WireGuard اضافه کنید. این مرحله تضمین می کند که می توانید ترافیک را از طریق VPN متصل و مسیریابی کنید. بدون اتمام این مرحله ، سرور WireGuard به همکاران اجازه ارسال یا دریافت ترافیک از طریق تونل را نمی دهد.

با اجرای موارد زیر ، مطمئن شوید که نسخه ای از کلید عمومی کد شده base64 را برای WireGuard Peer در اختیار دارید:

sudo cat /etc/wireguard/public.key

 

Output

PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=

حالا وارد سرور WireGuard شده و دستور زیر را اجرا کنید:

sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2,fd0d:86fa:c3bc::2

توجه داشته باشید که قسمت مجاز-ips فرمان ، لیستی از آدرس های IPv4 و IPv6 را با کاما جدا می کند. اگر می خواهید آدرس IP را که یک همتا می تواند به خود اختصاص دهد محدود کنید یا اگر همسالان شما می توانند از هر آدرس IP در محدوده VPN استفاده کنند ، می توانید IP های فردی را تعیین کنید. همچنین توجه داشته باشید که هیچ یک از همسالان نمی توانند تنظیمات مجاز ips یکسانی داشته باشند.

اگر می خواهید ips مجاز برای یک همکار موجود را به روز کنید ، می توانید دوباره همان فرمان را اجرا کنید ، اما آدرس IP را تغییر دهید. چندین آدرس IP پشتیبانی می شود. به عنوان مثال ، برای تغییر WireGuard Peer که به تازگی اضافه کرده اید و IP ای مانند 10.8.0.100 را به IP های 10.8.0.2 و fd0d: 86fa: c3bc :: 2 موجود اضافه می کنید ، موارد زیر را اجرا کنید:

sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= allowed-ips 10.8.0.2,10.8.0.100,fd0d:86fa:c3bc::2

پس از اجرای دستور افزودن همتا ، وضعیت تونل را روی سرور با استفاده از دستور wg بررسی کنید:

sudo wg

 

Output

interface: wg0
 public key: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
 private key: (hidden)
 listening port: 51820

peer: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
 allowed ips: 10.8.0.2/32, fd0d:86fa:c3bc::/128

توجه کنید که چگونه خط همتا کلید عمومی WireGuard Peer و آدرس های IP یا محدوده آدرس هایی را نشان می دهد که مجاز است از آنها برای اختصاص IP خود استفاده کند.

اکنون که پارامترهای اتصال همتا را روی سرور تعریف کرده اید ، مرحله بعدی این است که تونل را روی همتا راه اندازی کنید.

مرحله 9 – اتصال WireGuard Peer به Tunnel

اکنون که سرور و همکار شما به گونه ای پیکربندی شده اند که از انتخاب IPv4 ، IPv6 ، ارسال بسته ها و وضوح DNS پشتیبانی می کنند ، زمان آن رسیده است که همتا را به تونل VPN متصل کنید.

از آنجا که ممکن است فقط بخواهید VPN برای موارد خاص استفاده شود ، ما از دستور wg-quick برای ایجاد اتصال بصورت دستی استفاده می کنیم. اگر می خواهید شروع به کار تونل را مانند سرور انجام دهید ، مراحل زیر را در مرحله 6 دنبال کنید-به جای استفاده از دستور wq-quick ، بخش WireGuard Server را راه اندازی کنید.

برای شروع تونل ، موارد زیر را در WireGuard Peer اجرا کنید:

sudo wg-quick up wg0

خروجی مانند موارد زیر را دریافت خواهید کرد:

 

Output

[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip -6 address add fd0d:86fa:c3bc::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0

آدرس های IPv4 و IPv6 برجسته ای را که به همتای خود اختصاص داده اید ، اضافه کنید.

اگر AllowedIPs را روی همتا روی 0.0.0.0/0 و ::/0 تنظیم کنید (یا از محدوده هایی غیر از محدوده هایی که برای VPN انتخاب کرده اید استفاده کنید) ، خروجی شما شبیه موارد زیر خواهد بود:

 

Output

[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 10.8.0.2/24 dev wg0
[#] ip -6 address add fd0d:86fa:c3bc::2/64 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] mount `67.207.67.2' /etc/resolv.conf
[#] wg set wg0 fwmark 51820
[#] ip -6 route add ::/0 dev wg0 table 51820
[#] ip -6 rule add not fwmark 51820 table 51820
[#] ip -6 rule add table main suppress_prefixlength 0
[#] nft -f /dev/fd/63
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] nft -f /dev/fd/63
[#] ip rule add table 200 from 203.0.113.5
[#] ip route add table 200 default via 203.0.113.1

در این مثال ، به مسیرهای برجسته شده ای که فرمان اضافه کرده و مربوط به AllowedIPs در پیکربندی همتا است توجه کنید.

در مرحله بعد ، با استفاده از ping مقداری ترافیک در رابط تونل ایجاد کنید تا یک بسته ICMP (که در دستورات زیر با آرگومان -c 1 مشخص شده است) به سرور WireGuard نشان داده شود:

ping -c 1 10.8.0.1

اگر تمام ترافیک را از طریق VPN مسیریابی می کنید ، می توانید به جای آن از یکی از سرورهای CloudFlare استفاده کنید:

ping -c 1 1.1.1.1

اکنون با استفاده از دستور wg وضعیت تونل را روی همتا بررسی کنید:

sudo wg

 

Output

interface: wg0
 public key: PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg=
 private key: (hidden)
 listening port: 49338
 fwmark: 0xca6c

peer: U9uE2kb/nrrzsEU58GD3pKFU3TLYDMCbetIsnV8eeFE=
 endpoint: 203.0.113.1:51820
 allowed ips: 10.8.0.0/24, fd0d:86fa:c3bc::/64
 latest handshake: 1 second ago
 transfer: 6.50 KiB received, 15.41 KiB sent

همچنین می توانید وضعیت سرور را دوباره بررسی کنید و خروجی مشابهی دریافت خواهید کرد.

با استفاده از دستورات مسیر ip و مسیر ip -6 تأیید کنید که همتای شما از VPN استفاده می کند. اگر از VPN به عنوان دروازه ای برای همه ترافیک اینترنت خود استفاده می کنید ، بررسی کنید که کدام رابط برای ترافیک مقصد 1.1.1.1 CloudFlare و 2606: 4700: 4700 :: 1111 DNS وضوح مورد استفاده قرار می گیرد.

ip route get 1.1.1.1

 

Output

1.1.1.1 dev wg0 table 51820 src 10.8.0.2 uid 1000
   cache

توجه داشته باشید که از دستگاه wg0 و آدرس IPv4 10.8.0.2 که به همتای خود اختصاص داده اید استفاده می شود. به همین ترتیب ، اگر از IPv6 استفاده می کنید ، موارد زیر را اجرا کنید:

ip -6 route get 2606:4700:4700::1111

 

Output

2606:4700:4700::1111 dev wg0 table 51820 src fd0d:86fa:c3bc::2 metric 1024 pref medium

دوباره به رابط wg0 و آدرس IPv6 fd0d: 86fa: c3bc :: 2 که به همتای خود اختصاص داده اید توجه کنید.

اگر مرورگر همتای شما نصب شده است ، همچنین می توانید از ipleak.net و ipv6-test.com دیدن کنید تا تأیید کنید که همتای شما ترافیک خود را از طریق VPN مسیریابی می کند.

هنگامی که آماده قطع ارتباط VPN با همکار هستید ، از دستور wg-quick استفاده کنید:

sudo wg-quick down wg0

خروجی مشابه زیر دریافت خواهید کرد که نشان می دهد تونل VPN خاموش است:

 

Output

[#] ip link delete dev wg0

اگر AllowedIPs را روی همتا روی 0.0.0.0/0 و ::/0 تنظیم کنید (یا از محدوده هایی غیر از محدوده هایی که برای VPN انتخاب کرده اید استفاده کنید) ، خروجی شما شبیه موارد زیر خواهد بود:

 

Output

[#] ip rule delete table 200 from 137.184.109.48
[#] ip route delete table 200 default via 137.184.96.1
[#] ip -4 rule delete table 51820
[#] ip -4 rule delete table main suppress_prefixlength 0
[#] ip -6 rule delete table 51820
[#] ip -6 rule delete table main suppress_prefixlength 0
[#] ip link delete dev wg0
[#] umount /etc/resolv.conf
[#] nft -f /dev/fd/63

برای اتصال مجدد به VPN ، دستور wg-quick up wg0 را دوباره روی همتا اجرا کنید. اگر می خواهید پیکربندی همتا را از سرور WireGuard حذف کنید ، می توانید دستور زیر را اجرا کنید ، مطمئن باشید که کلید عمومی صحیح را برای همتایی که می خواهید حذف کنید جایگزین کنید:

sudo wg set wg0 peer PeURxj4Q75RaVhBKkRTpNsBPiPSGb5oQijgJsTa29hg= remove

به طور معمول فقط در صورت عدم وجود همتای دیگر ، یا کلیدهای رمزگذاری آن به خطر افتاده یا تغییر کرده است ، باید پیکربندی همتا را حذف کنید. در غیر این صورت بهتر است پیکربندی را در محل خود بگذارید تا همکار بتواند مجدداً به VPN متصل شود بدون اینکه لازم باشد هر بار کلید و ips مجاز آن را اضافه کنید.

نتیجه

در این آموزش شما بسته و ابزار WireGuard را روی هر دو سیستم سرور و سرویس گیرنده Rocky Linux 8 نصب کرده اید. شما قوانین فایروال را برای WireGuard تنظیم کرده و تنظیمات هسته را پیکربندی کرده اید تا بتوانید با استفاده از دستور sysctl روی سرور ، ارسال بسته را انجام دهید. شما نحوه تولید کلیدهای رمزگذاری خصوصی و عمومی WireGuard و نحوه پیکربندی سرور و همکاران (یا همتا) برای اتصال به یکدیگر را آموختید.

اگر شبکه شما از IPv6 استفاده می کند ، همچنین آموخته اید که چگونه یک محدوده آدرس محلی منحصر به فرد برای استفاده از اتصالات همتا ایجاد کنید. در نهایت ، شما نحوه محدود کردن میزان ترافیک VPN را با محدود کردن پیشوندهای شبکه که همکار می تواند استفاده کند ، و همچنین نحوه استفاده از سرور WireGuard به عنوان یک دروازه VPN برای رسیدگی به تمام ترافیک اینترنت برای همسالان یاد گرفتید.

 

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه استفاده از دکوراتورها در TypeScript

ورود به سایت

معرفی

TypeScript افزونه ای از زبان جاوا اسکریپت است که از زمان اجرای جاوا اسکریپت با یک نوع تایپ کننده زمان کامپایل استفاده می کند. این ترکیب به توسعه دهندگان اجازه می دهد تا از اکوسیستم جاوا اسکریپت و ویژگی های زبان کامل استفاده کنند ، در حالی که علاوه بر این ، نوع تایپ استاتیک ، شمارش ها ، کلاس ها و رابط ها را در بالای آن اضافه می کنند. یکی از این ویژگی های اضافی پشتیبانی از دکوراتور است.

دکوراتورها راهی برای decorator اعضای یک کلاس یا خود کلاس با قابلیت های اضافی هستند. هنگامی که از یک decorator کننده برای یک کلاس یا عضو کلاس استفاده می کنید ، در واقع یک تابع را فراخوانی می کنید که جزئیات decorator شده را دریافت می کند ، و اجرای decorator قادر خواهد بود کد را به صورت پویا تغییر داده و قابلیت های اضافی را اضافه کند. کاهش کد بویلر آنها راهی برای متا برنامه نویسی در TypeScript هستند ، که یک تکنیک برنامه نویسی است که برنامه نویس را قادر می سازد تا کدی ایجاد کند که از کدهای دیگر خود برنامه به عنوان داده استفاده کند.

این آموزش به شما نشان می دهد که چگونه decorator خود را در TypeScript برای کلاس ها و اعضای کلاس ایجاد کنید ، و همچنین نحوه استفاده از آنها. شما را از طریق نمونه کد های مختلف راهنمایی می کند ، که می توانید آنها را در محیط TypeScript خود یا TypeScript Playground دنبال کنید ، یک محیط آنلاین که به شما امکان می دهد TypeScript را مستقیماً در مرورگر بنویسید.

پیش نیازها

برای پیگیری این آموزش ، شما نیاز دارید:

  • محیطی که در آن می توانید برنامه های TypeScript را اجرا کنید تا همراه با مثال ها دنبال کنید. برای تنظیم این دستگاه در دستگاه محلی خود ، به موارد زیر نیاز دارید.
    • هر دو Node و npm (یا نخ) به منظور اجرای یک محیط توسعه که بسته های مربوط به TypeScript را مدیریت می کند ، نصب شده است. این آموزش با Node.js نسخه 14.3.0 و npm نسخه 6.14.5 آزمایش شده است. برای نصب روی macOS یا اوبونتو 18.04 ، مراحل نحوه نصب Node.js و ایجاد محیط توسعه محلی در macOS یا بخش Installing using a PPA از نحوه نصب Node.js در اوبونتو 18.04 را دنبال کنید. اگر از زیر سیستم Windows برای Linux (WSL) استفاده می کنید ، این نیز کار می کند.
    • علاوه بر این ، به TypeScript Compiler (tsc) نصب شده بر روی دستگاه خود نیاز دارید. برای انجام این کار ، به وب سایت رسمی TypeScript مراجعه کنید.
  • اگر نمی خواهید محیط TypeScript را در دستگاه محلی خود ایجاد کنید ، می توانید از زمین بازی رسمی TypeScript برای پیگیری استفاده کنید.
  • شما به دانش کافی در مورد جاوا اسکریپت ، به ویژه نحو ES6+ ، مانند تخریب ، عملگرهای استراحت و واردات/صادرات نیاز دارید. اگر به اطلاعات بیشتری در مورد این موضوعات نیاز دارید ، خواندن نحوه کدگذاری در سری JavaScript توصیه می شود
  • این آموزش به جنبه های ویرایشگرهای متنی که از TypeScript پشتیبانی می کنند اشاره می کند و خطاهای خطی را نشان می دهد. این برای استفاده از TypeScript ضروری نیست ، اما از ویژگیهای TypeScript بیشتر استفاده می کند. برای به دست آوردن مزایای این موارد ، می توانید از ویرایشگر متنی مانند Visual Studio Code استفاده کنید که از TypeScript پشتیبانی کامل دارد. همچنین می توانید این مزایا را در TypeScript Playground امتحان کنید

همه نمونه های نشان داده شده در این آموزش با استفاده از TypeScript نسخه 4.2.2 ایجاد شده است.

فعال کردن پشتیبانی Decorators در TypeScript

در حال حاضر ، decorator هنوز یک ویژگی آزمایشی در TypeScript هستند و بنابراین ، ابتدا باید آن را فعال کنید. در این بخش ، بسته به نحوه کار با TypeScript ، نحوه فعال کردن decorator در TypeScript را خواهید دید.

CLI کامپایلر TypeScript

برای فعال کردن پشتیبانی دکوراتورها در هنگام استفاده از TypeScript Compiler CLI (tsc) تنها مرحله اضافی مورد نیاز این است که یک پرچم اضافی –experimentalDecorators:

tsc –experimentalDecorators

tsconfig.json

هنگام کار در پروژه ای که دارای فایل tsconfig.json است ، برای فعال کردن decorator تجربی ، باید ویژگی experimentalDecorators را به شیء compilerOptions اضافه کنید:

{
“compilerOptions”: {
“experimentalDecorators”: true
}
}

در زمین بازی TypeScript ، دکوراتورها به طور پیش فرض فعال هستند.

با استفاده از نحو دکوراتور

در این بخش ، شما در کلاسهای TypeScript از decorator استفاده خواهید کرد.

در TypeScript ، می توانید با استفاده از نحو خاصexpression ، decorator کننده ایجاد کنید ، جایی که بیان یک تابع است که به طور خودکار در زمان اجرا با جزئیات مربوط به هدفdecorator فراخوانی می شود.

هدف یک دکوراتور بستگی به جایی دارد که آنها را اضافه می کنید. در حال حاضر ، decorator را می توان به اجزای زیر کلاس اضافه کرد:

  • خود اعلام کلاس
  • خواص
  • دستیاران
  • مواد و روش ها
  • مولفه های

برای مثال ، فرض کنید شما یک decorator به نام مهر و موم شده دارید که Object.seal را در یک کلاس فراخوانی می کند. برای استفاده از دکوراتور خود می توانید موارد زیر را بنویسید:

@sealed
class Person {}

در کد برجسته شده توجه کنید که decorator را درست قبل از هدف decorator مهر و موم شده خود اضافه کرده اید ، در این مورد ، اعلان کلاس Person.

همین امر برای انواع دیگر decorators معتبر است:

@classDecorator
class Person {
  @propertyDecorator
  public name: string;

  @accessorDecorator
  get fullName() {
    // ...
  }

  @methodDecorator
  printName(@parameterDecorator prefix: string) {
    // ...
  }
}

 

برای افزودن چند decorator ، آنها را یکی پس از دیگری به هم اضافه کنید:

@decoratorA
@decoratorB
class Person {}

ایجاد دکوراتورهای کلاس در TypeScript

در این بخش مراحل ایجاد decorator کلاس در TypeScript را طی خواهید کرد.

برای decorator به نامdecoratorA ، به TypeScript می گویید که باید تابع decoratorA را فراخوانی کند. یک تابع با جزئیات نحوه استفاده از decorator در کد خود فراخوانی می شود. به عنوان مثال ، اگر decorator را برای اعلان کلاس اعمال کرده اید ، تابع جزئیات مربوط به کلاس را دریافت می کند. این عملکرد باید در حدی باشد که دکوراتور شما بتواند کار کند.

برای ایجاد دکوراتور خود ، باید تابعی با همان نام decorator خود ایجاد کنید. به این معنی که برای ایجاد decorator کلاس مهر و موم شده که در قسمت قبل مشاهده کردید ، باید یک تابع مهر و موم شده ایجاد کنید که مجموعه خاصی از پارامترها را دریافت می کند. بیایید دقیقاً همین کار را انجام دهیم:

@sealed
class Person {}

function sealed(target: Function) {
  Object.seal(target);
  Object.seal(target.prototype);
}

پارامتر (های) منتقل شده به دکوراتور بستگی به محل استفاده از دکوراتور دارد. پارامتر اول معمولاً هدف نامیده می شود.

دکوراتور مهر و موم شده فقط در اعلان های کلاس استفاده می شود ، بنابراین عملکرد شما یک پارامتر واحد ، هدف ، که از نوع Function است دریافت می کند. این سازنده کلاسی خواهد بود که decorator کننده روی آن اعمال شده است.

در تابع مهر و موم شده ، سپس Object.seal را روی هدف ، که سازنده کلاس است ، و همچنین در نمونه اولیه آنها فراخوانی می کنید. هنگامی که این کار را انجام می دهید ، هیچ ویژگی جدیدی نمی تواند به سازنده کلاس یا ویژگی آنها اضافه شود ، و خصوصیات موجود به عنوان غیر قابل تنظیم علامت گذاری می شوند.

مهم است که به یاد داشته باشید که در حال حاضر نمی توان نوع TypeScript هدف را هنگام استفاده از decorator گسترش داد. این بدان معناست که ، به عنوان مثال ، شما نمی توانید یک فیلد جدید با استفاده از یک تزئین کننده به کلاس اضافه کنید و آن را از نظر نوع ایمن کنید.

اگر درdecorator کلاس مهر و موم شده مقداری را برگردانید ، این مقدار به تابع سازنده جدید کلاس تبدیل می شود. این می تواند مفید باشد اگر می خواهید سازنده کلاس را به طور کامل بازنویسی کنید.

شما اولین decorator کننده خود را ایجاد کرده اید و از آن در کلاس استفاده کرده اید. در قسمت بعدی نحوه ایجاد کارخانه های decorator را خواهید آموخت.

ایجاد Decorator Factories

گاهی اوقات هنگام استفاده از دکوراتور باید گزینه های اضافی را به دکوراتور منتقل کنید و برای این کار باید از کارخانه های decorator استفاده کنید. در این بخش نحوه ایجاد آن کارخانه ها و استفاده از آنها را خواهید آموخت.

کارخانه های decorator توابعی هستند که عملکرد دیگری را برمی گردانند. آنها این نام را دریافت می کنند زیرا خود اجرای decorator نیستند. در عوض ، آنها عملکرد دیگری را که مسئول اجرای decorator است ، باز می گردانند و به عنوان یک تابع بسته بندی عمل می کنند. آنها در سفارشی سازی دکوراتورها مفید هستند ، زیرا اجازه می دهند کد مشتری هنگام استفاده از گزینه ها به decorator منتقل کند.

بیایید تصور کنیم که شما یک دکوراتور کلاس به نام decoratorA دارید و می خواهید گزینه ای را اضافه کنید که می توانید هنگام فراخوانی با دکوراتور مانند پرچم بولی تنظیم کنید. شما می توانید با نوشتن یک کارخانه تزئیناتی مشابه کارخانه زیر به این مهم برسید:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

در اینجا ، تابع decoratorA با پیاده سازی تزئین کننده ، عملکرد دیگری را برمی گرداند. توجه کنید که چگونه کارخانه تزئینات پرچم بولی را به عنوان تنها پارامتر خود دریافت می کند:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

هنگام استفاده از دکوراتور ، می توانید مقدار این پارامتر را منتقل کنید. کد برجسته شده را در مثال زیر مشاهده کنید:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

@decoratorA(true)
class Person {}

در اینجا ، وقتی از decoratorA decorator استفاده می کنید ، قرار است کارخانه تزئینات با پارامتر someBooleanFlag روی true تنظیم شود. سپس اجرای تزئین کننده خود اجرا می شود. این به شما امکان می دهد رفتار دکوراتور خود را بر اساس نحوه استفاده از آن تغییر دهید ، و سفارشی سازی و استفاده مجدد از دکوراتورها را از طریق برنامه خود آسان کنید.

توجه داشته باشید که لازم است تمام پارامترهای مورد انتظار کارخانه دکوراتور را گذرانده باشید. اگر به سادگی از دکوراتور بدون عبور از پارامترها استفاده کرده اید ، مانند مثال زیر:

const decoratorA = (someBooleanFlag: boolean) => {
  return (target: Function) => {
  }
}

@decoratorA
class Person {}

کامپایلر TypeScript دو خطا به شما می دهد که ممکن است بسته به نوع تزئین کننده متفاوت باشد. برای تزئین کنندگان کلاس خطاها 1238 و 1240 است:

 

Output

Unable to resolve signature of class decorator when called as an expression.
  Type '(target: Function) => void' is not assignable to type 'typeof Person'.
    Type '(target: Function) => void' provides no match for the signature 'new (): Person'. (1238)
Argument of type 'typeof Person' is not assignable to parameter of type 'boolean'. (2345)

شما فقط یک کارخانه تزئینات ایجاد کرده اید که قادر به دریافت پارامترها و تغییر رفتار آنها بر اساس این پارامترها است. در مرحله بعد با نحوه ایجاد تزئین کننده املاک آشنا می شوید.

ایجاد Property Decorators

ویژگی های کلاس مکان دیگری است که می توانید از دکوراتور استفاده کنید. در این بخش نحوه ایجاد آنها را بررسی می کنید.

هر دکوراتور املاک پارامترهای زیر را دریافت می کند:

  • برای خواص استاتیک ، تابع سازنده کلاس. برای سایر ویژگی ها ، نمونه اولیه کلاس.
  • نام عضو.

در حال حاضر ، هیچ راهی برای به دست آوردن توصیف ویژگی به عنوان پارامتر وجود ندارد. این به دلیل روشی است که طراحان ویژگی در TypeScript راه اندازی می شوند.

در اینجا یک عملکرد تزئین کننده وجود دارد که نام اعضا را روی کنسول چاپ می کند:

const printMemberName = (target: any, memberName: string) => {
console.log(memberName);
};

class Person {
@printMemberName
name: string = “Jon”;
}

وقتی کد TypeScript بالا را اجرا می کنید ، موارد زیر را در کنسول چاپ می کنید:

 

Output

name

می توانید از طراحان املاک برای نادیده گرفتن ملک مورد تزئین استفاده کنید. این را می توان با استفاده از Object.defineProperty همراه با یک setter و getter جدید برای ویژگی انجام داد. بیایید ببینیم چگونه می توانید یک تزئین کننده با نام فهرست مجاز ایجاد کنید ، که فقط اجازه می دهد یک ویژگی بر روی مقادیر موجود در یک لیست مجاز استاتیک تنظیم شود:

const allowlist = ["Jon", "Jane"];

const allowlistOnly = (target: any, memberName: string) => {
  let currentValue: any = target[memberName];

  Object.defineProperty(target, memberName, {
    set: (newValue: any) => {
      if (!allowlist.includes(newValue)) {
        return;
      }
      currentValue = newValue;
    },
    get: () => currentValue
  });
};

ابتدا ، شما یک لیست مجاز استاتیک در بالای کد ایجاد می کنید:

const allowlist = [“Jon”, “Jane”];

سپس در حال پیاده سازی تزئین کننده اموال هستید:

const allowlistOnly = (target: any, memberName: string) => {
  let currentValue: any = target[memberName];

  Object.defineProperty(target, memberName, {
    set: (newValue: any) => {
      if (!allowlist.includes(newValue)) {
        return;
      }
      currentValue = newValue;
    },
    get: () => currentValue
  });
};

توجه داشته باشید که چگونه از هر کدام به عنوان نوع هدف استفاده می کنید:

const allowlistOnly = (target: any, memberName: string) => {

برای طراحان ویژگی ، نوع پارامتر هدف می تواند سازنده کلاس یا نمونه اولیه کلاس باشد ، در این شرایط استفاده از آن آسان تر است.

در خط اول پیاده سازی تزئین کننده خود ، مقدار فعلی دارایی را که تزئین می کنید در متغیر currentValue ذخیره می کنید:

let currentValue: any = target[memberName];

برای خواص استاتیک ، در صورت وجود ، مقدار پیش فرض آنها تنظیم می شود. برای خواص غیر استاتیک ، این همیشه تعریف نشده است. این به این دلیل است که در زمان اجرا ، در کد جاوا اسکریپت کامپایل شده ، تزئین کننده قبل از اینکه ویژگی نمونه روی مقدار پیش فرض تنظیم شود ، اجرا می شود.

سپس با استفاده از Object.defineProperty ویژگی را لغو می کنید:

Object.defineProperty(target, memberName, {
  set: (newValue: any) => {
    if (!allowlist.includes(newValue)) {
      return;
    }
    currentValue = newValue;
  },
  get: () => currentValue
});

فراخوانی Object.defineProperty دارای getter و setter است. دریافت کننده مقدار ذخیره شده در متغیر currentValue را برمی گرداند. اگر تنظیم کننده مقدار currentVariable را روی newValue تنظیم کند ، اگر در لیست مجاز باشد.

بیایید از دکوراتوری که شما نوشتید استفاده کنیم. کلاس Person زیر را ایجاد کنید:

class Person {
  @allowlistOnly
  name: string = "Jon";
}

اکنون یک نمونه جدید از کلاس خود ایجاد می کنید ، و تنظیمات آزمایشی و بدست آوردن ویژگی نمونه نام:

const allowlist = ["Jon", "Jane"];

const allowlistOnly = (target: any, memberName: string) => {
  let currentValue: any = target[memberName];

  Object.defineProperty(target, memberName, {
    set: (newValue: any) => {
      if (!allowlist.includes(newValue)) {
        return;
      }
      currentValue = newValue;
    },
    get: () => currentValue
  });
};

class Person {
  @allowlistOnly
  name: string = "Jon";
}

const person = new Person();
console.log(person.name);

person.name = "Peter";
console.log(person.name);

person.name = "Jane";
console.log(person.name);

 

هنگام اجرای کد باید خروجی زیر را مشاهده کنید:

 

Output

Jon
Jon
Jane

مقدار هرگز روی Peter تنظیم نمی شود ، زیرا Peter در لیست مجاز نیست.

اگر می خواهید کد خود را کمی بیشتر استفاده کنید و اجازه دهید هنگام استفاده از دکوراتور ، لیست مجاز تنظیم شود ، چه می کنید؟ این یک مورد استفاده عالی برای decorator factories. است. بیایید دقیقاً همین کار را انجام دهیم ، با تبدیل دکوراسیون مجاز خود فقط دکوراتور به decorator factories.:

const allowlistOnly = (allowlist: string[]) => {
  return (target: any, memberName: string) => {
    let currentValue: any = target[memberName];

    Object.defineProperty(target, memberName, {
      set: (newValue: any) => {
        if (!allowlist.includes(newValue)) {
          return;
        }
        currentValue = newValue;
      },
      get: () => currentValue
    });
  };
}

در اینجا شما پیاده سازی قبلی خود را به یک عملکرد دیگر ، یک کارخانه تزئینات ، پیچانده اید. کارخانه تزئینات یک پارامتر به نام مجاز لیست دریافت می کند که مجموعه ای از رشته ها است.

اکنون برای استفاده از دکوراتور خود ، باید از فهرست مجاز مانند کد برجسته زیر عبور کنید:

class Person {
  @allowlistOnly(["Claire", "Oliver"])
  name: string = "Claire";
}

سعی کنید کدی شبیه کد قبلی که نوشتید اجرا کنید ، اما با تغییرات جدید:

const allowlistOnly = (allowlist: string[]) => {
  return (target: any, memberName: string) => {
    let currentValue: any = target[memberName];

    Object.defineProperty(target, memberName, {
      set: (newValue: any) => {
        if (!allowlist.includes(newValue)) {
          return;
        }
        currentValue = newValue;
      },
      get: () => currentValue
    });
  };
}

class Person {
  @allowlistOnly(["Claire", "Oliver"])
  name: string = "Claire";
}

const person = new Person();
console.log(person.name);
person.name = "Peter";
console.log(person.name);
person.name = "Oliver";
console.log(person.name);

کد باید خروجی زیر را به شما بدهد:

 

Output

Claire
Claire
Oliver

نشان می دهد که آنطور که انتظار می رود کار می کند ، person.name هرگز روی Peter تنظیم نمی شود ، زیرا Peter در فهرست مجاز داده شده نیست.

اکنون که اولین تزئین کننده دارایی خود را با استفاده از عملکرد معمول تزئین کننده و کارخانه تزئینات ایجاد کرده اید ، وقت آن است که به نحوه ایجاد تزئینات برای دستیاران کلاس نگاهی بیندازید.

ایجاد Accessor Decorators

در این قسمت نگاهی به چگونگی تزئین اعضای کلاس می اندازید.

درست مانند دکوراتورهای املاک ، دکوراتورهای مورد استفاده در یک accessor پارامترهای زیر را دریافت می کنند:

برای خواص استاتیک ، تابع سازنده کلاس ، برای همه خواص دیگر ، نمونه اولیه کلاس.
نام عضو.
اما متفاوت از دکوراتور ویژگی ، پارامتر سوم را نیز با ویژگی توصیف کننده ویژگی عضو دسترسی دریافت می کند.

با توجه به این واقعیت که ویژگی های توصیف کننده شامل هر دو تنظیم کننده و گیرنده برای یک عضو خاص است ، تزئین کننده های جانبی فقط می توانند برای تنظیم کننده یا گیرنده یک عضو واحد اعمال شوند ، نه برای هر دو.

اگر یک مقدار از تزئین کننده accessor خود را برگردانید ، این مقدار به عنوان توصیف کننده ویژگی جدید accessor برای هر دو گروه getter و setter تبدیل می شود.

در اینجا نمونه ای از یک تزئین کننده است که می تواند برای تغییر پرچم قابل شمارش دسترسی گیرنده/تنظیم کننده استفاده شود:

const enumerable = (value: boolean) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    propertyDescriptor.enumerable = value;
  }
}

در مثال به نحوه استفاده از کارخانه تزئینات توجه کنید. این به شما این امکان را می دهد که هنگام تماس با دکوراتور پرچم شمارش شده را مشخص کنید. در اینجا نحوه استفاده از دکوراتور خود آورده شده است:

class Person {
  firstName: string = "Jon"
  lastName: string = "Doe"

  @enumerable(true)
  get fullName () {
    return `${this.firstName} ${this.lastName}`;
  }
}

دکوراتورهای اکسسوری شبیه به دکوراتورهای املاک هستند. تنها تفاوت این است که آنها پارامتر سوم را با توصیف کننده ویژگی دریافت می کنند. اکنون که اولین تزئین کننده اکسسوری خود را ایجاد کرده اید ، بخش بعدی نحوه ایجاد تزئین کننده متد را به شما نشان می دهد.

ایجاد Method Decorators

در این قسمت نگاهی به نحوه استفاده از تزئین کننده های متد می اندازید.

اجرای روش های تزئینات بسیار شبیه به نحوه ایجاد تزئینات اکسسوری است. پارامترهای ارسال شده به اجرای تزئینی مشابه پارامترهایی است که به تزئین کننده های اکسسوری ارسال شده است.

بیایید از همان دکوراتور قابل شمارش که قبلاً ایجاد کرده اید دوباره استفاده کنیم ، اما این بار در متد getFullName کلاس Person زیر:

const enumerable = (value: boolean) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    propertyDescriptor.enumerable = value;
  }
}

class Person {
  firstName: string = "Jon"
  lastName: string = "Doe"

  @enumerable(true)
  getFullName () {
    return `${this.firstName} ${this.lastName}`;
  }
}

اگر مقداری را از تزئین کننده متد خود برگردانده اید ، این مقدار به توصیف کننده جدید ویژگی متد تبدیل می شود.

بیایید یک دکوراتور منسوخ ایجاد کنیم که وقتی از متد استفاده می شود پیام ارسال شده را روی کنسول چاپ می کند و پیامی را ثبت می کند که می گوید این روش منسوخ شده است:

const deprecated = (deprecationReason: string) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    return {
      get() {
        const wrapperFn = (...args: any[]) => {
          console.warn(`Method ${memberName} is deprecated with reason: ${deprecationReason}`);
          propertyDescriptor.value.apply(this, args)
        }

        Object.defineProperty(this, memberName, {
            value: wrapperFn,
            configurable: true,
            writable: true
        });
        return wrapperFn;
      }
    }
  }
}

 

در اینجا ، شما در حال ایجاد یک تزئین کننده با استفاده از یک کارخانه تزئینات هستید. این کارخانه تزئینی یک آرگومان واحد از نوع string دریافت می کند ، که دلیل عدم استفاده از آن است ، همانطور که در قسمت برجسته زیر نشان داده شده است:

const deprecated = (deprecationReason: string) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    // ...
  }
}

deprecationReason بعداً هنگام ورود پیام منسوخ شدن به کنسول استفاده می شود. در اجرای تزئین منسوخ شده خود ، یک مقدار را برمی گردانید. هنگامی که مقداری را از یک تزئین کننده متد برمی گردانید ، این مقدار روی توصیف کننده ویژگی این عضو بازنویسی می کند.

شما از این مزیت استفاده می کنید تا متد را به روش کلاس تزئین شده خود اضافه کنید. به این ترتیب می توانید پیاده سازی خود روش را تغییر دهید.

اما چرا فقط از Object.defineProperty به جای بازگشت یک تزئین کننده جدید برای روش استفاده نکنید؟ این امر ضروری است زیرا باید به مقدار این دسترسی داشته باشید ، که برای روشهای کلاس غیر استاتیک ، به نمونه کلاس متصل است. اگر مستقیماً از Object.defineProperty استفاده می کنید ، هیچ راهی برای بازیابی مقدار آن برای شما وجود نخواهد داشت ، و اگر متدی که به هر نحوی از این روش استفاده می کرد ، تزئین کننده هنگام اجرای روش پیچیده شده از داخل اجرای تزئین کننده ، کد شما را می شکند.

در مورد شما ، خود گیرنده این مقدار را برای نمونه های غیراستاتیک به نمونه کلاس و برای متدهای استاتیک به سازنده کلاس محدود می کند.

در داخل getter شما سپس یک تابع wrapper به صورت محلی ایجاد می کنید ، به نام wrapperFn ، این تابع با استفاده از console یک پیام را به کنسول وارد می کند. هشدار دهید ، با رد deprecationReason دریافت شده از کارخانه decorator ، سپس با استفاده از propertyDescriptor.value روش اصلی را فراخوانی می کنید. apply (this، args) ، به این ترتیب متد اصلی نامیده می شود که این مقدار به درستی به نمونه کلاس متصل شده است در صورتی که یک روش غیر استاتیک بود.

سپس از definProperty برای بازنویسی مقدار متد خود در کلاس استفاده می کنید. این مانند یک مکانیسم یادآوری عمل می کند ، زیرا تماس های متعدد با یک روش دیگر با گیرنده شما تماس نمی گیرد ، بلکه مستقیماً با wrapperFn تماس می گیرد. اکنون شما با استفاده از Object.defineProperty ، عضو کلاس را طوری تنظیم می کنید که wrapperFn شما به عنوان مقدار آن باشد.

بیایید از دکوراتور منسوخ شده شما استفاده کنیم:

const deprecated = (deprecationReason: string) => {
  return (target: any, memberName: string, propertyDescriptor: PropertyDescriptor) => {
    return {
      get() {
        const wrapperFn = (...args: any[]) => {
          console.warn(`Method ${memberName} is deprecated with reason: ${deprecationReason}`);
          propertyDescriptor.value.apply(this, args)
        }

        Object.defineProperty(this, memberName, {
            value: wrapperFn,
            configurable: true,
            writable: true
        });
        return wrapperFn;
      }
    }
  }
}

class TestClass {
  static staticMember = true;

  instanceMember: string = "hello"

  @deprecated("Use another static method")
  static deprecatedMethodStatic() {
    console.log('inside deprecated static method - staticMember =', this.staticMember);
  }

  @deprecated("Use another instance method")
  deprecatedMethod () {
    console.log('inside deprecated instance method - instanceMember =', this.instanceMember);
  }
}

TestClass.deprecatedMethodStatic();

const instance = new TestClass();
instance.deprecatedMethod();

در اینجا ، شما یک TestClass با دو ویژگی ایجاد کرده اید: یکی استاتیک و دیگری غیر استاتیک. شما همچنین دو روش ایجاد کرده اید: یکی استاتیک و دیگری غیر استاتیک.

سپس از تزئین کننده منسوخ خود برای هر دو روش استفاده می کنید. هنگام اجرای کد ، موارد زیر در کنسول ظاهر می شود:

 

Output

(warning) Method deprecatedMethodStatic is deprecated with reason: Use another static method
inside deprecated static method - staticMember = true
(warning)) Method deprecatedMethod is deprecated with reason: Use another instance method
inside deprecated instance method - instanceMember = hello

این نشان می دهد که هر دو روش به درستی با عملکرد wrapper شما بسته شده است ، که پیامی را با دلیل منسوخ شدن به کنسول وارد می کند.

اکنون شما اولین تزئین کننده متد خود را با استفاده از TypeScript ایجاد کرده اید. بخش بعدی نحوه ایجاد آخرین نوع تزئین کننده پشتیبانی شده توسط TypeScript ، یک تزئین کننده پارامتر را به شما نشان می دهد.

ایجاد پارامترهای Decorators

تزئینات پارامتری را می توان در پارامترهای روش کلاس استفاده کرد. در این بخش نحوه ایجاد آن را خواهید آموخت.

عملکرد تزئین کننده مورد استفاده با پارامترها پارامترهای زیر را دریافت می کند:

برای خواص استاتیک ، تابع سازنده کلاس. برای سایر خصوصیات ، نمونه اولیه کلاس.
نام عضو.
فهرست پارامترها در لیست پارامترهای متد.
تغییر هر چیزی که مربوط به خود پارامتر باشد امکان پذیر نیست ، بنابراین چنین تزئیناتی فقط برای مشاهده استفاده از خود پارامترها مفید هستند (مگر اینکه از موارد پیشرفته تری مانند بازتاب داده های بازتاب استفاده کنید).

در اینجا یک نمونه از تزئین کننده است که شاخص پارامتر تزئین شده را به همراه نام روش چاپ می کند:

function print(target: Object, propertyKey: string, parameterIndex: number) {
  console.log(`Decorating param ${parameterIndex} from ${propertyKey}`);
}

سپس می توانید پارامتر decorators خود را مانند این استفاده کنید:

class TestClass {
  testMethod(param0: any, @print param1: any) {}
}

اجرای کد بالا باید موارد زیر را در کنسول نمایش دهد:

 

Output

Decorating param 1 from testMethod

شما اکنون یک  پارامتر decorator ایجاد کرده و اجرا کرده اید و نتیجه ای را که شاخص پارامتر decorator را برمی گرداند چاپ می کنید.

نتیجه
در این آموزش ، شما تمام decorators پشتیبانی شده توسط TypeScript را پیاده سازی کرده اید ، از آنها در کلاس ها استفاده کرده اید و تفاوت های هر یک را یاد گرفته اید. اکنون می توانید برای کاهش کد صفحه بویلر در پایگاه کد خود ، نوشتن دکوراتورهای خود را شروع کنید ، یا با اطمینان بیشتر از دکوراتورهای کتابخانه هایی مانند Mobx استفاده کنید.

decoratorMethod DecoratorsProperty DecoratorsTypeScriptپارامترهای Decoratorsجاواجاوا اسکریپتسرورسرور مجازیکامپایلر TypeScript

  • behnam gol mohamadi
  • ۰
  • ۰

نحوه تنظیم کلیدهای SSH در Rocky Linux 8

ورود به سایت

معرفی

SSH یا پوسته امن ، یک پروتکل رمزگذاری شده است که برای مدیریت و ارتباط با سرورها استفاده می شود. هنگام کار با سرور لینوکس راکی ، به احتمال زیاد بیشتر وقت خود را در جلسه ترمینال متصل به سرور خود از طریق SSH خواهید گذراند.

در این راهنما ، ما بر تنظیم کلیدهای SSH برای سرور Rocky Linux 8 تمرکز می کنیم. کلیدهای SSH یک روش ساده و ایمن برای ورود به سرور شما ارائه می دهند و برای همه کاربران توصیه می شود.

مرحله 1 – ایجاد جفت کلید RSA

اولین قدم ایجاد یک جفت کلید در ماشین سرویس گیرنده (معمولاً رایانه محلی شما) است:

ssh-keygen

به طور پیش فرض ، ssh-keygen یک جفت کلید RSA 2048 بیتی ایجاد می کند ، که برای اکثر موارد استفاده از امنیت کافی برخوردار است (برای ایجاد یک کلید بزرگتر 4096 می توانید به صورت اختیاری در پرچم -b 4096 قرار دهید).

پس از وارد کردن فرمان ، باید اعلان زیر را مشاهده کنید:

Output
Generating public/private rsa key pair.
Enter file in which to save the key (/your_home/.ssh/id_rsa):

ENTER را فشار دهید تا جفت کلید در .ssh/ subdirectory در فهرست اصلی ذخیره شود ، یا یک مسیر جایگزین مشخص کنید.

اگر قبلاً یک جفت کلید SSH ایجاد کرده اید ، ممکن است درخواست زیر را مشاهده کنید:

Output
/home/your_home/.ssh/id_rsa already exists.
Overwrite (y/n)?

در صورت انتخاب بازنویسی کلید روی دیسک ، دیگر نمی توانید با استفاده از کلید قبلی احراز هویت کنید. هنگام انتخاب بله بسیار مراقب باشید ، زیرا این یک روند مخرب است که قابل برگشت نیست.

سپس باید اعلان زیر را مشاهده کنید:

Output
Enter passphrase (empty for no passphrase):

در اینجا می توانید به صورت اختیاری یک رمز عبور امن وارد کنید ، که بسیار توصیه می شود. عبارت عبور یک لایه امنیتی اضافی به کلید شما می افزاید تا از ورود کاربران غیر مجاز به سیستم جلوگیری کند.

سپس باید خروجی زیر را مشاهده کنید:

 

Output

Your identification has been saved in /your_home/.ssh/id_rsa.
Your public key has been saved in /your_home/.ssh/id_rsa.pub.
The key fingerprint is:
a9:49:2e:2a:5e:33:3e:a9:de:4e:77:11:58:b6:90:26 username@remote_host
The key's randomart image is:
+--[ RSA 2048]----+
|     ..o         |
|   E o= .        |
|    o. o         |
|        ..       |
|      ..S        |
|     o o.        |
|   =o.+.         |
|. =++..          |
|o=++.            |
+-----------------+

 

اکنون یک کلید عمومی و خصوصی دارید که می توانید از آن برای احراز هویت استفاده کنید. مرحله بعدی این است که کلید عمومی را به سرور خود وارد کنید تا بتوانید از سیستم احراز هویت مبتنی بر کلید SSH برای ورود به سیستم استفاده کنید.

مرحله 2 – کپی کلید عمومی در سرور لینوکس سنگی خود

سریعترین راه برای کپی کردن کلید عمومی در میزبان Rocky Linux استفاده از ابزاری به نام ssh-copy-id است. این روش در صورت وجود بسیار توصیه می شود. اگر ssh-copy-id را در دستگاه مشتری خود در اختیار ندارید ، می توانید از یکی از دو روش جایگزین زیر استفاده کنید (کپی از طریق SSH مبتنی بر رمز عبور ، یا کپی دستی کلید).

کپی کلید عمومی خود با استفاده از ssh-copy-id

ابزار ssh-copy-id به طور پیش فرض در بسیاری از سیستم عامل ها گنجانده شده است ، بنابراین ممکن است آن را در سیستم محلی خود در دسترس داشته باشید. برای اینکه این روش کار کند ، باید از قبل دسترسی SSH مبتنی بر گذرواژه به سرور خود داشته باشید.

برای استفاده از این ابزار ، فقط باید میزبان از راه دور که می خواهید به آن متصل شوید و حساب کاربری که رمز عبور SSH به آن دسترسی دارید را مشخص کنید. این حسابی است که کلید SSH عمومی شما در آن کپی می شود:

ssh-copy-id username@remote_host

ممکن است پیام زیر را مشاهده کنید:

 

Output

The authenticity of host '203.0.113.1 (203.0.113.1)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes

این بدان معناست که رایانه محلی شما میزبان از راه دور را تشخیص نمی دهد. این اولین باری است که به میزبان جدید متصل می شوید. بله را تایپ کنید و ENTER را برای ادامه فشار دهید.

در مرحله بعد ، برنامه حساب محلی شما را برای کلید id_rsa.pub که قبلاً ایجاد کرده ایم اسکن می کند. هنگامی که کلید را پیدا کرد ، از شما رمز عبور حساب کاربر از راه دور را درخواست می کند:

 

Output

/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
username@203.0.113.1's password:

رمز عبور را وارد کنید (تایپ شما برای اهداف امنیتی نمایش داده نمی شود) و ENTER را فشار دهید. این ابزار با استفاده از گذرواژه ای که ارائه کرده اید به حساب موجود در میزبان راه دور متصل می شود. سپس محتویات کلید ~/.ssh/id_rsa.pub شما را در فایل remote/.ssh/author_keys حساب از راه دور کپی می کند.

شما باید خروجی زیر را مشاهده کنید:

 

Output

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'username@203.0.113.1'"
and check to make sure that only the key(s) you wanted were added.

در این مرحله ، کلید id_rsa.pub شما در حساب راه دور بارگذاری شده است. می توانید به مرحله 3 ادامه دهید.

کپی کلید عمومی با استفاده از SSH

اگر ssh-copy-id در دسترس ندارید ، اما دسترسی SSH مبتنی بر رمز عبور به یک حساب کاربری در سرور خود دارید ، می توانید کلیدهای خود را با استفاده از یک روش مرسوم SSH بارگذاری کنید.

ما می توانیم این کار را با استفاده از دستور cat برای خواندن محتویات کلید عمومی SSH در رایانه محلی خود و پیپ کردن آن از طریق اتصال SSH به سرور راه دور انجام دهیم.

از طرف دیگر ، می توانیم مطمئن شویم که فهرست ~/.ssh وجود دارد و دارای مجوزهای صحیح تحت حساب مورد استفاده ما است.

سپس می توانیم محتوایی را که پیپ کرده ایم در فایلی به نام author_keys در این دایرکتوری خروجی دهیم. ما برای افزودن محتوا به جای بازنویسی از نماد تغییر مسیر >> استفاده می کنیم. این به ما اجازه می دهد کلیدها را بدون از بین بردن کلیدهای قبلی اضافه شده اضافه کنیم.

دستور کامل به این شکل است:

cat ~/.ssh/id_rsa.pub | ssh username@remote_host “mkdir -p ~/.ssh && touch ~/.ssh/authorized_keys && chmod -R go= ~/.ssh && cat >> ~/.ssh/authorized_keys”

ممکن است پیام زیر را مشاهده کنید:

 

Output

The authenticity of host '203.0.113.1 (203.0.113.1)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes

 

این بدان معناست که رایانه محلی شما میزبان از راه دور را تشخیص نمی دهد. این اولین باری است که به میزبان جدید متصل می شوید. بله را تایپ کنید و ENTER را برای ادامه فشار دهید.

پس از آن ، باید از شما خواسته شود که گذرواژه حساب کاربری از راه دور را وارد کنید:

 

Output

username@203.0.113.1's password:

پس از وارد کردن گذرواژه خود ، محتوای کلید id_rsa.pub شما در انتهای فایل مجاز_keys حساب کاربر از راه دور کپی می شود. در صورت موفقیت آمیز بودن مرحله 3 را ادامه دهید.

کپی کلید عمومی به صورت دستی

اگر دسترسی SSH مبتنی بر رمز عبور به سرور خود ندارید ، باید مراحل بالا را به صورت دستی تکمیل کنید.

ما به صورت دستی محتوای فایل id_rsa.pub شما را به فایل ~/.ssh/author_keys در دستگاه راه دور خود اضافه می کنیم.

برای نمایش محتوای کلید id_rsa.pub خود ، این را در رایانه محلی خود تایپ کنید:

cat ~/.ssh/id_rsa.pub

محتوای کلید را مشاهده خواهید کرد ، که باید چیزی شبیه به این باشد:

 

Output

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCqql6MzstZYh1TmWWv11q5O3pISj2ZFl9HgH1JLknLLx44+tXfJ7mIrKNxOOwxIxvcBF8PXSYvobFYEZjGIVCEAjrUzLiIxbyCoxVyle7Q+bqgZ8SeeM8wzytsY+dVGcBxF6N4JS+zVk5eMcV385gG3Y6ON3EG112n6d+SMXY0OEBIcO6x+PnUSGHrSgpBgX7Ks1r7xqFa7heJLLt2wWwkARptX7udSq05paBhcpB0pHtA1Rfz3K2B+ZVIpSDfki9UVKzT8JUmwW6NNzSgxUfQHGwnW7kj4jp4AT0VZk3ADw497M2G/12N0PPB5CnhHf7ovgy6nL1ikrygTKRFmNZISvAcywB9GVqNAVE+ZHDSCuURNsAInVzgYo9xgJDW8wUw2o8U77+xiFxgI5QSZX3Iq7YLMgeksaO4rBJEa54k8m5wEiEE1nUhLuJ0X/vh2xPff6SQ1BL/zkOhvJCACK6Vb15mDOeCSq54Cr7kvS46itMosi/uS66+PujOO+xt/2FWYepz6ZlN70bRly57Q06J+ZJoc9FfBCbCyYH7U/ASsmY095ywPsBo1XQ9PqhnN1/YOorJ068foQDNVpm146mUpILVxmq41Cj55YKHEazXGsdBIbXWhcrRf4G2fJLRcGUr9q8/lERo9oxRm5JFX6TCmj6kmiFqv+Ow9gI0x8GvaQ== sammy@host

با استفاده از هر روشی که در دسترس دارید ، وارد میزبان راه دور خود شوید.

پس از دسترسی به حساب خود در سرور راه دور ، باید مطمئن شوید که فهرست ~/.ssh وجود دارد. این دستور در صورت لزوم دایرکتوری را ایجاد می کند یا در صورت وجود هیچ کاری انجام نمی دهد:

mkdir -p ~/.ssh

اکنون ، می توانید فایل author_keys را در این فهرست ایجاد یا اصلاح کنید. می توانید محتویات فایل id_rsa.pub خود را به انتهای فایل author_keys اضافه کنید و در صورت لزوم آن را با استفاده از این دستور ایجاد کنید:

echo public_key_string >> ~/.ssh/authorized_keys

در دستور بالا ، public_key_string را با خروجی دستور cat ~/.ssh/id_rsa.pub که در سیستم محلی خود اجرا کرده اید جایگزین کنید. باید با ssh-rsa AAAA شروع شود ….

در نهایت ، ما اطمینان حاصل می کنیم که دایرکتوری./.ssh و فایل author_keys دارای مجوزهای مناسب هستند:

chmod -R go= ~/.ssh

با این کار همه مجوزهای “گروه” و “دیگر” برای فهرست ~/ .ssh/ حذف می شود.

اگر از حساب اصلی برای تنظیم کلیدها برای یک حساب کاربری استفاده می کنید ، همچنین مهم است که فهرست ~/.ssh متعلق به کاربر باشد و نه روت:

chown -R sammy:sammy ~/.ssh

در این آموزش کاربر ما sammy نامیده می شود اما شما باید نام کاربری مناسب را در دستور بالا جایگزین کنید.

اکنون می توانیم با سرور Linux Rocky خود احراز هویت مبتنی بر کلید را انجام دهیم.

مرحله 3 – ورود به سرور سنگی لینوکس خود با استفاده از کلیدهای SSH

اگر یکی از مراحل بالا را با موفقیت انجام داده اید ، اکنون باید بتوانید بدون گذرواژه حساب راه دور وارد میزبان راه دور شوید.

فرایند اولیه مشابه احراز هویت مبتنی بر رمز عبور است:

ssh username@remote_host

اگر برای اولین بار است که به این میزبان وصل می شوید (اگر از آخرین روش بالا استفاده کرده اید) ، ممکن است چیزی شبیه به این را مشاهده کنید:

 

Output

The authenticity of host '203.0.113.1 (203.0.113.1)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes

این بدان معناست که رایانه محلی شما میزبان از راه دور را تشخیص نمی دهد. بله را تایپ کنید و سپس ENTER را برای ادامه فشار دهید.

اگر هنگام ایجاد جفت کلید خود در مرحله 1 یک رمز عبور ارائه نکرده اید ، بلافاصله وارد سیستم می شوید. اگر یک عبارت عبور ارائه کرده اید ، از شما خواسته می شود که آن را وارد کنید. پس از احراز هویت ، یک جلسه پوسته جدید باید با حساب پیکربندی شده در سرور Rocky Linux برای شما باز شود.

اگر احراز هویت مبتنی بر کلید موفقیت آمیز بود ، به نحوه یادگیری نحوه ایمن سازی بیشتر سیستم خود با غیرفعال کردن احراز هویت مبتنی بر رمز عبور سرور SSH خود ادامه دهید.

مرحله 4 – غیرفعال کردن احراز هویت رمز عبور در سرور خود

اگر می توانید بدون استفاده از SSH به حساب خود وارد شوید ، احراز هویت مبتنی بر کلید SSH را با موفقیت پیکربندی کرده اید. با این حال ، مکانیزم احراز هویت مبتنی بر رمز عبور شما هنوز فعال است ، به این معنی که سرور شما هنوز در معرض حملات بی رحمانه است.

قبل از اتمام مراحل این بخش ، مطمئن شوید که یا احراز هویت مبتنی بر کلید SSH برای حساب ریشه در این سرور پیکربندی شده است ، یا ترجیحاً احراز هویت مبتنی بر کلید SSH برای یک حساب غیر ریشه در این پیکربندی شده است. سرور دارای امتیازات sudo این مرحله ورودهای مبتنی بر گذرواژه را قفل می کند ، بنابراین اطمینان از این که هنوز می توانید دسترسی اداری داشته باشید بسیار مهم است.

هنگامی که تأیید کردید که حساب راه دور شما دارای امتیازات مدیریتی است ، با کلیدهای SSH وارد سرور راه دور خود شوید ، یا به صورت root یا با حسابی با امتیازات sudo. سپس ، فایل پیکربندی SSH daemon را باز کنید:

sudo vi /etc/ssh/sshd_config

در داخل فایل ، دستورالعملی به نام PasswordAuthentication را جستجو کنید. این ممکن است با یک # هش نظر داده شود. i را فشار دهید تا vi در حالت درج قرار گیرد ، و سپس خط را کامنت نکنید و مقدار را روی no قرار دهید. با این کار امکان ورود به سیستم از طریق SSH با استفاده از گذرواژه های حساب غیرفعال می شود:


PasswordAuthentication no

پس از اتمام اعمال تغییرات ، ESC و سپس: wq را فشار دهید تا تغییرات را در فایل بنویسید و خارج شوید. برای پیاده سازی واقعی این تغییرات ، باید سرویس sshd را راه اندازی مجدد کنیم:

sudo systemctl restart sshd

برای احتیاط ، یک پنجره ترمینال جدید باز کنید و قبل از بستن جلسه فعلی خود ، صحت عملکرد سرویس SSH را بررسی کنید:

ssh username@remote_host

هنگامی که تأیید کردید که سرویس SSH شما هنوز به درستی کار می کند ، می توانید با خیال راحت تمام جلسات سرور فعلی را ببندید.

الگوی SSH در سرور Linux Rocky شما اکنون فقط به کلیدهای SSH پاسخ می دهد. احراز هویت مبتنی بر رمز عبور با موفقیت غیرفعال شد.

خرید سرور لینوکسسرورسرور Rocky Linux 8سرور سنگی لینوکسسرور لینوکسفروش سرورکلیدهای SSHلینوکس

  • behnam gol mohamadi
  • ۰
  • ۰

چگونه برای جهان میزبانهای وب مدیریت شده  cloud-first در حال تکامل هستند

ورود به مدیریت

تعداد کمی از صنایع سریعتر از صنعت میزبانی وب رشد کرده اند زیرا مشاغل کوچک نیاز به حضور در وب را تشخیص می دهند. ظهور پلتفرم هایی مانند وردپرس ، Shopify و Magento باعث شده است که تیم های کوچک توسعه دهندگان وب بتوانند برای کسب و کار خود یا خدمات رسانی به نیازهای مشتریان خود ، صفحات وب پیشرفته و مدرن ایجاد کنند.

امروزه هزاران آژانس ، مترجمان آزاد و مشاغل کوچک به این ابزارها ، که بسیاری از آنها پلتفرم های منبع باز هستند ، تکیه می کنند تا دقیقاً آنچه را که لازم است بدون اختراع مجدد چرخ ایجاد کنند. از جمله چالش هایی که این تیم های کوچک توسعه دهندگان با آن روبرو هستند میزبانی است . وقتی نمایندگی ها. فریلنسرها و مشاغل کوچک می خواهند از مدیریت زیرساخت ها اجتناب کنند ، میزبان وب مدیریت شده می تواند با انتزاع بسیاری از گزینه های ارائه شده توسط سیستم عامل های ابر عمومی ، خدمات ارائه دهد. این به توسعه دهندگان این امکان را می دهد که لزوماً نیازی به تمایز بین سطوح CPU نداشته باشند یا نیازی به درک عمیق قیمت ها برای ترافیک مورد انتظار خود نداشته باشند.

چرا Cloud-First؟

مانند سایر نرم افزارها ، کسب و کارهای میزبانی به منظور استفاده از مقیاس ، پشتیبانی ، امنیت و مزایای متعدد به ابر منتقل شده اند. با ایجاد یک پلتفرم ابری ثابت ، میزبانهای ابر مدیریت شده همان مزایای اساسی را دارند که از ارائه دهندگان ابر عمومی استفاده می کنند و سپس می توانند این مزایا را به مشتری نهایی منتقل کنند. با استفاده از ابرهای عمومی ، ارائه دهندگان ابر مدیریت شده و مشتریان آنها می توانند بر بهترین کاری که انجام می دهند تمرکز کنند. برای مشتری نهایی ، این تمرکز بر ایجاد وردپرس و همتایان آن است. برای میزبان های ابری مدیریت شده ، این تمرکز بر افزودن ارزش عظیمی بر زیرساخت محاسبات ابری است که به طور خاص برای موارد استفاده از میزبانی اصلی آنها طراحی شده است.

یک امتیاز اضافی: مقیاس پذیری و صرفه جویی در هزینه از طرف ارائه دهندگان ابر عمومی ، مزایایی است که میزبان می تواند به مشتری نهایی منتقل کند ، و در نتیجه پیشنهاد بسیار ارزشمندی را ارائه می دهد که باعث می شود توسعه اولین سرویس میزبانی ابری بسیار جذاب تر شود

نکاتی در مورد ایجاد ارائه دهنده میزبانی مدیریت شده

کسانی که به دنبال ایجاد یک تجارت میزبانی مدیریت شده هستند باید چندین عامل کلیدی را در نظر بگیرند. مهمتر از همه ، آنها باید از برآوردن نیازهای مشتریان خود اطمینان حاصل کنند. بسیاری از کاربران نهایی ارائه دهندگان میزبانی مدیریت شده از WordPress استفاده می کنند ، به عنوان غالب ترین سیستم مدیریت محتوا (CMS) که امروزه در دسترس است. یک کاربر نهایی معمولی ممکن است یک آژانس وب کوچک با تیمی از چند توسعه دهنده باشد که همه آنها WordPress را از داخل و خارج می شناسند. نکته کلیدی برای آن آژانس عبارت است از (1) ساختن روی پلتفرمی که کار می کند ، (2) ایجاد بودجه و (3) ساختن به موقع برای مشتریان خود. ارائه دهندگان میزبانی مدیریت شده می توانند با احداث ابرهای قابل اعتماد عمومی مانند DigitalOcean این نیازها را برآورده کنند

ساختن بر پلتفرمی که کار می کند

آژانس ها ، برای گرفتن یک مشتری معمولی مدیریت شده میزبانcloud ، به یک میزبانcloud مدیریت شده نیاز دارند که از هر نظر ممکن است رقابتی باشد: عملکرد ، قابلیت مقیاس بندی ، زمان به روز و پشتیبانی. مشتریان میزبان ابر مدیریت شده ملزم به رعایت الزامات عملکرد و انتظارات از حجم ترافیک هستند. با ایجاد cloud به روشی که در مقیاس قابل اطمینان کار کند ، میزبان می تواند با اطمینان توافقنامه هایی در سطح سرویس ارائه دهد که نشان دهنده این قابلیت حیاتی است.

بر اساس بودجه

دوم ، و بسیار مهم برای کاربران نهایی ، ایجاد بودجه است. برای خود میزبان های ابری مدیریت شده ، درک هزینه های میزبانی در برخی از ابرهای مقیاس بزرگ می تواند پیچیده و مدل قیمت گذاری غیرقابل بررسی باشد. به طور مشابه ، برای مشتریان ، قیمت گذاری یک الزام کلیدی است و در صورت غیرقابل بررسی ، می تواند یک مشکل عمده ایجاد کند.

آژانس معمولی به هزینه استفاده از CPU و پهنای باند یا سطح عملکردی که برای ترافیک مورد انتظار خود نیاز دارند فکر نمی کند. آنها می خواهند این جزئیات با شرایط قیمت گذاری که می توانند بفهمند و پیش بینی کنند ، در پس زمینه محو شود تا بتوانند از پس بودجه برآیند. برای اینکه میزبان ابری مدیریت شده آن قیمت واضح و شفاف را ارائه دهد ، هزینه های خود باید قابل پیش بینی باشد ، به همین دلیل است که آنها باید بر روی سیستم عامل های ابری با مدل های قیمت گذاری روشن ساخته شوند.

ساخت به موقع

پشتیبانی در خدمات مشتری بسیار مهم است زیرا بسیاری ، مانند نمایندگی معمولی ما ، تا حدی میزبان ابری مدیریت شده را انتخاب می کنند ، زیرا زبان تخصصی نرم افزار میزبانی شده را درک می کنند. هنگامی که آنها با مشکل استقرار یا اشکالی که مربوط به یکی از این فناوری ها است مواجه می شوند ، میزبان ابر مدیریت شده دارای دانش و تخصص لازم برای کمک به مشتری برای حل این مشکل است. مشتریان از زمان انجام کارها انتظار دارند و داشتن یک تیم پشتیبانی آماده برای کمک در ایجاد اعتماد بسیار مهم است.

برای ساختن به موقع و اطمینان از اینکه میزبان ابری مدیریت شده از مشتریان با کیفیت پشتیبانی می کند ، آنها باید بدانند که زیرساخت های شخصی آنها مورد مراقبت قرار می گیرد. ارائه دهنده مدیریت شده باید بداند که از ارائه دهنده ابری خود مراقبت می کند ، از استقرار اولیه یا مهاجرت وب سایت های میزبانی شده آنها ، تا پشتیبانی مداوم در صورت بروز هرگونه چالش در مقیاس و عملکرد.

DigitalOcean برای مدیریت Cloud Hosting

این که آیا شما در حال راه اندازی یک تجارت میزبانی ابری جدید هستید یا قصد دارید کسب و کار فعلی خود را به سطح بالاتری برسانید ، تیم شما احتمالاً با پیچیدگی محصول ، قیمت غیرقابل پیش بینی و پشتیبانی غیرقابل دسترسی از سوی برخی از ارائه دهندگان cloud مواجه شده است. DigitalOcean دارای سابقه اثبات شده در زمینه ایجاد راه حل هایی است که به میزبان های cloud مدیریت شده کمک می کند تا کسب و کار خود را توسعه دهند.

WPMU DEV یکی از این مشتریان است. WPMU DEV یک میزبان ابری مدیریت شده است که به هزاران کسب و کار کوچک خدمات رسانی می کند. تیم کوچک توسعه دهندگان آنها می خواستند به راه حل کم هزینه مهاجرت کنند بدون اینکه پشتیبانی یا عملکرد مشتریان خود را از دست بدهند. با استفاده از Droplets ، DigitalOcean یک مدل قیمت شفاف و شفاف را در اختیار تیم قرار داد که با نیازهای آنها مطابقت داشت

DigitalOcean تنها سرویسی است که انعطاف پذیری و مقیاس یک پلتفرم ابری با کارایی بالا را با هزینه و نیازهای پشتیبانی یک مشاغل کوچک رو به رشد متعادل می کند.

Cloud HostingCMSسرورسرورمجازیمدیریت محتوامیزبانی وبهاستهاستینگ خرید سرور فروش سرور vps DigitalOcean Droplets پلتفرم ابری

  • behnam gol mohamadi
  • ۰
  • ۰

افزایش امنیت ، بینش و ادغام DBaaS در پلت فرم برنامه DigitalOcean

ورود به سایت

مشاغل به طور فزاینده ای به دنبال راهی هستند تا برنامه های خود را سریعتر به بازار عرضه کنند. پلتفرم برنامه DigitalOcean با ارائه یک راه حل کاملاً مدیریت شده که به شما کمک می کند برنامه های خود را بسازید ، مستقر و مقیاس بندی کنید ، به آن نیازها آدرس می دهد. شما می توانید برنامه ها را به سادگی با اشاره به repo GitHub یا GitLab خود مستقر کنید ، و App Platform وظایف سنگین مدیریت زیرساخت ، زمان اجرای برنامه و سایر وابستگی ها را انجام می دهد.

برنامه های خود را به صورت امن به پایگاه های داده مدیریت شده به عنوان منابع قابل اعتماد متصل کنید

چه توسعه دهنده باشید ، چه کارآفرین ، چه یک کسب و کار کوچک ، امنیت برنامه ها و داده های شما برای همه اولویت اصلی است. با ایجاد ارتباط ایمن بین برنامه ها و پایگاه های داده خود ، می توانید احتمال نقض امنیت ، تلاش برای گذرواژه بی رحمانه و حملات منع سرویس از هر سرور که صراحتا مجاز به اتصال به پایگاه داده شما نیست را تا حد زیادی کاهش دهید.

با افتخار اعلام می کنیم که اکنون می توانید برنامه های خود را که به طور امن بر روی App Platform ساخته شده اند به پایگاه های مدیریتی DigitalOcean به عنوان منابع قابل اعتماد متصل کنید. افزودن برنامه به عنوان یک منبع قابل اعتماد ، یک اتصال امن به پایگاه داده ایجاد می کند که ترافیک را فقط از برنامه می پذیرد و دیگر اتصالات خصوصی و عمومی را رد می کند و پایگاه داده شما را ایمن تر می کند. به طور مشابه ، اگر پایگاه داده مدیریت شده موجود شما منابع معتبری را فعال کرده باشد ، برنامه به طور خودکار به عنوان یک منبع قابل اعتماد اضافه می شود. این ویژگی برای پایگاه های مدیریتی Redis ، MySQL و PostgreSQL موجود است و به زودی برای Managed MongoDB اضافه می شود

با هشدارها و نظارت ، دید بهتری در برنامه های خود به دست آورید

هنگام ایجاد و نگهداری برنامه ها ، اعلانات مربوط به وضعیت برنامه شما می تواند به شما در کاهش سریع مشکلات کمک کند. دید واضح از وضعیت و سلامت برنامه های شما نیز به شما کمک می کند تا بهره وری بیشتری داشته باشید ، زیرا دیگر نیازی به استخراج گزارش ها ندارید تا بفهمید چرا برنامه شما آنطور که انتظار می رود کار نمی کند. خوشحال می شویم اعلام کنیم که قابلیت هشدار و نظارت را به App Platform اضافه کرده ایم تا بتوانید از وضعیت برنامه های خود مطلع شوید و مشکلات را سریع حل کنید. سیاست های هشدار پیش فرض DigitalOcean به شما در مورد نحوه استقرار و پیکربندی دامنه برنامه های شما اطلاع می دهد ، همانطور که در تصویر زیر نشان داده شده است.

خط مشی های پیش فرض هشدار

می توانید اعلان ها را از طریق ایمیل یا Slack دریافت کنید. همچنین می توانید خط مشی های هشدار جدیدی اضافه کنید که بر اساس شرایطی که تعیین کرده اید ، فعال می شوند.

ادغام بستر برنامه با MongoDB مدیریت شده

در ماه ژوئن ، ما DigitalOcean Managed MongoDB را راه اندازی کردیم – یک پایگاه داده کاملاً مدیریت شده به عنوان سرویس برنامه های مدرن. پلتفرم برنامه به صورت یکپارچه با Managed MongoDB ادغام می شود و به شما این امکان را می دهد که MongoDB مدیریت شده را به عنوان پشتیبان برنامه خود انتخاب کنید. می توانید هنگام ایجاد برنامه خود با استفاده از App Platform ، یک خوشه MongoDB مدیریت شده را بچرخانید یا MongoDB را به برنامه ای که قبلاً ایجاد کرده اید متصل کنید. در اینجا یک ویدیو عالی وجود دارد که نشان می دهد چگونه می توانید از Managed MongoDB با برنامه های App Platforms استفاده کنید.

انعطاف پذیری بیشتری برای استقرار برنامه های خود با پشتیبانی از monorepos

monorepo یک مخزن واحد است که کد بسیاری از پروژه های مختلف را ذخیره می کند. توسعه دهندگان اغلب از monorepos برای استفاده مجدد از کد ، مدیریت وابستگی ها ، بهینه سازی ساختارها و همکاری موثر در بین تیم ها استفاده می کنند. ما مفتخریم اعلام کنیم که Platform App در حال حاضر از استقرار برنامه های مختلف پشتیبانی می کند که همه در یک مخزن واحد git (monorepo) قرار دارند. هر یک از این برنامه ها ممکن است در پوشه جداگانه ای در repo قرار داشته باشند. این به کاهش زمان لازم برای توسعه و استقرار برنامه ها کمک می کند و توسعه دهندگان را کارآمدتر و پربارتر می کند. این ویدئو را ببینید تا این قابلیت را در عمل ببینید.

ادغام بستر برنامه با Stackbit

Stackbit یک پلتفرم است که به شما امکان می دهد در سایت های Jamstack همکاری کنید ، و تیم خود را قادر می سازد تا به جای برخورد با Markdown ، git یا نوشتن کد ، آنها را بصری ویرایش کند. شما می توانید از مزایای Jamstack ، از جمله عملکرد بهتر ، امنیت بیشتر ، هزینه کمتر و مقیاس پذیری بیشتر ، همراه با راحتی ویرایش بصری داخلی استفاده کنید. اکنون می توانید به راحتی سایت های خود را که بر روی Stackbit to App Platform ساخته شده منتشر کرده و از پلتفرم کاملاً مدیریت شده استفاده کنید.

:DBaaSMongoDBStackbitپلتفرمپلتفرمStackbitسرورسرورمجازی ،vps ، خرید سرور ،فروش سرور 

  • behnam gol mohamadi