Nuxt
Nuxt

Intro do Nuxt3 - Návod na Nuxt

Patrik KeblušekPatrik Keblušek,

Nuxt postavený na Vue.js patří mezi nejpoužívanější technologie v rámci frontendového webového programování. V době psaní tohoto článku se blíži k 50 000 stars na GitHube. V článku se detailně podívame na Nuxt3 jako celek, projdeme si ho od základů až po užitečné typy.

Co je Nuxt3?

Nuxt je framework založený na populární knihovne Vue.js. Jeho cílem je zjednodušit prácu s Vue.js a líp postavit JavaScriptové aplikace z pohledu performance a SEO. První stabilní 3.0.0. release byl vydán 20. ledna 2023. Zaujímavostí je to, že autoři pracovali na frameworku 16 měsícu, kým vydali první release-candidate verzi. Novinek je opravdu hodně, tak se na to pojďme podívat.

Jeho silnými stránkami jsou

  • server side rendering
  • automatický routing a automatické importy
  • performance a seo optimalizace (code splitting, minifikace…)
  • Rychlý Vite
  • Nitro engine
  • zero-config TypeScript support
  • podpora Vue.js composition API

Když by jsme porovnávali Nuxt3 se starším Nuxt2, tak Nuxt3 je díky novému Nitro výrazně rychlejší. Uživatelé ve Windowse, který čekali v Nuxt2 na cold-start až 1 minutu, se posunuli v Nuxt3 na pouhých 5 sekund. V Nuxt3 také můžete psát Composition API a s podporou TypeScriptu. Mimo jiné Nuxt3 má o 75% procent menší server deployments a client bundles v porovnání s Nuxt2. Také je k dispozici nová Nuxt CLI, která se jmenuji nuxi. Pokud jste analytický typ, tak určite oceníte nové Nuxt Devtools.

Init projektu

Projekt vytvoříme nasledujícím příkazem (my-app nahraďte za název váš aplikace):

npx nuxi@latest init my-app

Následně se můžeme přepnout do repozitára a nainstalovat balíčky:

cd my-app
npm install

A spouštíme projekt:

npm run dev

Konzole nám ukáže adresu, na které web běží. Obvykle je to localhost:3000.

Struktura projektu

Nuxt3 přichází s pevně danou strukturou složek. Při inicializaci nového projektu Nuxt vytvoří jenom potřebné složky. Nuxt3 může obsahovat tyto složky a soubory.

[složka] .nuxt 
[složka] .output 
[složka] assets 
[složka] components 
[složka] composables 
[složka] content 
[složka] layouts 
[složka] middleware 
[složka] modules 
[složka] node_modules 
[složka] pages 
[složka] plugins 
[složka] public 
[složka] server 
[složka] utils 
[soubor] .env 
[soubor] .gitignore 
[soubor] .nuxtignore 
[soubor] app.config.ts 
[soubor] app.vue 
[soubor] nuxt.config.ts 
[soubor] package.json 
[soubor] tsconfig.json

Routing (Pages) a navigace

Nuxt3 jsi automaticky vytváří url adresy na základě toho, jak mu vyskladáte .vue soubory v složce /pages. Když vytvoříte soubor s názvem articles.vue a umístěte tento soubor do /pages, tak se vám vytvoří url adresa /articles. Více napoví kód níže.

Tyhle soubory:

pages/
--| about.vue
--| index.vue
--| posts/
----| [id].vue

Vytvoří tenhle router soubor:

{
  "routes": [
    {
      "path": "/about",
      "component": "pages/about.vue"
    },
    {
      "path": "/",
      "component": "pages/index.vue"
    },
    {
      "path": "/posts/:id",
      "component": "pages/posts/[id].vue"
    }
  ]
}

[id].vue je dynamická url adresa. Znamená to, že na místo [id], může přijít cokoliv. Vytváříme tak url adresy jako /posts/123. V tomhle případě si hodnotu [id], odchytíme pomocí useRoute() composable nasledovně.

const route = useRoute();
console.log(route.params.id);

V případě, že používate pages pro vykreslení obsahu, přidajte do App.vue komponentu <NuxtPage />, která zajistí vykreslení aktívní stránky.

Komponenty a auto-importy

Komponenty k webu ukladáme do složky /components a následně k nim přistupujeme z našich šablon zavolaním cesty k souboru (od úrovně složky components). K souboru, který je teda umístněn ve /components/Article/item přistúpime v HTML v našich .vue souborech jako <ArticleItem />. Komponenty není třeba importovat, to udělá za nás Nuxt. 

V případě, že vytvoříte rovnaký název komponenty jako je název složky o úroveň výše, tak v kódě přistupujete k souboru pouze s názvem komponenty. To znamená, že soubor /ArticleItem/ArticleItem.vue zavoláte jenom jako <ArticleItem />.

Kód v komponentách pak píšeme tak, jak jsme zvyklý z Vue.js:

<script setup>
</script>
<template>
</template>
<style scoped>
</style>

Layouts

Layouty nám slouží pro vytvoření znovu-použitelného kódu, například pro rozvržení obsahu s hlavičkou a patičkou. Layouts patří do složky /layouts a je potřebné <NuxtPage> obalit do <NuxtLayout />.

App.vue

<NuxtLayout >
   <NuxtPage />
</NuxtLayout>

/layouts/custom.vue

<template>
   <div>
      <header>header</header>
      <NuxtPage />
   </div>
</template>

Následně potřebujeme jednotlivým stránkam říct, že mají použít náš vytvořený layout pomocí definePageMeta():

/pages/articles/index.vue

<script setup>
    definePageMeta({
        layout: 'custom'
    });
</script>
<template>
    <main>
        <h1>Article list</h1>
    </main>
</template>

Pokuď chceme, aby náš layout bol automaticky na všech stránkach, pak stačí soubor s layoutem přejmenovat na default.vue a třetí krok můžete vynechat.

Middlewares

Middlewares se spouští vždy před přesměrováním na specifickou url adresu.

Rozdělujeme je do 3 kategorií:

  • Anonymous/ Inline middlewares (definované pŕímo v pages, kde jsou použité)
  • Named route middlewares (ve složce middleware)
  • Global route middlewares (ve složce middleware - přidáme .global za název souboru, spustí se vždy se změnou url adresy)

Nejdříe se spouští global middleware, pak middlewares definované na úrovni stránek. Pořadí global middlewares můžeme ovlivnit tak, že před název middleware vložíme pořadové číslo.

01.setup.global.ts
02.analytics.global.ts

Ukázka jak spustíme middleware pro konkrétní stránku:

/middleware/auth.js

export default defineNuxtRouteMiddleware((to, from) => {
    // named route middleware
    if (1 === 1) {
        console.log('is logged in');
    } else {
        return navigateTo('/nekam');
    }
});

Definujeme middleware na konkrétní stránce pomocí definePageMeta():

/pages/articles/index.vue

<script setup>
    definePageMeta({
        middleware: 'auth',
    });
</script>
<template>
    <main>
        <h1>Article list</h1>
    </main>
</template>

Spuštění global middleware

Stačí pouze vytvořit soubor s názvem neco.global.ts ve složce middleware.

export default defineNuxtRouteMiddleware((to, from) => {
    //global middleware
    console.log('global middleware');
});

Fetchování dat

Na fetchování dat nám slouží composables od Nuxtu, konkrétně useFetch a useAsyncData a také knihovna $fetch. useFetch a useAsyncData jsou vykonávané na server, data jsou klientovi zasílýny v payloudu a zamezují opětovnému zavoláni requestu na clientovi (v našem případě browsru). useFetch je wrapper nad useAsyncData a $fetch. useFetch a useAsyncData jsou cachované.

useFetch je nejpřímější způsob fetchovania v script-setup funkcií.

$fetch Nuxt dokumentace doporučuji používat na základě interakce uživatele na stránce.

Pro větší kontrolu můžeme použít useAsyncData a $fetch samostatně.

Použití useFetch v script setup:

const { data } = await useFetch('https://swapi.dev/api/people/1');

SEO a Meta

Nuxt3 poskytuje composables, které nám umožňují nastavovat SEO a meta tagy. Můžeme to udělat díky useHead() nebo useSeoMeta(). Obě composables jsou reaktivní. Také lze značky definovat přímo v HTML kódu pomocí komponent <Title>, <NoScript>, <Style>

// způsob 1
useHead({
   title: 'Nuxt App SEO page',
   meta: [
      { name: 'description', content: 'Nuxt 3 app description' }
   ],
   bodyAttrs: {
      class: 'test'
   },
   script: [ { innerHTML: 'console.log(\'Hello from script\')' } ],
});
// způsob 2 -> key: values
useSeoMeta({
   ogTitle: 'Neco og title',
   description: 'Neco description',
   ogDescription: 'Neco og description',
   ogImage: 'https://example.com/image.png',
   twitterCard: 'summary_large_image',
   cokoliv: 'cokoliv here'
});

Tipy (užitečné composables)

  • ty které jsem již zmínil (useHead(), useRoute()…)
  • useFetch() a pick option: string[] - fetchujte z dat jenom ty klíče, které potřebujete
  • useCookie() - reaktivní SSR read and write cookies
  • useRouter() - přístup k Nuxt routeru a jeho metodám (.back(), .push()…)
  • useRuntimeConfig() - přístup k proměnným nastavení aplikace (napr. ENV variables)
  • spoustu dalších v dokumentaci https://nuxt.com/docs/api/composables

Tipy (page transitions)

V Nuxtu je možné definovat animace při přechodu jednotlivých stránek a layoutů. Nastavení se provádí v nuxt.config.ts a přidaním CSS ke stránce (nebo App.vue).

nuxt.config.ts

app: {
   pageTransition: { name: 'page', mode: 'out-in' }
},

App.vue

<style>
   .page-enter-active,
   .page-leave-active {
      transition: all 0.4s;
   }
   .page-enter-from,
   .page-leave-to {
		opacity: 0;
      filter: blur(1rem);
   }
</style>

Nuxt modules

Nuxt3 poskytuje moduly, které jsi nainstalujete skrz npm/ pnpm/ yarn. Jde o nejpoužívanější balíčky, které se spolu s Nuxt.js běžne nebo často používají. Nájdete zde například moduly pro ESLint, Piniu nebo Tailwind CSS… Samozřejmě, že si můžete nainstalovat balíčky aj vlastní cestou ale pokuď existuje modul pro Nuxt3, měli by jste tuto možnost minimálně zvážit. Pravdepodobně se nainstalovaním modulu cez oficiální stránky vyhnete problémům například se server-side renderingem.

Balíčky si můžete prohlédnout na této adrese.

Repozitář

Prezentovaný kód naleznete v našem repu.

Závěr

Díky pokud jste se dočetli až sem. Nuxt je síce mladá technologie ale díky i díky ní je Vue.js intuitivnejší a zábavnější. Kromě našeho blogu běží na Nuxt3 už i několik známych stránek v ČR a to například Prima+, Airstop.cz nebo Batstore. Přeji hodně úspechů s Nuxt3.