Skip to content

10. Esempio [nuxt-07]: Contesti client e server

10.1. Introduzione

L'esempio [nuxt-07] mira a esplorare l'oggetto [context] sia sul lato server che sul lato client. È importante ricordare che questi due componenti delle applicazioni [nuxt] sono separati: non condividono nulla tranne:

  • ciò che il server sceglie di inviare al client (nella risposta HTTP e nella pagina renderizzata);
  • ciò che il client sceglie di inviare al server (nella sua richiesta HTTP);

Quindi, come vedremo, sebbene gli oggetti gestiti dal server e quelli gestiti dal client abbiano lo stesso nome, non sono identici: a volte possono essere copie l'uno dell'altro, ma non hanno mai lo stesso riferimento. La modifica di un oggetto lato client non ha alcun effetto sull'oggetto con lo stesso nome sul lato server, e viceversa.

L'esempio [nuxt-07] si ottiene inizialmente copiando l'esempio [nuxt-01]:

Image

  • in [2], aggiungeremo un plugin condiviso dal client e dal server;
  • in [3], modificheremo leggermente la pagina [index];

10.2. Il plugin [common / main.js]

Il plugin [common / main.js] viene eseguito sia dal client che dal server: ciò è dovuto alla seguente configurazione in [nuxt.config.js]:


/*
   ** Plugins to load before mounting the App
   */
plugins: [{ src: '~/plugins/common/main.js' }],
  • riga 4: l'assenza della proprietà [mode] significa che il plugin [~/plugins/common/main.js] verrà eseguito sia dal client che dal server: prima dal server, poi dal client;

Questo plugin sarà il seguente:


/* eslint-disable no-undef */
/* eslint-disable no-console */
export default function(...args) {
  // who executes this code?
  console.log('[main server], process.server=', process.server, 'process.client=', process.client)
  const who = process.server ? 'server' : 'client'
  const main = '[main ' + who + ']'
  // number of arguments
  console.log(main + ', il y a', args.length, 'arguments')
 
  // 1st argument
  const context = args[0]
  // key context
  dumpkeys(main + ', context', context)
  // the application
  dumpkeys(main + ', context.app', context.app)
  // the road
  dumpkeys(main + ', context.route', context.route)
  console.log(main + ', context.route=', context.route)
  // the router
  dumpkeys(main + ', context.app.router', context.app.router)
  // on router.options.routes
  dumpkeys(main + ', context.app.router.options.routes', context.app.router.options.routes)
  console.log(main + ', context.app.router.options.routes=', context.app.router.options.routes)
 
  // 2nd argument
  const inject = args[1]
  console.log('inject=', typeof inject)
}
 
function dumpkeys(message, object) {
  // list of [object] keys
  const ligne = 'Liste des clés [' + message + ']'
  console.log(ligne)
  // kEY LIST
  if (object) {
    console.log(Object.keys(object))
  }
}
  • righe 31–39: la funzione [dumpkeys] elenca le proprietà dell'oggetto passato come secondo parametro. Questo elenco è preceduto dal messaggio passato come primo parametro;
  • riga 3: vogliamo sapere quanti argomenti riceve la funzione. Per farlo, usiamo la notazione [...args], che inserirà i parametri effettivi della funzione nell'array [args]. Scopriremo che ci sono due argomenti;
  • riga 5: visualizziamo chi sta eseguendo il codice, il server o il client;
  • riga 6: l'esecutore del codice, client o server;
  • riga 7: una costante stringa utilizzata nei log;
  • riga 12: vedremo che il primo argomento ricevuto dal plugin è il contesto dell'esecutore;
  • riga 14: elenco delle chiavi per l'oggetto [context];
  • riga 16: vedremo che l'oggetto [context] ha una proprietà [app] che rappresenta l'applicazione [nuxt];
  • riga 18: vedremo che l'oggetto [context] ha una proprietà [route] che rappresenta il percorso corrente del router;
  • riga 21: vedremo che l'oggetto [app] ha una proprietà [router] che rappresenta il router;
  • riga 23: l'oggetto [router.options.routes] rappresenta i vari percorsi dell'applicazione;
  • righe 27–28: il secondo argomento del plugin è la funzione [inject] che abbiamo usato nell'esempio [nuxt-06];

10.3. Il plugin eseguito dal server

Una volta eseguito, il server visualizza quanto segue:

[main server], process.server= true process.client= false
[main server], il y a 2 arguments
Liste des clés [[main server], context]
[
  'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
  '$axios'
]
  • righe 11–12: abbiamo già avuto modo di utilizzare le proprietà [base] e [env], i cui valori provengono dal file [nuxt.config.js];
  • riga 8: la proprietà [app] si riferisce all'applicazione [nuxt];
  • riga 18: la proprietà [route] si riferisce al percorso corrente del router, ovvero alla pagina che il server invierà;
  • riga 13: la richiesta HTTP proveniente dal browser del client;
  • riga 14: la risposta HTTP del server;

L'elenco delle proprietà [context.app] è il seguente:

Liste des clés [[main server], context.app]
[
  'router',
  'nuxt',
  'head',
  'render',
  'data',
  'beforeCreate',
  'created',
  'mounted',
  'watch',
  'computed',
  'methods',
  'components',
  'context',
  '$axios'
]
  • riga 3: la proprietà [router] ci consente di accedere al router dell'applicazione. Questo è importante in [Nuxt] poiché il router è definito da [Nuxt] stesso e non dallo sviluppatore. Questa proprietà consente allo sviluppatore di modificare il router;

L'elenco delle proprietà [context.route] è il seguente:

Liste des clés [[main server], context.route]
[
  'name',
  'meta',
  'path',
  'hash',
  'query',
  'params',
  'fullPath',
  'matched'
]

Il percorso [context.route] all'avvio del server è il seguente:

[main server], context.route= {
  name: 'index',
  meta: [
    {}
  ],
  path: '/',
  hash: '',
  query: {},
  params: {},
  fullPath: '/',
  matched: [
    {
      path: '',
      regex: /^(?:\/(?=$))?$/i,
      components: [Object],
      instances: {},
      name: 'index',
      parent: undefined,
      matchAs: undefined,
      redirect: undefined,
      beforeEnter: undefined,
      meta: {},
      props: {}
    }
  ]
}
  • riga 2: vediamo che la pagina successiva sul server è [index] e che il suo percorso è [/] (riga 10);
  • riga 22: la proprietà [meta] consente di aggiungere proprietà ai percorsi;

Le proprietà di [context.app.router] del server sono le seguenti:

Liste des clés [[main server], context.app.router]
[
  'app',
  'apps',
  'options',
  'beforeHooks',
  'resolveHooks',
  'afterHooks',
  'matcher',
  'fallback',
  'mode',
  'history'
]

I vari percorsi dell'applicazione si trovano nella proprietà [context.app.router.options.routes]:

Liste des clés [[main server], context.app.router.options.routes]
[
  '0',
  '1',
  '2'
]
[main server], context.app.router.options.routes= [
  {
    path: '/page1',
    component: [Function: _d7b6c762],
    name: 'page1'
  },
  {
    path: '/page2',
    component: [Function: _d79a9860],
    name: 'page2'
  },
  {
    path: '/',
    component: [Function: _31eaad9f],
    name: 'index'
  }
]

Infine, il secondo argomento:

inject= function

10.4. La pagina [index] del server

La pagina [index] è la seguente:


<!-- page principale -->
<template>
  <Layout :left="true" :right="true">
    <!-- navigation -->
    <Navigation slot="left" />
    <!-- message-->
    <b-alert slot="right" show variant="warning">
      Home
    </b-alert>
  </Layout>
</template>
 
<script>
/* eslint-disable no-undef */
/* eslint-disable no-console */
/* eslint-disable nuxt/no-env-in-hooks */
 
import Navigation from '@/components/navigation'
import Layout from '@/components/layout'
 
export default {
  name: 'Home',
  // components used
  components: {
    Layout,
    Navigation
  },
  data() {
    return {
      who: process.server ? 'server' : 'client'
    }
  },
 
  // life cycle
  beforeCreate() {
    // client and server
    console.log('[home beforeCreate]')
  },
  created() {
    // client and server
    console.log('[home ' + this.who + ' created]')
    this.dumpkeys('[home ' + this.who + ' created], this.$nuxt', this.$nuxt)
    this.dumpkeys('[home ' + this.who + ' created], this.$nuxt.context', this.$nuxt.context)
  },
  beforeMount() {
    // customer only
    console.log('[home ' + this.who + ' beforeMount]')
  },
  mounted() {
    // customer only
    console.log('[home ' + this.who + ' mounted]')
  },
  methods: {
    dumpkeys(message, object) {
      // list of [object] keys
      const ligne = 'Liste des clés [' + message + ']'
      console.log(ligne)
      if (object) {
        console.log(Object.keys(object))
      }
    }
  }
}
</script>
  • riga 43: abbiamo già visto che il contesto di una pagina si trova in [this.$nuxt.context];
  • riga 42: visualizziamo anche le proprietà dell'oggetto [this.$nuxt];

Quando viene eseguita dal server, questa pagina genera i seguenti log:

[home beforeCreate]
[home server created]
Liste des clés [[home server created], this.$nuxt]
[
  '_uid',
  '_isVue',
  '$options',
  '_renderProxy',
  '_self',
  '$parent',
  '$root',
  '$children',
  '$refs',
  '_watcher',
  '_inactive',
  '_directInactive',
  '_isMounted',
  '_isDestroyed',
  '_isBeingDestroyed',
  '_events',
  '_hasHookEvent',
  '_vnode',
  '_staticTrees',
  '$vnode',
  '$slots',
  '$scopedSlots',
  '_c',
  '$createElement',
  '$attrs',
  '$listeners',
  '_routerRoot',
  '_router',
  '_route',
  '_bv__modal',
  '_bv__toast',
  '_vueMeta',
  'nuxt',
  '_watchers',
  'refreshOnlineStatus',
  'refresh',
  'errorChanged',
  'setLayout',
  'loadLayout',
  '_data',
  'layoutName',
  'layout',
  'isOnline',
  '_computedWatchers',
  'isOffline',
  'error',
  'context'
]

Le proprietà del contesto del server nella pagina [index] sono le seguenti:

Liste des clés [[home server created], this.$nuxt.context]
[
  'isStatic',
  'isDev',
  'isHMR',
  'app',
  'payload',
  'error',
  'base',
  'env',
  'req',
  'res',
  'ssrContext',
  'redirect',
  'beforeNuxtRender',
  'route',
  'next',
  '_redirected',
  '_errored',
  'params',
  'query',
  '$axios'
]

Queste sono le stesse proprietà presenti nell'oggetto [context] del plugin.

10.5. Il plugin eseguito dal client

Una volta che il server ha inviato la pagina [index] al browser del client, subentrano gli script lato client. Verrà quindi eseguito il plugin [main.js]. Questi log sono i seguenti:

[main server], process.server= false process.client= true
[main client], il y a 2 arguments
Liste des clés [[main client], context]
Array(17)0: "isStatic"1: "isDev"2: "isHMR"3: "app"4: "payload"5: "error"6: "base"7: "env"8: "redirect"9: "nuxtState"10: "route"11: "next"12: "_redirected"13: "_errored"14: "params"15: "query"16: "$axios"length: 17__proto__: Array(0)
Liste des clés [[main client], context.app]
Array(14)0: "router"1: "nuxt"2: "head"3: "render"4: "data"5: "beforeCreate"6: "created"7: "mounted"8: "watch"9: "computed"10: "methods"11: "components"12: "context"13: "$axios"length: 14__proto__: Array(0)
Liste des clés [[main client], context.route]
Array(8)0: "name"1: "meta"2: "path"3: "hash"4: "query"5: "params"6: "fullPath"7: "matched"length: 8__proto__: Array(0)
[main client], context.route= ObjectfullPath: "/"hash: ""matched: [{}]meta: [{}]name: "index"params: {}path: "/"query: {}__proto__: Object
Liste des clés [[main client], context.app.router]
Array(10)0: "app"1: "apps"2: "options"3: "beforeHooks"4: "resolveHooks"5: "afterHooks"6: "matcher"7: "fallback"8: "mode"9: "history"length: 10__proto__: Array(0)
Liste des clés [[main client], context.app.router.options.routes]
Array(3)0: "0"1: "1"2: "2"length: 3__proto__: Array(0)
[main client], context.app.router.options.routes= Array(3)0: {path: "/page1", name: "page1", component: ƒ}1: {path: "/page2", name: "page2", component: ƒ}2: {path: "/", name: "index", component: ƒ}length: 3__proto__: Array(0)
inject= function

Troviamo proprietà simili a quelle presenti sul lato server, con alcune proprietà mancanti e altre presenti. Ad esempio, alla riga 4, mancano le proprietà [req, res] — che erano le richieste HTTP del browser client e la risposta HTTP del server.

10.6. La pagina [index] del client

La pagina [index] del client produce i seguenti log:

1
2
3
4
5
6
7
8
[home beforeCreate]
[home client created]
Liste des clés [[home client created], this.$nuxt]
(51) ["_uid", "_isVue", "$options", "_renderProxy", "_self", "$parent", "$root", "$children", "$refs", "_watcher", "_inactive", "_directInactive", "_isMounted", "_isDestroyed", "_isBeingDestroyed", "_events", "_hasHookEvent", "_vnode", "_staticTrees", "$vnode", "$slots", "$scopedSlots", "_c", "$createElement", "$attrs", "$listeners", "_routerRoot", "_router", "_route", "_bv__modal", "_bv__toast", "_vueMeta", "nuxt", "_watchers", "refreshOnlineStatus", "refresh", "errorChanged", "setLayout", "loadLayout", "_data", "layoutName", "layout", "isOnline", "_computedWatchers", "isOffline", "error", "context", "_name", "setTransitions", "$loading", "$el"]
Liste des clés [[home client created], this.$nuxt.context]
(17) ["isStatic", "isDev", "isHMR", "app", "payload", "error", "base", "env", "redirect", "nuxtState", "route", "next", "_redirected", "_errored", "params", "query", "$axios"]
[home client beforeMount]
[home client mounted]
  • riga 4: le proprietà dell'oggetto [this.$nuxt]. Si tratta di un oggetto ricco con 51 proprietà;
  • riga 6: le proprietà dell'oggetto [this.$nuxt.context]. Si tratta delle stesse proprietà presenti nell'oggetto [context] del plugin client;