Skip to content

3. یک برنامهٔ اول [nuxt.js]

3.1. ایجاد برنامه

برای کار توسعه [nuxt.js]، به استفاده از VS Code ادامه خواهیم داد. ما یک پوشه خالی [dvp] ایجاد کرده‌ایم که در آن مثال‌هایمان را قرار خواهیم داد. سپس این پوشه را باز می‌کنیم:

Image

ما فضای کاری را با نام [intro-nuxtjs] [3-5] ذخیره می‌کنیم:

Image

یک ترمینال به نام [6-7] را باز می‌کنیم:

Image

تا کنون از مدیر بسته‌های جاوااسکریپت [npm] استفاده کرده‌ایم. برای تنوع، اکنون از مدیر [yarn] استفاده خواهیم کرد. این مدیر، مانند [npm]، به همراه نسخه‌های اخیر [node.js] نصب می‌شود. برای ایجاد یک برنامهٔ اولیهٔ [nuxt]، از دستور [yarn create nuxt-app <dossier>] [1] استفاده می‌کنیم. دستورالعمل تعدادی جزئیات دربارهٔ پروژه‌ای که باید تولید شود را درخواست می‌کند و پس از ارائهٔ آن‌ها، آن را تولید خواهد کرد:

Image

در [2]، یک درخت کامل فایل ایجاد شده است. فایل [package.json] فهرستی از کتابخانه‌های جاوااسکریپت دانلود شده به پوشه [node-modules] [4] را فهرست می‌کند:


{
  "name": "nuxt-intro",
  "version": "1.0.0",
  "description": "nuxt-intro",
  "author": "serge-tahe",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
  },
  "dependencies": {
    "nuxt": "^2.0.0",
    "bootstrap-vue": "^2.0.0",
    "bootstrap": "^4.1.3",
    "@nuxtjs/axios": "^5.3.6"
  },
  "devDependencies": {
    "@nuxtjs/eslint-config": "^1.0.1",
    "@nuxtjs/eslint-module": "^1.0.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^6.1.0",
    "eslint-plugin-nuxt": ">=0.4.2",
    "eslint-config-prettier": "^4.1.0",
    "eslint-plugin-prettier": "^3.0.1",
    "prettier": "^1.16.4"
  }
}

این فایل، پاسخ‌های مربوط به دستور [create nuxt-app] را که برای تعریف پروژه ایجادشده (نوامبر ۲۰۱۹) استفاده شده است، منعکس می‌کند. ممکن است خواننده فایل [package.json] متفاوتی داشته باشد:

  • ممکن است پاسخ‌های متفاوتی به سؤالات داده باشند؛
  • دستور [create nuxt-app] از زمان نگارش این سند تغییر کرده است: وابستگی‌ها و نسخه‌ها تغییر کرده‌اند؛

خط ۸ اسکریپت، دستوری است که برنامه را اجرا می‌کند:

Image

  • در [4]، می‌توانیم ببینیم که برنامه در URL و [localhost:3000] در دسترس است؛
  • در [5-6]، می‌توانیم ببینیم که برنامه یک سرور ([6]) و یک کلاینت (برای آن سرور) ([5]) ایجاد می‌کند؛

بیایید در یک مرورگر URL [http://localhost:3000/] را درخواست کنیم:

Image

3.2. توضیح ساختار دایرکتوری یک برنامه [nuxt]

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

Image

هدف از پوشه‌ها به شرح زیر است:

assets
منابع کامپایل‌نشدهٔ برنامه (تصاویر و غیره)؛
ثابت
فایل‌های موجود در این پوشه در ریشهٔ برنامه در دسترس خواهند بود. این پوشه برای فایل‌هایی است که باید در ریشهٔ برنامه قرار گیرند، مانند فایل [robots.txt] که برای موتورهای جستجو در نظر گرفته شده است؛
کامپوننت‌ها
کامپوننت‌های [vue] برنامه که در فایل‌های [layouts] و [pages] استفاده می‌شوند؛
قالب‌بندی‌ها
کامپوننت‌های [vue] برنامه که برای قالب‌بندی فایل‌های [pages] استفاده می‌شوند؛
صفحات
اجزای [vue] که توسط مسیرهای مختلف در برنامه نمایش داده می‌شوند. این‌ها را می‌توان نماهای برنامه نامید. صفحات در [nuxt] نقش ویژه‌ای دارند: مسیرها به‌صورت پویا از ساختار دایرکتوری موجود در پوشه [pages] ایجاد می‌شوند؛
میان‌افزار
اسکریپت‌هایی که هر زمان یک مسیر تغییر می‌کند، اجرا می‌شوند. آنها امکان کنترل این مسیرها را فراهم می‌کنند؛
پلاگین‌ها
نام نسبتاً گمراه‌کننده‌ای دارد. این پوشه ممکن است حاوی پلاگین‌ها و همچنین اسکریپت‌های استاندارد باشد. اسکریپت‌های موجود در این پوشه هنگام راه‌اندازی برنامه اجرا می‌شوند؛
انبار
اگر حاوی اسکریپتی با نام [index.js] باشد، در این صورت این یک نمونه از store برای [Vuex] را تعریف می‌کند؛

اگر یک پوشه خالی باشد، می‌توان آن را از ساختار دایرکتوری حذف کرد. در مثال بالا، پوشه‌های [assets, static, middleware, plugins, store] و [2] را می‌توان حذف کرد.

3.3. فایل پیکربندی [nuxt.config]

اجرای برنامه توسط فایل زیر کنترل می‌شود: [nuxt.config.js]:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: process.env.npm_package_description || ''
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // مستندات: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  }
}
  • خط ۲: نوع برنامه تولید شده:
    • [universal]: برنامهٔ کلاینت/سرور. هنگامی که برنامه برای اولین بار بارگذاری می‌شود و هر بار که صفحه در مرورگر تازه می‌شود، سرور برای تحویل صفحه فراخوانی می‌شود؛
    • [sap]: برنامه‌ای از نوع [Single Page Application]: سرور در ابتدا کل برنامه را تحویل می‌دهد. پس از آن، کلاینت به طور مستقل عمل می‌کند، حتی زمانی که یک صفحه در مرورگر تازه می‌شود؛
  • خطوط ۶–۱۸: هدر <head> HTML را برای صفحات مختلف برنامه تعریف می‌کنند:
    • خط ۷: تگ <title> برای عنوان صفحه؛
    • خطوط ۸–۱۶: تگ‌های <meta
    • خط ۱۷: تگ‌های <link>

در برنامه تولید شده، تگ <head> به شرح زیر است (کد منبع صفحه نمایش داده شده در مرورگر):


<title>nuxt-intro</title>
<meta data-n-head="ssr" charset="utf-8">
<meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
<meta data-n-head="ssr" data-hid="description" name="description" content="nuxt-intro">
<link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="preload" href="/_nuxt/runtime.js" as="script">
<link rel="preload" href="/_nuxt/commons.app.js" as="script">
<link rel="preload" href="/_nuxt/vendors.app.js" as="script">
<link rel="preload" href="/_nuxt/app.js" as="script">

اکنون، بیایید فایل [nuxt.config] را به شرح زیر اصلاح کنیم:


head: {
    title: 'Introduction à [nuxt.js]',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: 'ssr routing loading asyncdata middleware plugins store'
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
},

وقتی برنامه را دوباره اجرا می‌کنیم، تگ <head> به شکل زیر درمی‌آید (کد منبع صفحه‌ای که در مرورگر نمایش داده می‌شود):


  <head >
    <title>Introduction à [nuxt.js]</title>
    <meta data-n-head="ssr" charset="utf-8">
    <meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1">
    <meta data-n-head="ssr" data-hid="description" name="description" content="ssr routing loading asyncdata middleware plugins store">
    <link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico">
    <link rel="preload" href="/_nuxt/runtime.js" as="script">
    <link rel="preload" href="/_nuxt/commons.app.js" as="script">
    <link rel="preload" href="/_nuxt/vendors.app.js" as="script">
<link rel="preload" href="/_nuxt/app.js" as="script">

بیایید به فایل [nuxt.config] بازگردیم:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    ...
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    // مستندات: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://bootstrap-vue.js.org
    'bootstrap-vue/nuxt',
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  }
}
  • خط ۱۲: بین هر مسیر در [nuxt] کلاینت، یک نوار بارگذاری ظاهر می‌شود اگر تغییر مسیر کمی زمان ببرد. خاصیت [loading] به شما امکان می‌دهد این نوار بارگذاری را پیکربندی کنید؛ در اینجا، رنگ نوار؛
  • خط ۱۶: فایل‌های سراسری [css]. این فایل‌ها به‌طور خودکار در تمام صفحات برنامه گنجانده می‌شوند؛
  • خطوط ۲۴–۲۷: ماژول‌های جاوااسکریپت مورد نیاز برای ساخت برنامه؛
  • خطوط ۳۱–۳۶: ماژول‌های جاوااسکریپتی که توسط برنامه استفاده می‌شوند؛
  • خط ۴۱: پیکربندی کتابخانه [axios] هنگامی که کاربر آن را برای مکالمات HTTP با سرورهای شخص ثالث انتخاب کرده است؛
  • خطوط ۴۵–۵۰: تنظیمات ساخت پروژه؛

می‌توان کلیدهای بیشتری به فایل پیکربندی اضافه کرد. به‌ویژه، می‌توانید پورت سرویس (به‌طور پیش‌فرض 3000) و ریشه پروژه (به‌طور پیش‌فرض پوشه ریشه پروژه) را پیکربندی کنید. این کاری است که اکنون با افزودن کلیدهای زیر انجام خواهیم داد:


// پوشهٔ کد منبع
  srcDir: '.',
  router: {
    // URL ریشه صفحات برنامه
    base: '/nuxt-intro/'
  },
  // سرور
  server: {
    // پورت سرویس – پیش‌فرض 3000
    port: 81,
    // آدرس‌های شبکه شنودشده – پیش‌فرض: localhost=127.0.0.1
    host: '0.0.0.0'
  }
  • خط ۲: محل یافتن کد منبع پروژه. این فایل در همین پوشهٔ جاری قرار دارد، یعنی در همان سطح فایل [nuxt.config.js]. این مقدار پیش‌فرض است؛
  • خطوط ۸–۱۳: پیکربندی سرور (به یاد داشته باشید که یک برنامه [nuxt] از نوع [universal] هم روی سرور و هم روی مرورگر کلاینتی که به آن سرور دسترسی دارد نصب شده است);
  • خط ۱۰: صفحات برنامه روی پورت ۸۱ سرور ارائه می‌شوند؛
  • خط ۱۲: به طور پیش‌فرض، [localhost] (آدرس شبکه 127.0.0.1). یک ماشین ممکن است چندین آدرس شبکه داشته باشد اگر به چندین شبکه تعلق داشته باشد. آدرس 0.0.0.0 نشان می‌دهد که وب‌سرور در تمام آدرس‌های شبکه ماشین در حال گوش دادن است؛
  • خطوط ۳–۶: راه‌انداز را برای برنامه [nuxt] پیکربندی کنید؛
  • خط ۵: صفحات برنامه در URL و [http://localhost:81/nuxt-intro/] در دسترس خواهند بود؛

بیایید این خطوط را به فایل [nuxt.config.js] اضافه کنیم و سپس پروژه را اجرا کنیم (اسکریپت npm dev). نتیجه به شرح زیر است:

Image

  • در [1]، آدرس ماشین در یک شبکه عمومی؛
  • در [2]، پورت سرویس؛
  • [3]، ریشهٔ برنامه؛

3.4. پوشه [layouts]

Image

پوشه [layouts] برای کامپوننت‌های چیدمان در نظر گرفته شده است. به طور پیش‌فرض، از کامپوننت با نام [default.vue] استفاده می‌شود. در این پروژه، به شرح زیر است:


<template>
  <div>
    <nuxt />
  </div>
</template>

<style>
html {
  font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI',
    Roboto, 'Helvetica Neue', Arial, sans-serif;
  font-size: 16px;
  word-spacing: 1px;
  -ms-text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: border-box;
  margin: 0;
}

.button--green {
  display: inline-block;
  border-radius: 4px;
  border: 1px solid #3b8070;
  color: #3b8070;
  text-decoration: none;
  padding: 10px 30px;
}

.button--green:hover {
  color: #fff;
  background-color: #3b8070;
}

.button--grey {
  display: inline-block;
  border-radius: 4px;
  border: 1px solid #35495e;
  color: #35495e;
  text-decoration: none;
  padding: 10px 30px;
  margin-left: 15px;
}

.button--grey:hover {
  color: #fff;
  background-color: #35495e;
}
</style>

توضیحات

  • خطوط ۱–۵: کامپوننت [template
  • خط ۳: تگ <nuxt /> صفحهٔ جاری را در مسیریابی مشخص می‌کند؛
  • خطوط ۷–۵۵: استایلی که توسط کامپوننت چیدمان جاسازی شده است. از آنجایی که این شامل صفحه مسیریابی فعلی است، این سبک برای تمام صفحات مسیریابی‌شده در برنامه اعمال می‌شود؛

می‌توانیم ببینیم که هدف اصلی صفحه [default.vue] در اینجا اعمال یک استایل بر صفحات مسیریابی‌شده است.

3.5. پوشه [pages]

Image

پوشه [pages] حاوی ویوهای مسیریابی‌شده است—یعنی ویوهایی که کاربر می‌بیند. صفحه [index.vue] صفحه اصلی برنامه است. برای [nuxt.js]، هیچ فایل مسیریابی وجود ندارد. مسیرها بر اساس ساختار پوشه [pages] تعیین می‌شوند. در اینجا، وجود فایلی به نام [index.vue] به طور خودکار یک مسیر به نام [index] ایجاد می‌کند، و مسیر [/index] به [/] کاهش می‌یابد، زیرا این صفحه اصلی است. بدین ترتیب، مسیر زیر ایجاد می‌شود:

        { name : ‘index’, path : ‘/’}

فایل [index.vue] به شرح زیر است:


<template>
  <div class="container">
    <div>
      <logo />
      <h1 class="title">
        nuxt-intro
      </h1>
      <h2 class="subtitle">
        nuxt-intro
      </h2>
      <div class="links">
        <a href="https://nuxtjs.org/" target="_blank" class="button--green">
          Documentation
        </a>
        <a
          href="https://github.com/nuxt/nuxt.js"
          target="_blank"
          class="button--grey"
        >
          GitHub
        </a>
      </div>
    </div>
  </div>
</template>

<script>
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  }
}
</script>

<style>
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 100px;
  color: #35495e;
  letter-spacing: 1px;
}

.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}

.links {
  padding-top: 15px;
}
</style>

خطوط ۱–۲۵ از فایل [template] نمای زیر را نمایش می‌دهند:

Image

تصویر [1] توسط خط ۴ از [template] تولید می‌شود. بنابراین می‌توانیم ببینیم که صفحه از کامپوننتی به نام [logo] استفاده می‌کند. این کامپوننت در خطوط ۲۷ تا ۳۵ اسکریپت صفحه تعریف شده است. در خط ۲۸، نشانه [~] به ریشه پروژه اشاره دارد.

Image

کامپوننت [Logo.vue] به شرح زیر است:


<template>
  <div class="VueToNuxtLogo">
    <div class="Triangle Triangle--two" />
    <div class="Triangle Triangle--one" />
    <div class="Triangle Triangle--three" />
    <div class="Triangle Triangle--four" />
  </div>
</template>

<style>
.VueToNuxtLogo {
  display: inline-block;
  animation: turn 2s linear forwards 1s;
  transform: rotateX(180deg);
  position: relative;
  overflow: hidden;
  height: 180px;
  width: 245px;
}

.Triangle {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
}

.Triangle--one {
  border-left: 105px solid transparent;
  border-right: 105px solid transparent;
  border-bottom: 180px solid #41b883;
}

.Triangle--two {
  top: 30px;
  left: 35px;
  animation: goright 0.5s linear forwards 3.5s;
  border-left: 87.5px solid transparent;
  border-right: 87.5px solid transparent;
  border-bottom: 150px solid #3b8070;
}

.Triangle--three {
  top: 60px;
  left: 35px;
  animation: goright 0.5s linear forwards 3.5s;
  border-left: 70px solid transparent;
  border-right: 70px solid transparent;
  border-bottom: 120px solid #35495e;
}

.Triangle--four {
  top: 120px;
  left: 70px;
  animation: godown 0.5s linear forwards 3s;
  border-left: 35px solid transparent;
  border-right: 35px solid transparent;
  border-bottom: 60px solid #fff;
}

@keyframes turn {
  100% {
    transform: rotateX(0deg);
  }
}

@keyframes godown {
  100% {
    top: 180px;
  }
}

@keyframes goright {
  100% {
    left: 70px;
  }
}
</style>

این کامپوننت اساساً شامل استایل‌ها و انیمیشن‌ها برای ایجاد یک تصویر متحرک است.

3.7. مشاهده DevTools

[Vue DevTools] افزونهٔ مرورگری است که به شما امکان می‌دهد اشیاء [nuxt.js] و [vue.js] را در مرورگر بررسی کنید. ما قبلاً از آن در فصل مربوط به [vue.js] استفاده کرده‌ایم. بیایید بررسی کنیم که این ابزار هنگام نمایش صفحهٔ اصلی برنامهٔ ما چه چیزی را پیدا می‌کند:

Image

  • در [1]، کامپوننت [PagesIndex] به صفحه [pages/index.vue] اشاره می‌کند؛
  • می‌توانیم در [2] ببینیم که این کامپوننت دارای یک خاصیت [$route] است، که همان رووتی است که به صفحه [index] منتهی شده است؛

به‌عنوان یک تمرین ساده، بیایید این مسیر را در کنسول نمایش دهیم.

3.8. ویرایش صفحهٔ اصلی

ما قصد داریم فایل [index.vue] را ویرایش کنیم. در نصب پروژه خود، دو وابستگی را نصب کرده‌ایم:

  • [eslint]: که سینتکس فایل‌های جاوااسکریپت و کامپوننت‌های Vue را اعتبارسنجی می‌کند. اگر افزونه [ESLint] برای VSCode نصب شده باشد، این سینتکس هنگام تایپ بررسی می‌شود و خطاها بلافاصله گزارش می‌شوند؛
  • [prettier]: که کد جاوااسکریپت را به یک قالب استاندارد قالب‌بندی می‌کند؛

این وابستگی‌ها در فایل [package.json] فهرست شده‌اند:


"devDependencies": {
    "@nuxtjs/eslint-config": "^1.0.1",
    "@nuxtjs/eslint-module": "^1.0.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^6.1.0",
    "eslint-config-prettier": "^4.1.0",
    "eslint-plugin-nuxt": ">=0.4.2",
    "eslint-plugin-prettier": "^3.0.1",
    "prettier": "^1.16.4"
}

من متوجه شدم (نوامبر ۲۰۱۹) که با نصب انجام شده با استفاده از دستور [yarn create nuxt-app]، ابزارهای [eslint, prettier] هنگام تایپ متن کار نمی‌کنند. خطاها فقط در زمان کامپایل گزارش می‌شوند. پس از کمی تحقیق، یک پیکربندی که کار می‌کند پیدا کردم:

Image

یک پوشه به نام [.vscode] را در ریشه پروژه نصب کنید که حاوی فایل زیر باشد: [settings.json]:


{
  "eslint.validate": [
    {
      "language": "vue",
      "autoFix": true
    },
    {
      "language": "javascript",
      "autoFix": true
    }
  ],
  "eslint.autoFixOnSave": true,
  "editor.formatOnSave": false
}
  • خطوط ۲–۱۱: مشخص می‌کند که وقتی [eslint] فایل‌های .vue و .js را اعتبارسنجی می‌کند، باید هر خطایی را که می‌تواند اصلاح کند؛
  • خط ۱۲: هنگامی که یک فایل ذخیره می‌شود، [eslint] باید هر خطایی را که قادر به اصلاح آن است، تصحیح کند؛
  • خط ۱۳: قالب‌بندی پیش‌فرض انجام‌شده توسط VSCode هنگام ذخیره را غیرفعال می‌کند. [prettier] به‌جای آن این کار را انجام خواهد داد؛

با این پیکربندی:

  • خطاهای نحوی یا قالب‌بندی به محض وارد کردن متن علامت‌گذاری می‌شوند؛
  • خطاهای قالب‌بندی هنگام ذخیرهٔ فایل به‌طور خودکار اصلاح می‌شوند؛

کتابخانه [prettier] توسط فایل [.prettierrc] پیکربندی می‌شود:

Image

به‌طور پیش‌فرض، این فایل است:


{
  "semi": false,
  "arrowParens": "always",
  "singleQuote": true
}
  • خط ۱: هیچ «؛» در انتهای دستورات وجود ندارد؛
  • خط ۲: اگر تابع 'arrow' یک پارامتر داشته باشد، در پرانتز قرار می‌گیرد؛
  • خط ۳: رشته‌ها در گیومهٔ تکی قرار می‌گیرند (نه گیومهٔ دوبل)؛

ما دو قاعده زیر را اضافه می‌کنیم:


{
  "semi": false,
  "arrowParens": "always",
  "singleQuote": true,
  "printWidth": 120,
  "endOfLine": "auto"
}
  • خط ۵: یک خط کد می‌تواند تا ۱۲۰ کاراکتر طول داشته باشد؛
  • خط ۶: نشانگر پایان خط می‌تواند CRLF (ویندوز) یا LF (یونیکس) باشد؛

در نهایت، فایل [package.json] به شرح زیر اصلاح می‌شود:


"scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "lintfix": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
},
  • خط ۷: ما دستور [lintfix] را اضافه می‌کنیم که با دستور [lint] در خط ۶ یکسان است، با این تفاوت که شامل پارامتر [--fix] نیز می‌باشد. دستور [lint] نحوی و قالب همه فایل‌های پروژه را بررسی می‌کند و هرگونه خطا را گزارش می‌دهد. دستور [lintfix] نیز همین کار را انجام می‌دهد، با این تفاوت که هرگونه مشکل قالب‌بندی که قابل اصلاح باشد، به‌طور خودکار برطرف خواهد شد. [lintfix] دستوری است که در صورت شکست کامپایل به‌دلیل مشکلات قالب‌بندی فایل باید استفاده شود؛

پس از انجام این کار، فایل [index.vue] را به شرح زیر اصلاح می‌کنیم:

Image


<script>
/* eslint-disable no-console */
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  // چرخهٔ عمر
  created() {
    console.log('created, route=', this.$route)
  }
}
</script>
  • خطوط ۱۰–۱۲: تابع [created] را اضافه کنید که پس از ایجاد کامپوننت، به طور خودکار اجرا می‌شود؛
  • خط ۱۱: نمایش مسیر فعلی؛
  • خط ۲: یک نظر برای [eslint]. بدون این نظر، [eslint] خطای خط ۱۱ را گزارش می‌کند: این تابع دستورالعمل‌های [console] را در توابع چرخه عمر نمی‌پذیرد. [eslint] قابل پیکربندی است. ما پیکربندی پیش‌فرض آن را حفظ می‌کنیم و از نظراتی مانند نظر در خط ۲ برای غیرفعال کردن یک قاعده خاص در [eslint] استفاده خواهیم کرد. ما از دو نوع نظر استفاده خواهیم کرد:
    • /* غیرفعال کردن قاعده [eslint] */: یک قاعده را برای کل فایل غیرفعال می‌کند؛
    • // disable rule [eslint]: یک قاعده را برای خط بعدی غیرفعال می‌کند؛

همزمان با تایپ کردن، خطاها علامت‌گذاری می‌شوند و تابع [Quick Fix] در دسترس است:

Image

پروژه را اجرا کنید:

Image

  • در [1]، برگه [Vue] ابزارهای توسعه‌دهنده مرورگر (F12);
  • در [2] و [3]، نمایش مسیر؛

چرا به جای یک نما، دو نما؟

یک برنامه [nuxt] از دو مؤلفه تشکیل شده است: یک سرور و یک کلاینت:

  1. سرور صفحات برنامه را هنگام راه‌اندازی برنامه و سپس هر بار که یک صفحه در مرورگر تازه می‌شود (F5) یا کاربر دستی یک URL را برای برنامه وارد می‌کند، فراهم می‌کند؛
  2. هر صفحه که توسط مرورگر ارائه می‌شود، شامل صفحه درخواستی و همچنین کد جاوااسکریپت کل برنامه است که سپس در مرورگر اجرا می‌شود. این بخش کلاینت است. تا زمانی که صفحه در مرورگر رفرش نشود، برنامه مانند یک برنامه استاندارد Vue در حالت [sap] (برنامه تک‌صفحه‌ای) عمل می‌کند. به محض اینکه کاربر به صورت دستی رفرش صفحه را فعال کند، صفحه از سرور درخواست می‌شود و فرآیند به فاز ۱ قبلی بازمی‌گردد.

آنچه مهم است درک این نکته است که صفحات موجود در پوشه [pages] یکسان هستند، چه توسط سرور ارائه شوند و چه توسط کلاینت. به همین دلیل، توسعه‌دهندگان [nuxt] این نوع صفحات را صفحات ایزومورفیک می‌نامند. همان صفحات [.vue] می‌توانند هم توسط کلاینت و هم توسط سرور تفسیر شوند. بیایید مثال صفحه [index] را در نظر بگیریم:


<template>
  <div class="container">
    <div>
      <logo />
      <h1 class="title">
        nuxt-intro
      </h1>
      <h2 class="subtitle">
        nuxt-intro
      </h2>
      <div class="links">
        <a href="https://nuxtjs.org/" target="_blank" class="button--green">
          Documentation
        </a>
        <a
          href="https://github.com/nuxt/nuxt.js"
          target="_blank"
          class="button--grey"
        >
          GitHub
        </a>
      </div>
    </div>
  </div>
</template>

<script>
/* eslint-disable no-console */
import Logo from '~/components/Logo.vue'

export default {
  components: {
    Logo
  },
  //چرخهٔ زندگی
  created() {
    console.log('created, route=', this.$route)
  }
}
</script>

از آنجایی که این صفحه، صفحه اصلی است، هنگام راه‌اندازی برنامه توسط سرور ارائه می‌شود. صفحه روی سرور نیز یک چرخه عمر دارد که با چرخه عمر یک صفحه استاندارد [Vue] یکسان است، به جز توابع [beforeMount, monted] که در سمت سرور وجود ندارند. تابع [created] اجرا می‌شود که این موضوع را اولین ورودی لاگ توضیح می‌دهد. ضمناً، این بدان معناست که سرور قادر به اجرای اسکریپت‌های جاوااسکریپت است. در این مورد، و به طور کلی، این سرور یک سرور [node.js] است. پس از ایجاد صفحه در سرور، آن به مرورگر ارسال می‌شود و در آنجا دوباره چرخهٔ عمر را طی می‌کند. تابع [created] برای بار دوم اجرا می‌شود که منجر به ثبت دومین ورودی در لاگ می‌شود.

معماری یک برنامه [nuxt] ممکن است به شکل زیر باشد:

Image

  • [1]: مرورگری که پس از بارگذاری برنامه [nuxt] در آن میزبانی می‌کند. این همان چیزی است که به آن کلاینت [nuxt] گفته می‌شود؛
  • [3]: سروری که در ابتدا میزبان برنامه [nuxt] است. این فایل هنگام راه‌اندازی برنامه و هر بار که کاربر صفحه جاری مرورگر را تازه می‌کند یا دستی یک URL را از برنامه وارد می‌کند، در مرورگر [1] بارگذاری می‌شود. تفاوت در عملکرد نسبت به یک برنامه Vue سنتی در همینجاست. در مورد مورد دوم، پس از بارگذاری در مرورگر، سرور دیگر هرگز فراخوانی نمی‌شد. تفاوت مهم دیگری که تاکنون نتوانسته‌ایم مشاهده کنیم این است که سرور یک برنامه Vue یک سرور ایستا است و قادر به تفسیر صفحات [.vue] نیست، در حالی که سرور یک برنامه Nuxt از نوع [universal] یک سرور جاوا اسکریپت است. پیش از ارسال یک صفحه به مرورگر، سرور می‌تواند اسکریپت‌ها را اجرا کند و برای مثال، داده‌ها را از سرور [2] بازیابی نماید؛
  • [2]: سروری است که داده‌ها را یا به کلاینت [nuxt] [1]، یا به سرور [nuxt] [3] ارائه می‌دهد؛

در نمودار بالا، سه زیرسامانهٔ کلاینت/سرور قابل تشخیص هستند:

  • [1, 3]: میزبان برنامه [nuxt] است. [3] آن را هنگام راه‌اندازی برنامه، همراه با صفحه اصلی، و هر زمان که کاربر به‌صورت دستی یک صفحه را درخواست کند، فراهم می‌کند. [1] میزبان استبرنامه [nuxt] که از [3] دریافت می‌شود، سپس در حالت [SAP] عمل می‌کند تا زمانی که صفحات به صورت دستی از [3] درخواست شوند؛
  • [1, 2]: در حالت [SAP]، کلاینت [nuxt] داده‌های خارجی را از یک یا چند سرور بازیابی می‌کند؛
  • [3, 2]: هنگام تولید صفحه‌ای که کاربر درخواست کرده است، سرور [3] ممکن است داده‌های خارجی را نیز از یک یا چند سرور بازیابی کند؛

بنابراین، سرور [3] است که یک برنامه [nuxt] را از یک برنامه [vue] متمایز می‌کند. این سرور هر بار که کاربر به‌صورت دستی یک صفحه را درخواست می‌کند، فراخوانی می‌شود. این سرور همان صفحات [.vue] را مانند کلاینت‌های [vue] و [1] پردازش می‌کند. این یک سرور جاوااسکریپت است که قادر به اجرای اسکریپت‌های موجود در صفحه می‌باشد. این می‌تواند، برای مثال، نحوه تولید صفحه اصلی را با استفاده از داده‌های خارجی تغییر دهد: در حالی که یک برنامه [vue] لزوماً این داده‌ها را از کلاینت [1] دریافت می‌کند، در اینجا این داده‌ها می‌توانند توسط سرور [3] قبل از ارسال صفحه به کلاینت، به دست آیند. بدین ترتیب صفحه اصلی معنادار شده و می‌تواند به بهبود SEO برنامه کمک کند.

توجه: در حالت توسعه، سه موجودیت [1, 2, 3] اغلب روی یک ماشین قرار دارند. این وضعیت در تمام مثال‌های ما نیز صادق است.

3.9. انتقال کد منبع برنامه به یک پوشهٔ جداگانه

ما بعداً برنامه‌های مختلف [nuxt] را در همان پوشه [dvp] ایجاد خواهیم کرد. این به آن دلیل است که پوشه وابستگی‌های [node_modules] که برای هر پروژه [nuxt] ایجاد می‌شود، می‌تواند حجمی در حدود چند صد مگابایت داشته باشد. ما پوشه‌های مختلف [nuxt-00, nuxt-01, ...] را در داخل پوشه [dvp] ایجاد خواهیم کرد تا کد منبع مثال‌هایی را که قرار است آزمایش شوند، در خود جای دهند. سپس از فایل پیکربندی [nuxt-config.js] برای مشخص کردن محل کد منبع پروژه [dvp] استفاده خواهیم کرد، که در این آموزش تنها پروژه [nuxt] باقی خواهد ماند.

ما کد منبع برنامه‌ای را که در ابتدا توسط دستور [yarn create nuxt-app] تولید شده است، به پوشه‌ای به نام [nuxt-00] منتقل می‌کنیم:

Image

  • در [2]، ما پوشه‌های [components, layouts, pages] را به پوشه‌ای به نام [nuxt-00] منتقل کرده‌ایم؛
  • در [3]، باید فایل [nuxt.config.js] را اصلاح کنیم؛

ما فایل [nuxt.config.js] را به شرح زیر اصلاح می‌کنیم:


export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  ...
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  },
  // پوشه کد منبع
  srcDir: 'nuxt-00',
  // روتر
  router: {
    //ریشهٔ برنامه
    base: '/nuxt-00/'
  },
  // سرور
  server: {
    // پورت سرویس، به‌طور پیش‌فرض 3000
    port: 81,
    // آدرس‌های شبکهٔ گوش‌داده‌شده، پیش‌فرض localhost: 127.0.0.1
    //0.0.0.0 = تمام آدرس‌های شبکه روی دستگاه
    host: '0.0.0.0'
  }
}

این فایل در دو مکان اصلاح شده است:

  • خط ۱۷: مشخص می‌کنیم که کد منبع پروژه [dvp] در پوشه [nuxt-00] قرار دارد؛
  • خط ۲۱: مشخص شده است که ریشهٔ برنامهٔ URL اکنون [/nuxt-00/] است. این تغییر اجباری نبود. ما می‌توانستیم این ویژگی را حذف کنیم، که در این صورت ریشه URL، [/] می‌شد. در اینجا، این موضوع به ما کمک می‌کند تا به یاد داشته باشیم که کد منبع در حال اجرا، متعلق به پوشه [nuxt-00] است؛

پس از انجام این کار، پروژه [dvp] مانند قبل اجرا می‌شود:

Image

3.10. استقرار برنامه [nuxt-00]

ما قصد داریم برنامه [nuxt-00] را در محیطی غیر از محیط یکپارچه VSCode اجرا کنیم.

ابتدا، برنامه را کامپایل می‌کنیم:

Image

  • به [3]، نتیجه کامپایل سمت کلاینت. این توسط مرورگر اجرا خواهد شد؛
  • به [4]، نتیجهٔ کامپایل سمت سرور. این توسط سرور [node.js] اجرا خواهد شد؛

نتیجهٔ کامپایل در پوشهٔ [.nuxt] قرار می‌گیرد:

Image

ما پوشه‌های [.nuxt, node_modules] و فایل‌های [package.json, nuxt.config.js] را به یک پوشهٔ جداگانه کپی می‌کنیم:

Image

فایل [package.json] به صورت زیر ساده‌سازی شده است:


{
  "scripts": {
    "start": "nuxt start"
  }
}
  • فقط اسکریپت [start] حفظ می‌شود، زیرا امکان اجرای نسخه کامپایل‌شده پروژه را فراهم می‌کند؛

فایل [nuxt.config.js] به صورت زیر ساده‌سازی شده است:


export default {
  // روتر
  router: {
    // ریشهٔ URL برنامه
    base: '/nuxt-00/'
  },
  // سرور
  server: {
    // پورت سرویس، به‌طور پیش‌فرض 3000
    port: 81,
    // آدرس‌های شبکه‌ای که گوش داده می‌شوند، پیش‌فرض localhost: 127.0.0.1
    // 0.0.0.0 = تمام آدرس‌های شبکه روی دستگاه
    host: '0.0.0.0'
  }
}
  • خط ۵: پایه URL برای برنامه کامپایل‌شده تنظیم می‌شود؛
  • خطوط ۸–۱۴: پورت سرویس و آدرس‌های شبکه‌ای که باید روی آن‌ها گوش فرا داده شود، تعریف شده‌اند؛

پس از انجام این کار، یک ترمینال Laragon را باز کرده و به پوشه‌ای که حاوی نسخه کامپایل‌شده پروژه است، بروید. شما می‌توانید هر نوع ترمینالی را باز کنید، اما فایل اجرایی [npm] باید در دایرکتوری ترمینال باشد. این مورد برای ترمینال Laragon صدق می‌کند.

پس از انجام این کار، دستور [npm run start] را تایپ کنید:

Image

در [3] می‌بینیم که یک سرور راه‌اندازی شده و در حال گوش دادن به URL [http://192.168.1.128:81/nuxt-00/] است. حالا با استفاده از یک مرورگر در [4] این URL را درخواست کنیم. دقیقاً همان نتیجهٔ قبلی را دریافت می‌کنیم. در سمت سرور، لاگ‌ها نوشته شده‌اند. این همان لاگی است که در متدِ صفحه‌ای که توسط سرور اجرا شد، وجود دارد.

Image

در سمت مرورگر [6]، ما همچنین لاگ مربوط به متد [created] را در صفحه [index.vue] پیدا می‌کنیم، اما این بار توسط کلاینت اجرا شده است.

3.11. راه‌اندازی یک سرور امن

در بالا، URL برنامه، [http://192.168.1.128/nuxt-00/] است. ما می‌خواهیم که [https://192.168.1.128/nuxt-00/] باشد. بنابراین باید یک سرور امن راه‌اندازی کنیم. ما به شما نشان خواهیم داد چگونه این کار را انجام دهید.

توجه: این روش از مقاله [https://stackoverflow.com/questions/56966137/how-to-run-nuxt-npm-run-dev-with-https-in-localhost] گرفته شده است.

ابتدا، ما با استفاده از [openssl] یک کلید خصوصی و یک کلید عمومی ایجاد می‌کنیم. [openssl] معمولاً همزمان با سرور Laragon نصب می‌شود. در نتیجه، این فرمان در هر ترمینال Laragon در دسترس است. پس بیایید یک ترمینال Laragon را باز کرده و به پوشه‌ای که حاوی برنامه استقرار یافته است، برویم:

Image

Image

  • در [2]، دستور [openssl genrsa 2048 > server.key] را تایپ کنید؛
  • در [3]، فایلی با نام [server.key] ایجاد می‌شود؛
  • در [4]، دستور [openssl req -new -x509 -nodes -sha256 -days 365 -key server.key -out server.crt] را وارد کنید؛
  • در [5]، فایلی به نام [server.crt] ایجاد می‌شود؛

این دو فایل یک گواهی خودامضا را تشکیل می‌دهند. اکثر مرورگرها تنها پس از تأیید کاربر درخواست‌کننده صفحه، آن‌ها را می‌پذیرند.

اکنون باید از فایل‌های [server.key, server.crt] توسط وب‌اپلیکیشن استفاده شود. برای این کار، فایل [nuxt.config.js] باید به شرح زیر اصلاح شود:


import path from 'path'
import fs from 'fs'

export default {
  // روتر
  router: {
    // ریشهٔ URL برنامه
    base: '/nuxt-00/'
  },
  // سرور
  server: {
    // پورت سرویس، به‌طور پیش‌فرض 3000
    port: 81,
    // آدرس‌های شبکه‌ای که گوش داده می‌شوند، پیش‌فرض localhost: 127.0.0.1
    // 0.0.0.0 = تمام آدرس‌های شبکه روی دستگاه
    host: '0.0.0.0',
    // گواهی خودامضا
    https: {
      key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
      cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
    }
  }
}

خطوط ۱۸–۲۱ پروتکل [https] را پیاده‌سازی می‌کنند.

اکنون بیایید برنامه را دوباره اجرا کنیم:

Image

3.12. پایان مثال اول

مثال اول اکنون کامل شده است. این مثال چیزهای زیادی در مورد مفاهیم [nuxt] به ما آموخته است. اکنون مثال‌های بیشتری را توسعه خواهیم داد که آن‌ها را در پوشه‌های [nuxt-01, nuxt-02, ...] قرار می‌دهیم. از آنجا که این مثال‌ها از یک فایل [nuxt.config.js] متفاوت استفاده می‌کنند، فایل [nuxt.config.js] مورد استفاده برای اجرای آن‌ها را در هر یک از این پوشه‌ها ذخیره خواهیم کرد:

Image