3. Een eerste [nuxt.js]-toepassing
3.1. Het maken van de applicatie
Voor onze [nuxt.js]-ontwikkelingen blijven we VS Code gebruiken. We hebben een lege map [dvp] aangemaakt waarin we onze voorbeelden gaan plaatsen. Vervolgens openen we deze map:

We slaan de werkruimte op onder de naam [intro-nuxtjs] [3-5]:

We openen een terminal [6-7]:

Tot nu toe hebben we de JavaScript-pakketbeheerder [npm] gebruikt. Voor de afwisseling gaan we hier de pakketbeheerder [yarn] gebruiken. Deze wordt, net als [npm], meegeleverd met de recente versies van [node.js]. Om een eerste [nuxt]-toepassing te maken, gebruiken we het commando [yarn create nuxt-app <dossier>] [1]. Het commando vraagt om een aantal gegevens over het te genereren project en genereert het vervolgens, zodra deze gegevens zijn verkregen: [2]:

In [2] is een volledige boomstructuur van bestanden aangemaakt. Het bestand [package.json] geeft de lijst weer van de JavaScript-bibliotheken die zijn gedownload naar de map [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"
}
}
Dit bestand geeft de antwoorden weer die zijn gegeven op het commando [create nuxt-app] om het aangemaakte project te definiëren (november 2019). De lezer kan een ander bestand [package.json] hebben:
- hij heeft mogelijk andere antwoorden op de vragen gegeven;
- de opdracht [create nuxt-app] is sinds het schrijven van dit document gewijzigd: de afhankelijkheden en versies zijn veranderd;
Regel 8 van het script is het commando dat de applicatie start:

- in [4] zien we dat de applicatie beschikbaar is op URL en [localhost:3000];
- in [5-6] zien we dat de applicatie een server [6] en een client (van deze server) [5] genereert;
Laten we URL [http://localhost:3000/] in een browser openen:

3.2. Beschrijving van de boomstructuur van een applicatie [nuxt]
Laten we de boomstructuur van de aangemaakte applicatie nog eens bekijken:

De mappen hebben de volgende functie:
assets | niet-gecompileerde bronbestanden van de applicatie (afbeeldingen, ...); |
static | de bestanden in deze map zijn beschikbaar in de hoofdmap van de applicatie. In deze map plaatsen we bestanden die in de hoofdmap van de applicatie moeten staan, zoals bijvoorbeeld het bestand [robots.txt] dat bestemd is voor zoekmachines; |
components | de [vue]-componenten van de applicatie die worden gebruikt in de [layouts] en de [pages]; |
lay-outs | de [vue]-componenten van de applicatie die dienen als lay-out voor de [pages]-bestanden; |
pagina’s | de componenten [vue] die door de verschillende routes van de applicatie worden weergegeven. Men zou ze de weergaven van de applicatie kunnen noemen. De pagina’s spelen een bijzondere rol in [nuxt]: de routes worden dynamisch aangemaakt op basis van de boomstructuur in de map [pages]; |
middleware | de scripts die bij elke routewijziging worden uitgevoerd. Hiermee kunnen de routes worden aangestuurd; |
plugins | heeft een verwarrende naam. Kan plug-ins bevatten, maar ook gewone scripts. De scripts in deze map worden uitgevoerd bij het opstarten van de applicatie; |
store | als deze map een script [index.js] bevat, dan definieert dit een instantie van de store van [Vuex]; |
Als een map leeg is, kan deze uit de boomstructuur worden verwijderd. Hierboven kunnen de mappen [assets, static, middleware, plugins, store] en [2] worden verwijderd.
3.3. Het configuratiebestand [nuxt.config]
De uitvoering van de applicatie wordt geregeld door het volgende bestand [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: [
// Doc: 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) {}
}
}
- regel 2: het type gegenereerde applicatie:
- [universal]: client/server-toepassing. Bij het eerste laden van de toepassing en bij elke paginaverversing in de browser wordt de server gevraagd om de pagina te leveren;
- [sap]: applicatietype [Single Page Application]: een server levert in eerste instantie de volledige applicatie. Vervolgens werkt de client zelfstandig, zelfs bij het verversen van een pagina in de browser;
- regels 6-18: definiëren de header HTML <head> van de verschillende pagina’s van de applicatie:
- regel 7: de tag <title> voor de titel van de pagina's;
- regels 8-16: de tags <meta>;
- regel 17: de tags <link>
In de gegenereerde applicatie ziet de tag <head> er als volgt uit (broncode van de pagina die in de browser wordt weergegeven):
<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">
Laten we nu het bestand [nuxt.config] als volgt aanpassen:
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' }]
},
Wanneer we de applicatie opnieuw uitvoeren, is de tag <head> als volgt geworden (broncode van de pagina die in de browser wordt weergegeven):
<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">
Laten we teruggaan naar het bestand [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: [
// Doc: 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) {}
}
}
- regel 12: tussen elke route van de client [nuxt] verschijnt een laadbalk (loading) als het wisselen van route even duurt. Met de eigenschap [loading] kun je deze laadbalk instellen, in dit geval de kleur van de balk;
- regel 16: de globale bestanden [css]. Deze worden automatisch opgenomen in alle pagina's van de applicatie;
- regels 24-27: de JavaScript-modules die nodig zijn voor het compileren (build) van de applicatie;
- regels 31-36: de JavaScript-modules die door de applicatie worden gebruikt;
- regel 41: instellingen voor de bibliotheek [axios] wanneer deze door de gebruiker is geselecteerd voor de dialoogvensters HTTP met servers van derden;
- regels 45-50: instellingen voor het compileren (build) van het project;
Er kunnen nog andere sleutels aan het configuratiebestand worden toegevoegd. Zo kunnen met name de servicepoort (standaard 3000) en de projectroot (standaard de hoofdmap van het project) worden ingesteld. Dat doen we nu door de volgende sleutels toe te voegen:
// broncodemap
srcDir: '.',
router: {
// URL hoofdmap van de applicatiepagina’s
base: '/nuxt-intro/'
},
// server
server: {
// servicepoort – standaard 3000
port: 81,
// netwerkadressen waarop wordt geluisterd – standaard localhost=127.0.0.1
host: '0.0.0.0'
}
- regel 2: waar de broncode van het project te vinden is. Deze bevindt zich hier in de huidige map, d.w.z. op hetzelfde niveau als het bestand [nuxt.config.js]. Dit is de standaardwaarde;
- regels 8-13: configureren de server (vergeet niet dat een [nuxt]-toepassing van het type [universal] zowel op een server als in een clientbrowser van die server is geïnstalleerd);
- regel 10: de pagina’s van de applicatie worden geleverd via poort 81 van de server;
- regel 12: standaard [localhost] (netwerkadres 127.0.0.1). Een machine kan meerdere netwerkadressen hebben als deze tot meerdere netwerken behoort. Het adres 0.0.0.0 geeft aan dat de webserver luistert op alle netwerkadressen van de machine;
- regels 3-6: configureren de router van de applicatie [nuxt];
- regel 5: de pagina’s van de applicatie zullen beschikbaar zijn op URL en [http://localhost:81/nuxt-intro/];
Laten we deze regels toevoegen aan het bestand [nuxt.config.js] en vervolgens het project uitvoeren (npm dev-script). Het resultaat is als volgt:

- in [1], het adres van de machine op een openbaar netwerk;
- in [2], de servicepoort;
- in [3], de root van de applicatie;
3.4. De map [layouts]

De map [layouts] is bestemd voor lay-outcomponenten. Standaard wordt de component met de naam [default.vue] gebruikt. In dit project is dat de volgende:
<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>
Opmerkingen
- regels 1-5: de [template] van de component;
- regel 3: de tag <nuxt /> verwijst naar de huidige pagina in de routing;
- regels 7-55: de stijl die door de lay-outcomponent wordt meegeleverd. Aangezien deze de huidige pagina van de routing bevat, wordt deze stijl toegepast op alle gerouteerde pagina’s van de applicatie;
We zien dat het primaire doel van de pagina [default.vue] hier is om een stijl toe te passen op de gerouteerde pagina’s.
3.5. De map [pages]

De map [pages] bevat de gerouteerde weergaven, die de gebruiker te zien krijgt. De pagina [index.vue] is de startpagina van de applicatie. Bij [nuxt.js] is er geen routeringsbestand. De routes worden bepaald op basis van de structuur van de map [pages]. Als er hier een bestand [index.vue] aanwezig is, wordt automatisch een route aangemaakt met de naam [index] en het pad [/index], dat wordt teruggebracht naar [/] omdat het om de startpagina gaat. Zo wordt de volgende route aangemaakt:
Het bestand [index.vue] ziet er als volgt uit:
<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>
De regels 1-25 van het bestand [template] geven het volgende beeld weer:

De afbeelding [1] wordt gegenereerd door regel 4 van het bestand [template]. We zien dus dat de pagina gebruikmaakt van een component met de naam [logo]. Deze wordt gedefinieerd in de regels 27-35 van het paginascript. In regel 28 verwijst de notatie [~] naar de root van het project.
3.6. De component [Logo]

De component [Logo.vue] is als volgt:
<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>
Deze component bestaat voornamelijk uit stijlen en animaties om een geanimeerde afbeelding te maken.
3.7. Weergave DevTools
[Vue DevTools] is de browserextensie waarmee de objecten [nuxt.js] en [vue.js] in de browser kunnen worden geïnspecteerd. We hebben deze extensie al gebruikt in het hoofdstuk over [vue.js]. Laten we eens kijken wat deze tool vindt wanneer de startpagina van onze applicatie wordt weergegeven:

- in [1] verwijst de component [PagesIndex] naar de pagina [pages/index.vue];
- in [2] zien we dat deze component een eigenschap [$route] heeft, wat de route is die naar de pagina [index] heeft geleid;
Laten we als eenvoudige oefening deze route in de console weergeven.
3.8. De startpagina aanpassen
We gaan het bestand [index.vue] aanpassen. In onze projectinstallatie hebben we twee afhankelijkheden geïnstalleerd:
- [eslint]: deze controleert de syntaxis van JavaScript-bestanden en Vue-componenten. Als de extensie [ESLint] van VSCode is geïnstalleerd, wordt deze syntaxis gecontroleerd tijdens het typen en worden fouten onmiddellijk gemeld;
- [prettier]: deze opmaakt de JavaScript-code volgens een standaardformaat;
Deze afhankelijkheden zijn vastgelegd in het bestand [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"
}
Ik heb gemerkt (nov. 2019) dat bij de installatie via het commando [yarn create nuxt-app] de tools [eslint, prettier] niet werken tijdens het typen van tekst. Fouten worden pas bij het compileren gemeld. Na wat onderzoek heb ik een configuratie gevonden die werkt:

In de hoofdmap van het project installeer je een map [.vscode] met daarin het volgende bestand [settings.json]:
{
"eslint.validate": [
{
"language": "vue",
"autoFix": true
},
{
"language": "javascript",
"autoFix": true
}
],
"eslint.autoFixOnSave": true,
"editor.formatOnSave": false
}
- regels 2-11: geven aan dat wanneer [eslint] de .vue- en .js-bestanden valideert, het de fouten moet corrigeren die het kan corrigeren;
- regel 12: wanneer een bestand wordt opgeslagen, moet [eslint] de fouten corrigeren die het kan corrigeren;
- regel 13: schakelt de standaardopmaak in VSCode uit bij het opslaan. Dit wordt door [prettier] gedaan;
Met deze configuratie:
- worden syntax- of opmaakfouten direct gemeld tijdens het invoeren van de tekst;
- worden opmaakfouten automatisch gecorrigeerd bij het opslaan van het bestand;
De bibliotheek [prettier] wordt geconfigureerd door het bestand [.prettierrc]:

Dit bestand is standaard het volgende:
{
"semi": false,
"arrowParens": "always",
"singleQuote": true
}
- regel 1: geen ; aan het einde van de instructies;
- regel 2: als een ‘pijlfunctie’ (arrow) één parameter heeft, wordt deze tussen haakjes geplaatst;
- regel 3: tekenreeksen worden tussen apostrofs geplaatst (geen aanhalingstekens);
We voegen de volgende twee regels toe:
{
"semi": false,
"arrowParens": "always",
"singleQuote": true,
"printWidth": 120,
"endOfLine": "auto"
}
- regel 5: de coderegel mag maximaal 120 tekens lang zijn;
- regel 6: het einde-van-regel-teken kan zowel CRLF (Windows) als LF (Unix) zijn;
Ten slotte wordt het bestand [package.json] als volgt gewijzigd:
"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 ."
},
- regel 7: we voegen de opdracht [lintfix] toe, die identiek is aan de opdracht [lint] op regel 6, behalve dat deze de parameter [--fix] extra bevat. Het commando [lint] controleert de syntaxis en het formaat van alle bestanden in het project en meldt eventuele fouten. [lintfix] doet hetzelfde, met dit verschil dat opmaakfouten die kunnen worden gecorrigeerd, automatisch worden verholpen. [lintfix] is de opdracht die u moet gebruiken als de compilatie mislukt vanwege opmaakfouten in de bestanden;
Zodra dit is gebeurd, passen we het bestand [index.vue] als volgt aan:

<script>
/* eslint-disable no-console */
import Logo from '~/components/Logo.vue'
export default {
components: {
Logo
},
// levenscyclus
created() {
console.log('created, route=', this.$route)
}
}
</script>
- regels 10-12: we voegen de functie [created] toe, die automatisch wordt uitgevoerd zodra de component is aangemaakt;
- regel 11: de huidige route wordt weergegeven;
- regel 2: een opmerking voor [eslint]. Zonder deze opmerking geeft [eslint] een foutmelding; regel 11: er mogen geen [console]-instructies in de levenscyclusfuncties staan. [eslint] is configureerbaar. We behouden de standaardconfiguratie en gebruiken opmerkingen zoals die op regel 2 om een specifieke regel van [eslint] uit te schakelen. We gebruiken twee soorten opmerkingen:
- /* regel [eslint] uitschakelen */: een regel voor het hele bestand uitschakelen;
- // regel [eslint] uitschakelen: uitschakeling van een regel voor de volgende regel;
Tijdens het typen worden fouten gemeld en is de functie [Quick Fix] beschikbaar:

Het project wordt uitgevoerd:

- in [1], het tabblad [Vue] van de ontwikkeltools van de browser (F12);
- in [2] en [3], de weergave van de route;
Waarom twee weergaven en niet één?
Een [nuxt]-applicatie bestaat uit twee onderdelen: een server en een client:
- de server levert de pagina’s van de applicatie bij het opstarten ervan en vervolgens telkens wanneer een pagina in de browser wordt vernieuwd (F5) of wanneer de gebruiker handmatig een URL van de applicatie invoert;
- elke door de browser geleverde pagina bevat zowel de opgevraagde pagina als de JavaScript-code van de gehele applicatie, die vervolgens in de browser wordt uitgevoerd. Dit is de client. Zolang de pagina in de browser niet wordt vernieuwd, werkt de applicatie als een klassieke Vue-applicatie in [sap]-modus (Single Page Application). Zodra de gebruiker handmatig een paginavernieuwing activeert, wordt de pagina bij de server opgevraagd en keert men terug naar de vorige fase 1.
Wat je moet begrijpen, is dat het om dezelfde pagina’s uit de map [pages] gaat, ongeacht of ze door de server of de client worden geleverd. Om die reden noemen de ontwerpers van [nuxt] dit soort pagina’s isomorfe pagina’s. Dezelfde [.vue]-pagina’s kunnen zowel door de client als door de server worden geïnterpreteerd. Laten we de pagina [index] als voorbeeld nemen:
<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
},
// levenscyclus
created() {
console.log('created, route=', this.$route)
}
}
</script>
Aangezien dit de startpagina is, wordt deze bij het opstarten van de applicatie door de server geleverd. De pagina op de server heeft ook een levenscyclus, dezelfde als die van een klassieke [Vue]-pagina, behalve wat betreft de [beforeMount, monted]-functies die aan de serverzijde niet bestaan. De functie [created] wordt wel uitgevoerd, wat de eerste logvermelding verklaart. Dit betekent overigens dat de server in staat is om JavaScript-scripts uit te voeren. In dit geval, en in het algemeen, is deze server een [node.js]-server. Zodra de pagina op de server is aangemaakt, komt deze in de browser terecht, waar de levenscyclus opnieuw doorloopt. De functie [created] wordt een tweede keer uitgevoerd, wat de tweede log oplevert.
De architectuur van een [nuxt]-applicatie zou er als volgt uit kunnen zien:

- [1]: de browser die de applicatie [nuxt] host wanneer deze in de browser is geladen. Dit wordt de client [nuxt] genoemd;
- [3]: de server waarop de applicatie [nuxt] aanvankelijk wordt gehost. Deze wordt bij het opstarten van de applicatie en telkens wanneer de gebruiker de huidige browserpagina vernieuwt of handmatig een URL van de applicatie invoert, in de browser geladen. Hierin ligt het verschil in werking ten opzichte van een klassieke Vue-applicatie. Bij een klassieke Vue-applicatie werd de server, zodra deze in de browser was geladen, daarna nooit meer benaderd. Een ander belangrijk verschil dat we tot nu toe nog niet hebben kunnen zien, is dat de server van een Vue-app een statische server is, die de [.vue]-pagina's niet kan interpreteren, terwijl die van een Nuxt-app van het type [universal] een JavaScript-server is. Voordat een pagina naar de browser wordt verzonden, kan de server scripts uitvoeren en bijvoorbeeld gegevens ophalen van de server [2];
- [2]: is de server die gegevens levert aan ofwel de client [nuxt] [1], ofwel aan de server [nuxt] [3];
In het bovenstaande schema kunnen we drie client/server-subsystemen onderscheiden:
- [1, 3]: host de applicatie [nuxt]. [3] levert deze bij het opstarten van de applicatie samen met de startpagina en telkens wanneer de gebruiker handmatig een pagina opvraagt. [1] host deapplicatie [nuxt] die is ontvangen van [3], die op zijn beurt in de modus [SAP] werkt zolang de pagina’s niet handmatig worden opgevraagd bij [3];
- [1, 2]: in de modus [SAP] haalt de client [nuxt] externe gegevens op van een of meer servers;
- [3, 2]: bij het genereren van de door de gebruiker opgevraagde pagina kan de server [3] eveneens externe gegevens ophalen van een of meer servers;
Het is dus de server [3] die een toepassing [nuxt] onderscheidt van een toepassing [vue]. Deze server wordt telkens aangeroepen wanneer de gebruiker handmatig een pagina opvraagt. Hij verwerkt dezelfde [.vue]-pagina’s als de client [vue] en [1]. Het is een JavaScript-server die de scripts op de pagina kan uitvoeren. Dit kan bijvoorbeeld de manier beïnvloeden waarop de startpagina met externe gegevens wordt gegenereerd: terwijl een applicatie [vue] deze gegevens noodzakelijkerwijs van de client [1] haalt, kunnen ze hier door de server [3] worden opgehaald voordat de pagina naar de client wordt verzonden. De startpagina krijgt zo meer betekenis en kan bijdragen aan het verbeteren van de SEO van de applicatie.
Opmerking: in de ontwikkelingsmodus bevinden de drie entiteiten [1, 2, 3] zich vaak op dezelfde machine. Dit zal hier voor al onze voorbeelden het geval zijn.
3.9. De broncode van de applicatie verplaatsen naar een aparte map
Vervolgens gaan we verschillende [nuxt]-applicaties aanmaken in dezelfde map [dvp]. De map met afhankelijkheden [node_modules] die voor elk project [nuxt] wordt gegenereerd, kan namelijk enkele honderden megabytes groot zijn. We gaan verschillende mappen [nuxt-00, nuxt-01, ...] aanmaken in de map [dvp] om de broncode van de te testen voorbeelden in op te slaan. Vervolgens gebruiken we het configuratiebestand [nuxt-config.js] om aan te geven waar de broncode van het project [dvp] zich bevindt; dit blijft het enige project [nuxt] in deze tutorial.
We verplaatsen de broncode van de applicatie die aanvankelijk met het commando [yarn create nuxt-app] is gegenereerd naar een map met de naam [nuxt-00]:

- in [2] hebben we de mappen [components, layouts, pages] verplaatst naar een map [nuxt-00];
- in [3] moeten we het bestand [nuxt.config.js] aanpassen;
We wijzigen het bestand [nuxt.config.js] als volgt:
export default {
mode: 'universal',
/*
** Headers of the page
*/
...
/*
** Build configuration
*/
build: {
/*
** You can extend webpack config here
*/
extend(config, ctx) {}
},
// broncodemap
srcDir: 'nuxt-00',
// router
router: {
// hoofdmap van de applicatie
base: '/nuxt-00/'
},
// server
server: {
// servicepoort, standaard 3000
port: 81,
// netwerkadressen waarop wordt geluisterd, standaard localhost: 127.0.0.1
// 0.0.0.0 = alle netwerkadressen van de machine
host: '0.0.0.0'
}
}
Het bestand wordt op twee punten aangepast:
- regel 17: we geven aan dat de broncode van het project [dvp] te vinden is in de map [nuxt-00];
- regel 21: er wordt aangegeven dat de hoofdmap van de applicatie URL voortaan [/nuxt-00/] is. Deze wijziging was niet verplicht. We zouden deze eigenschap ook kunnen weglaten, waardoor de root van URL dan [/] zou zijn. Op deze manier kunnen we onthouden dat de uitgevoerde broncode afkomstig is uit de map [nuxt-00];
Nu dit is gebeurd, wordt het project [dvp] uitgevoerd zoals eerder:

3.10. Implementatie van de applicatie [nuxt-00]
We gaan de applicatie [nuxt-00] uitvoeren in een andere omgeving dan de geïntegreerde omgeving van VSCode.
Eerst compileren we de applicatie:

- tot [3], het resultaat van de compilatie door de client. Dit wordt uitgevoerd door de browser;
- naar [4], het resultaat van de servercompilatie. Dit wordt uitgevoerd door de server [node.js];
Het resultaat van de compilatie wordt in de map [.nuxt] geplaatst:

We kopiëren de mappen [.nuxt, node_modules] en de bestanden [package.json, nuxt.config.js] naar een aparte map:

Het bestand [package.json] wordt als volgt vereenvoudigd:
{
"scripts": {
"start": "nuxt start"
}
}
- alleen het script [start] wordt behouden, waarmee de gecompileerde versie van het project kan worden uitgevoerd;
Het bestand [nuxt.config.js] wordt als volgt vereenvoudigd:
export default {
// router
router: {
// root van de URL van de applicatie
base: '/nuxt-00/'
},
// server
server: {
// servicepoort, standaard 3000
port: 81,
// netwerkadressen waarop wordt geluisterd, standaard localhost: 127.0.0.1
// 0.0.0.0 = alle netwerkadressen van de machine
host: '0.0.0.0'
}
}
- regel 5: we stellen de basis-URL van de gecompileerde applicatie in;
- regels 8-14: de servicepoort en de netwerkadressen waarop wordt geluisterd, worden gedefinieerd;
Zodra dit is gebeurd, openen we een Laragon-terminal en navigeren we naar de map met de gecompileerde versie van het project. We kunnen elk type terminal openen, maar het uitvoerbare bestand [npm] moet zich in de werkdirectory van de terminal bevinden. Dit is het geval bij de Laragon-terminal.
Vervolgens typ je de opdracht [npm run start]:

In [3] zien we dat er een server is gestart en dat deze luistert op URL [http://192.168.1.128:81/nuxt-00/]. Laten we nu dit adres URL opvragen met een browser [4]. We zien inderdaad hetzelfde als eerder. Op de terminal zijn er logbestanden geschreven [5]. Dit is het logbestand dat is geplaatst in de methode [created] van de pagina [index.vue], die is uitgevoerd door de server [node.js].

Aan de browserzijde [6] vinden we ook het logboek van de methode [created] van de pagina [index.vue], maar deze keer uitgevoerd door de client.
3.11. Een beveiligde server opzetten
Hierboven is de URL van de applicatie [http://192.168.1.128/nuxt-00/]. We willen dat deze [https://192.168.1.128/nuxt-00/] wordt. We moeten dus een beveiligde server opzetten. We laten zien hoe je dit doet.
Opmerking: de methode is ontleend aan het artikel [https://stackoverflow.com/questions/56966137/how-to-run-nuxt-npm-run-dev-with-https-in-localhost].
Allereerst maken we een privésleutel en een openbare sleutel aan met [openssl]. [openssl] wordt normaal gesproken tegelijk met de Laragon-server geïnstalleerd. Daardoor is dit commando beschikbaar in elke Laragon-terminal. Laten we dus een Laragon-terminal openen en naar de map van de geïmplementeerde applicatie gaan:


- in [2] typen we de opdracht [openssl genrsa 2048 > server.key];
- in [3] wordt een bestand [server.key] aangemaakt;
- in [4] voer je het commando [openssl req -new -x509 -nodes -sha256 -days 365 -key server.key -out server.crt] in;
- in [5] wordt een bestand [server.crt] aangemaakt;
Deze twee bestanden vormen samen een zelfondertekend certificaat. De meeste browsers accepteren deze pas na goedkeuring door de gebruiker die de pagina heeft opgevraagd.
De bestanden [server.key, server.crt] moeten nu door de webapplicatie worden gebruikt. Hiervoor moet het bestand [nuxt.config.js] als volgt worden aangepast:
import path from 'path'
import fs from 'fs'
export default {
// router
router: {
// root van de URL van de applicatie
base: '/nuxt-00/'
},
// server
server: {
// servicepoort, standaard 3000
port: 81,
// netwerkadressen waarop wordt geluisterd, standaard localhost: 127.0.0.1
// 0.0.0.0 = alle netwerkadressen van de machine
host: '0.0.0.0',
// zelfondertekend certificaat
https: {
key: fs.readFileSync(path.resolve(__dirname, 'server.key')),
cert: fs.readFileSync(path.resolve(__dirname, 'server.crt'))
}
}
}
Dit zijn de regels 18-21 die het protocol [https] instellen.
Laten we de applicatie nu opnieuw uitvoeren:

3.12. Einde van het eerste voorbeeld
Het eerste voorbeeld is nu afgerond. We hebben hiermee veel concepten van [nuxt] geleerd. We gaan nu andere voorbeelden ontwikkelen die we in mappen met de naam [nuxt-01, nuxt-02, ...] zullen plaatsen. Aangezien deze voorbeelden een ander [nuxt.config.js]-bestand zullen gebruiken, slaan we in elk van deze mappen het [nuxt.config.js]-bestand op dat is gebruikt om ze uit te voeren:
