Prosty i Nowoczesny Framework dla Vue.js
7 godz. 2 min · Vue.js · Full-stack i Programowanie
Wojciech PołowniakSr. Fullstack EngineerW tym projekcie tworzyć będziemy praktyczny projekt - klona Wikipedii! Minipedia pobierze dane z prawdziwego źrodła danych, zewnętrznego API WikiMedia - będzie łudząco podobna do oryginału oraz współdzieliła najważniejsze funkcjonalności, takie jak dostarczanie treści w różnych wersjach językowych, możliwość wyszukiwania artykułów, czy pobieranie najpopularniejszych wpisów dla danego języka. Stworzymy także podstronę wyświetlającą za każdym razem losowy artykuł w danej wersji językowej.Zobaczysz też, jak dokonać migracji ze statycznej strony HTML na Nuxt - oraz jak tworzyć przykładowe komponenty podczas tego procesu.Dzięki temu wszystkiemu, dowiesz się jak wykorzystać nabytą wiedzę w praktyce.
Dzięki Nuxtowi dowiesz się jak optymalizować Twoje strony www z duchem idei progressive enhancement, dostarczając coraz to lepsze doświadczenia dla swoich użytkowników oraz tworząc aplikację napisaną w 100% w JavaScript, która będzie działała nawet wtedy, gdy użytkownik jawnie wyłączy go w przeglądarce! To wszystko za SSR (Server Side Rendering), dzięki któremu treści będą gotowe do konsumpcji już przy wstępnej, pierwszej odpowiedzi z serwera WWW.Oczywiście, ma to swoje implikacje na wydajność naszej aplikacji - sprawiając że Lighthouse czy optymalizacja pod SEO staje się coraz prostsza!
Czymże jest ekosystem danego frameworka bez wsparcia społeczności! Dlatego podczas tego kursu nauczysz się instalować i wykorzystywać różne pluginy i moduły, które zaoszczędzą Ci dużo czasu. Dowiesz się też, jak tworzyć własne moduły - które rozszerzą działanie Twojej aplikacji Nuxt w sposób czysty i zarządzalny.
Nuxt jest frameworkiem w którym pracujemy zarówno po stronie front-endu, jak i back-endu. W związku z czym, stworzymy swoje własne API (bazujące na express.js) które będzie pewnego rodzaju pośrednikiem pomiędzy API WikiMedia oraz Twoją aplikacją internetową.
W tym kursie, dowiesz się także jak tworzyć swoje własne Middleware'y - czyli fragmenty kodu wywoływane pomiędzy przechodzeniem między stronami, czy podczas innych zapytań HTTP.Dodatkowo, zobaczysz jakie narzędzia daje nam Nuxt aby tworzyć progresywne aplikacje internetowe, oferując wsparcie dla takich funkcjonalności jak np. animacje między przejściami pojedynczymi podstronami naszego serwisu.
Tajemnicze i18n - czyli numeronim odpowiadający angielskiemu słowu "internalisation" - odnosi się w kontekście web developmentu do tłumaczenia danych na różne języki. Podczas realizacji projektu Minipedii, nie tylko wykorzystamy standardowe podejście do tłumaczeń stałych elementów naszego interfejsu użytkownika, ale także przetłumaczymy same dane zwracane z API, wykorzystując inną wersję językową w zależności od preferencji użytkownika!
Poznasz też kilka ciekawych pluginów i rozwiązań dotyczących optymalizacji pod SEO - poza faktem, że podejście spełniające intencje użytkownika jest najlepszym, co możemy zrobić - pluginy generujące nam mapę stron automatycznie na podstawie zadeklarowanych przez nas podstron, czy generatory danych jsonld pomogą w pozycjonowaniu Twojej wydajnej aplikacji jeszcze wyżej w hierarchii wyszukiwarek.
Aby móc efektywnie korzystać z tego kursu, powinieneś posiadać średnio zaawansowaną wiedzę z kategorii Front End, z naciskiem na umiejętność posługiwania się JavaScriptem oraz solidne podstawy NodeJS. Konieczna jest znajomość Vue, jako że Nuxt jest frameworkiem korzystającym z niego u swoich podstaw. Jeśli czujesz się dość swobodnie w wyżej wymienionych aspektach web developmentu, ten kurs będzie idealny dla Ciebie.
Cześć! W poprzedniej lekcji przenieśliśmy nasz
projekt na makieta, jednak chciałem jeszcze wrócić tutaj do
sekcji związanej z lotami w jednym celu, bo w tym momencie mamy tylko i wyłącznie
jeden domyślny layout default i default oznacza, że jest on domyślnym layoutem,
który jeżeli nie zostanie sprecyzowany na poziomie page,
to zostanie on wykorzystany, aby renderować dane podstrony.
Ale to co możemy zrobić to możemy stworzyć
nowy tutaj plik, który nazywa się error kropka.
Jest to też domyślna rzecz, która po prostu jest w pakiecie.
Nie musimy jakoś rozumieć dlaczego to tak działa i w dokumentacji jest właśnie
napisane, że jesteśmy w stanie zadeklarować taki oto
layout, który będzie tworzył nam stronę z błędami.
Czyli na przykład jeżeli nie ma danej
strony, to taki błąd może nam się renderować.
Jeżeli to wykorzystamy
ja tutaj uzupełnię ten plik r.w tymi danymi, które wziąłem z dokumentacji.
No i to co tutaj się dzieje to faktycznie ustalamy layout na error i tutaj w opcjach
dostajemy od samego nexta wartość błędu który nastąpił.
Czyli jeśli teraz wpiszemy sobie.
Ścieżkę, która nie istnieje np.
Terror.
No to faktycznie widzimy, że jest tutaj sajgon.
Możemy wpisać dowolną treść, ona zawsze zostanie przekierowana na tą stronę.
I oczywiście tak samo jak w poprzednim przypadku.
Może powinniśmy to zmienić tutaj na article?
Nie wiem czy to ma sens w kontekscie
semantyki, ale w kontekscie renderowania jesteśmy w stanie tutaj ustawić article.
Po klasie content i w tym momencie cała
treść będzie renderowane tak jak pozostała część strony.
Czyli generalnie jesteśmy w stanie tworzyć
różne layouty i wybierać, który z layoutów ma zostać zaaplikowany.
Poprzez właściwość leją, czyli jeśli byśmy
tutaj dodali nowy layout z tego zaraz usuniemy, bo nie będzie
takiej konieczności, aby z niego korzystać.
Skupujemy tylko.
Podstawową strukturę zapiszemy to tutaj.
I powiedzmy, że chcemy mieć layout bez paska bocznego, bez nawigacji.
No to możemy się usunąć całą tą sekcję.
A.
Zapisać.
I w tym momencie, jeżeli np.
w indeksie zmienimy, że nie chcemy korzystać z domyślnego layoutu.
Domyślnym layoutem jest default, tylko powiemy sobie test.
To po zapisaniu.
Zobaczymy, że ten sidebar nam zniknął.
Oczywiście tutaj CSS3 nam się troszkę
rozjechały, ale idea jest taka, że możemy definiować za pomocą.
Właściwości layoutu na komponentach View na komponentach Nexta.
Który format renderowania chcemy wykorzystać w danej podstronie.
Czyli jeśli nie chcielibyśmy np.
na naszej stronie logowania posiadać
sidebar czy paska głównego, to oczywiście możemy go właśnie wyłączyć w
ten sposób tworząc nowy layout taki jaki jest nam potrzebny.
I wybierając, który z nich ma zostać użyte na poziomie taga.
Zmiany wprowadzone w lekcji · 3 min
diff --git a/06/minipedia/layouts/error.vue b/06/minipedia/layouts/error.vue
new file mode 100644
index 0000000..6f91613
--- /dev/null
+++ b/06/minipedia/layouts/error.vue
@@ -0,0 +1,14 @@
+<template>
+ <article class="content">
+ <h1 v-if="error.statusCode === 404">Page not found</h1>
+ <h1 v-else>An error occurred</h1>
+ <NuxtLink to="/">Home page</NuxtLink>
+ </article>
+</template>
+
+<script>
+ export default {
+ props: ['error'],
+ layout: 'error' // you can set a custom layout for the error page
+ }
+</script>
\ No newline at end of file
diff --git a/06/minipedia/layouts/test.vue b/06/minipedia/layouts/test.vue
new file mode 100644
index 0000000..73520d6
--- /dev/null
+++ b/06/minipedia/layouts/test.vue
@@ -0,0 +1,242 @@
+<template>
+ <div class="wrapper">
+ <header class="banner">
+ <ul>
+ <li>
+ <a href="#create-account">
+ Create account
+ </a>
+ </li>
+ <li>
+ <a href="#login">
+ Log in
+ </a>
+ </li>
+ </ul>
+
+ <input type="search" list="autocomplete" class="site-search" placeholder="🔍 Search minipedia">
+ <datalist id="autocomplete">
+ <!-- <option value=""> -->
+ </datalist>
+ </header>
+
+ <Nuxt />
+ </div>
+</template>
+
+<style>
+ h1 {
+ font-size: 2rem;
+ font-weight: normal;
+ margin-top: 0;
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ border-bottom: 0.1rem solid var(--border-color)
+ }
+
+ figure {
+ margin: 0;
+ margin-bottom: 0.5rem;
+ }
+
+ figcaption {
+ white-space: nowrap;
+ font-weight: normal;
+ font-size: 0.9em;
+ }
+
+ h2 {
+ font-weight: normal;
+ }
+
+ .side-navigation h3 {
+ font-weight: normal;
+ font-size: 1em;
+ color: black;
+ opacity: 0.6;
+ }
+
+ body {
+ line-height: 1.6;
+ font-size: 0.9rem;
+ font-family: sans-serif;
+ padding: 0 1rem;
+ }
+
+ :root {
+ --gray: #f6f6f6;
+ --border-color: rgb(162, 169, 177);
+ --light-blue: #A7D7F9;
+ }
+
+ .box {
+ background: var(--gray);
+ padding: 0.1rem;
+ border: 0.1rem solid var(--border-color);
+ }
+
+ .full-bio {
+ max-width: 271px;
+ border-collapse: separate;
+ border-spacing: 0.5rem;
+ float: right;
+ margin-left: 1rem;
+ margin-bottom: 1rem;
+ position: relative;
+ font-size: 0.85rem;
+ }
+
+ .full-bio::before {
+ position: absolute;
+ left: -1.1rem;
+ width: 1rem;
+ height: 100%;
+ background: white;
+ z-index: 1;
+ content: '';
+ display: inline-block;
+ }
+
+ .full-bio [colspan="2"] {
+ text-align: center;
+ }
+
+ .full-bio td {
+ vertical-align: center;
+ }
+
+ .full-bio td:first-child {
+ font-weight: bold;
+ }
+
+ .site-search {
+ font-size: 1rem;
+ padding: 0.2rem;
+ padding-left: 0.5rem;
+ width: 15rem;
+ border-color: var(--border-color);
+ border-style: solid;
+ ;
+ border-radius: 0.5rem;
+ margin-bottom: 0.4rem;
+ font-size: 0.9rem;
+
+ }
+
+ .wrapper {
+ display: grid;
+ grid-template-areas:
+ "sidenav banner banner banner"
+ "sidenav content content content";
+ grid-template-columns: max-content 1fr;
+ grid-template-rows: max-content 1fr;
+ }
+
+ .logo {
+ grid-area: logo;
+ }
+
+ .logo a {
+ text-decoration: none !important;
+ color: black !important;
+ }
+
+ .side-navigation {
+ grid-area: sidenav;
+ padding: 1rem;
+ }
+
+ .content {
+ grid-area: content;
+ background: white;
+ padding: 1rem;
+ border: 0.1rem solid var(--light-blue);
+ }
+
+ a {
+ text-decoration: none;
+ color: #0645ad;
+ }
+
+ ul {
+ padding: 0;
+ margin: 0;
+ list-style-type: none;
+ }
+
+ ol {
+ padding: 0 2ch;
+ }
+
+ body {
+ background: var(--gray);
+ }
+
+ .toc .box {
+ display: inline-block;
+ grid-template-columns: max-content;
+ padding: 0.5rem;
+ }
+
+ .toc h2 {
+ margin: 0 auto;
+ font-weight: bold;
+ border: none;
+ font-size: 1rem;
+ text-align: center;
+ }
+
+
+ .references {
+ column-count: 2;
+ column-gap: 2rem;
+ }
+
+ .references li {
+ margin-bottom: 0.5rem;
+ }
+
+ .banner {
+ margin-left: auto;
+ text-align: right;
+ }
+
+ .banner ul {
+ display: flex;
+ justify-content: flex-end;
+ margin-bottom: 1rem;
+ }
+
+ .banner ul li {
+ margin-left: 1rem;
+ }
+
+ .banner input {
+ display: inline-block;
+ }
+
+ .notice {
+ display: block;
+ margin-bottom: 1.5rem;
+ }
+
+ .logo a {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-bottom: 2rem;
+ text-transform: uppercase;
+ font-family: cursive;
+ }
+
+ .logo img {
+ width: 7rem;
+ margin-bottom: 0.3rem;
+ }
+</style>
diff --git a/06/minipedia/pages/index.vue b/06/minipedia/pages/index.vue
index 48354d1..1adc4ac 100644
--- a/06/minipedia/pages/index.vue
+++ b/06/minipedia/pages/index.vue
@@ -283,7 +283,9 @@
</template>
<script>
-export default {}
+export default {
+ layout: 'default',
+}
</script>
<style>