SQLite
 sql >> Baza danych >  >> RDS >> SQLite

Budowanie aplikacji offline z wykorzystaniem Node.js i SQLite

„Najpierw offline” to paradygmat tworzenia aplikacji, w którym programiści zapewniają, że na funkcjonalność aplikacji nie ma wpływu chwilowa utrata łączności sieciowej. Progresywne aplikacje internetowe, które przypominają aplikacje natywne, ale działają jak aplikacje internetowe, są często budowane na tym paradygmacie.

Ten samouczek nauczy Cię, jak zbudować najpierw aplikację offline z Node.js i bazą danych SQLite. Zacznijmy od wprowadzenia do progresywnych aplikacji internetowych.

Wprowadzenie do PWA

Progresywne aplikacje internetowe (PWA) to aplikacje internetowe korzystające z pracowników usług, manifestów i innych funkcji platformy internetowej oraz progresywnego ulepszania, aby zapewnić użytkownikom wrażenia porównywalne z aplikacjami natywnymi.

Programy PWA mogą czasami przewyższać aplikacje natywne pod względem wydajności. Działają na żądanie i są zawsze dostępne, nie zużywając cennej pamięci smartfona ani danych. Użytkownicy zużywają mniej danych, wybierając PWA zamiast natywnej wersji tej samej aplikacji. Nadal mogą zapisać PWA na swoim ekranie głównym; można go zainstalować bez konieczności pełnego pobierania.

Co budujemy?

Aby zademonstrować moc progresywnych aplikacji internetowych, zbudujemy prostą aplikację blogową.

Użytkownik będzie mógł wchodzić z nim w interakcję jak z innymi PWA, takimi jak Twitter PWA. Przejdźmy od razu.

Zainicjuj aplikację NodeJs

Ubrudźmy sobie ręce. Aby rozpocząć, utworzymy folder naszego projektu za pomocą poniższego polecenia:

mkdir PWA && cd PWA

Następnie zainicjujemy aplikację Node.js za pomocą poniższych poleceń:

npm init -y

Powyższe polecenie tworzy package.json plik dla aplikacji.

Następnie utwórz następującą strukturę folderów w naszym folderze projektu:

Skonfiguruj serwer Express

Po zainstalowaniu naszej aplikacji zainstalujmy Express, aby utworzyć nasz serwer Node.js za pomocą poniższego polecenia:

npm install express

Następnie utworzymy kilka folderów i plików w folderze publicznym:

  • plik css/style.css
  • plik js/app.js

Następnie utwórz plik index.js plik w katalogu głównym projektu z następującymi fragmentami kodu poniżej:

const express = require("express");
const path = require("path");
const app = express();
app.use(express.static(path.join(__dirname, "public")));

app.get("/", function (req, res) {
  res.sendFile(path.join(__dirname, "public/index.html"));
});
app.listen(8000, () => console.log("Server is running on Port 8000"));

We fragmencie kodu importujemy ekspres stworzyć nasz serwer i ścieżkę moduł. Skonfigurowaliśmy naszą aplikację do renderowania naszych plików statycznych przy użyciu express.static metody, która pobiera ścieżkę do folderu statycznego (public), utworzyliśmy ścieżkę główną naszej aplikacji i wyrenderowaliśmy index.html plik. Następnie skonfigurowaliśmy aplikację do nasłuchiwania na porcie 8000 .

Połącz z bazą danych SQLite

Po skonfigurowaniu serwera dla naszej aplikacji utwórzmy i połączmy naszą aplikację, aby zapisać szczegóły naszego bloga. Aby rozpocząć, uruchom poniższe polecenie, aby zainstalować zależność sqlite3.

npm install sqlite3

Następnie w punkcie wejścia index.js pliku, dodaj poniższy fragment kodu, aby utworzyć i połączyć aplikację z bazą danych SQLite.

const db = new sqlite3.Database("db.sqlite", (err) => {
  if (err) {
    // Cannot open database
    console.error(err.message);
    throw err;
  } else {
    console.log("Connected to the SQLite database.");
  }
});

Następnie utworzymy listę blogów, które będziemy przechowywać w naszej bazie danych i renderować później po stronie klienta za pomocą poniższego fragmentu kodu:

let blogs = [
  {
    id: "1",
    title: "How To Build A RESTAPI With Javascript",
    avatar: "images/coffee2.jpg",
    intro: "iste odio beatae voluptas dolor praesentium illo facere optio nobis magni, aspernatur quas.",
  },
  {
    id: "2",
    title: "How to Build an Offline-First Application with Node.js,"
    avatar: "images/coffee2.jpg",
"iste odio beatae voluptas dolor praesentium illo facere optio nobis magni, aspernatur quas.",
  },
  {
    id: "3",
    title: "Building a Trello Clone with React DnD",
    avatar: "images/coffee2.jpg",
    intro: "iste odio beatae voluptas dolor praesentium illo facere optio nobis magni, aspernatur quas.",
  },
];

Każdy blokowy post w naszej aplikacji będzie miał id , tytuł , awatar i wstęp pola.

Teraz utwórz tabelę bazy danych o nazwie blogi i zapisz szczegóły bloga, które właśnie utworzyliśmy powyżej, z fragmentem kodu poniżej:

db.run(
  `CREATE TABLE blog (id INTEGER PRIMARY KEY AUTOINCREMENT, title text,avatar text,intro text)`,
  (err) => {
    if (err) {
      // console.log(err)
      // Table already created
    } else {
      // Table just created, creating some rows
      var insert = "INSERT INTO blogs (title, avatar, intro) VALUES (?,?,?)";
      blogs.map((blog) => {
        db.run(insert, [
          `${blog.title}`,
          `${blog.avatar}`,
          `${blog.intro}`,
        ]);
      });
    }
  }
);

We fragmencie kodu utworzyliśmy tabelę blogi za pomocą db.run. db.run Metoda przyjmuje zapytanie SQL jako parametr, a następnie przeglądamy naszą tablicę blogów w pętli i wstawiamy je do tabeli blogów, którą właśnie utworzyliśmy za pomocą funkcji mapy js.

Wyświetl rekordy bazy danych

Teraz przyjrzyjmy się rekordom, które właśnie utworzyliśmy za pomocą Arctype. Aby wyświetlić rekordy w bazie danych SQLite za pomocą Arctype, wykonaj następujące czynności:

  • Zainstaluj Arctype
  • Uruchom aplikację z node index.js stworzyć bazę danych
  • Uruchom Arctype i kliknij kartę SQLite

  • Kliknij Wybierz plik SQLite i znajdź db.sqlite plik wygenerowany po uruchomieniu serwera.
  • Powinieneś zobaczyć tabelę blogów i rekordy, które tworzymy, jak pokazano na poniższym zrzucie ekranu:

Renderuj stronę

W tym momencie połączyliśmy aplikację z bazą danych SQLite, a także wstawiliśmy do niej kilka rekordów. Teraz otwórz index.html plik i dodaj następujące fragmenty kodu poniżej:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="css/style.css" />
    <title>Blogger</title>
    <link rel="manifest" href="manifest" />
  </head>
  <body>
    <section>
      <nav>
        <h1>Blogger</h1>
        <ul>
          <li>Home</li>
           <li class="active">Blog</li>
        </ul>
      </nav>
      <div class="container"></div>
    </section>
    <script src="js/app.js"></script>
  </body>
</html>

Stworzyliśmy prosty znacznik z linkami do naszego manifestu w powyższym pliku, który będziemy tworzyć w następnej sekcji, style i app.js akta.

Następnie utworzymy blogi trasa w naszym index.js plik, aby zwrócić blogi po stronie klienta.

...
app.get("/blogs", (req, res) => {
  res.status(200).json({
    blogs,
  });
});
...

W naszym public/js/app.js pliku, wyślemy żądanie pobrania do punktu końcowego bloga, aby pobrać blogi z naszego zaplecza. Następnie przeglądamy blogi, celując w kontener klasę i wyświetlaj je.

let result = "";
fetch("http://localhost:8000/blogs")
  .then((res) => res.json())
   .then(({ rows } = data) => {
    rows.forEach(({ title, avatar, intro } = rows) => {
      result += `
       <div class="card">
            <img class="card-avatar" src="/${avatar}"/>
            <h1 class="card-title">${title}</h1>
            <p class="intro">${intro}</p>
            <a class="card-link" href="#">Read</a>
        </div>
       `;
    });
    document.querySelector(".container").innerHTML = result;
  })
  .catch((e) => {
    console.log(e);
  });

Dodamy również stylizację do naszej aplikacji w pliku public/css/style.css z fragmentem kodu poniżej:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  background: #fdfdfd;
  font-size: 1rem;
}
section {
  max-width: 900px;
  margin: auto;
  padding: 0.5rem;
  text-align: center;
}
nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
ul {
  list-style: none;
  display: flex;
}
li {
  margin-right: 1rem;
}
h1 {
  color: #0e9c95;
  margin-bottom: 0.5rem;
}
.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  grid-gap: 1rem;
  justify-content: center;
  align-items: center;
  margin: auto;
  padding: 1rem 0;
}
.card {
  display: flex;
  align-items: center;
  flex-direction: column;
  width: 15rem auto;
  background: #fff;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19), 0 6px 6px rgba(0, 0, 0, 0.23);
  border-radius: 10px;
  margin: auto;
  overflow: hidden;
}
.card-avatar {
  width: 100%;
  height: 10rem;
  object-fit: cover;
}
.card-title {
  color: #222;
  font-weight: 700;
  text-transform: capitalize;
  font-size: 1.1rem;
  margin-top: 0.5rem;
}
.card-link {
  text-decoration: none;
  background: #16a0d6e7;
  color: #fff;
  padding: 0.3rem 1rem;
  border-radius: 20px;
  margin: 10px;
}
.intro {
  color: #c2c5c5;
  padding: 10px;
}
.active {
  color: #16a0d6e7;
}

Teraz otwórz package.json plik i dodaj skrypt startowy.

"start": "node index.js"

W tym momencie skonfigurowaliśmy naszą aplikację. Ale nie możemy uruchomić naszej aplikacji, gdy serwer nie działa lub gdy nie ma połączenia sieciowego do produkcji. Ustawmy to w następnej sekcji.

Optymalizacja aplikacji

Musimy sprawić, by nasza aplikacja była kompatybilna ze wszystkimi rozmiarami ekranu. Dodamy również kolor motywu, dodając znacznik poniżej w sekcji head naszego index.html plik.

<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#16a0d6e7"/>

Utwórz manifest

Musimy opisać naszą aplikację i jak powinna się zachowywać po zainstalowaniu na urządzeniu użytkownika. Możemy to zrobić, tworząc manifest.

Utwórz manifest plik w katalogu głównym projektu i dodaj następujące konfiguracje:

{
    "name": "Blogger"
    "short_name": "Blogger"
    "start_url": "/",
    "display": "standalone",
    "background_color": "#0e9c95",
    "theme_color": "#16a0d6e7",
    "orientation": "portrait",
    "icons": []
}

W naszym manifeście zdefiniowaliśmy następujące konfiguracje:

  • nazwa :Definiuje wyświetlaną nazwę aplikacji.
  • short_name :Określa nazwę, która będzie wyświetlana pod ikoną aplikacji po zainstalowaniu.
  • start_url :To informuje przeglądarkę o głównym adresie URL aplikacji.
  • wyświetlacz :To mówi przeglądarce, jak wyświetlić aplikację.
  • kolor_tła: To określa kolor tła aplikacji po jej zainstalowaniu.
  • theme_color: To określa kolor paska stanu.
  • orientacja: To określa orientację do użycia podczas wyświetlania aplikacji.
  • ikony: Definiuje to ikony lub obrazy o różnych rozmiarach, które mają być używane jako ikony główne naszej aplikacji.

Ręczne tworzenie ikon na ekranie głównym może być bardzo skomplikowanym zadaniem, ale nie martw się. Skorzystamy z modułu innej firmy, znanego jako pwa-asset-generator, aby wygenerować ikony o różnych rozmiarach z naszej głównej ikony aplikacji w katalogu publicznym za pomocą poniższego polecenia:

#change directory to the public folder
cd public
#generate icons
npx pwa-asset-generator logo.png icons

Powyższe polecenie utworzy ikony folder wewnątrz folderu publicznego z wieloma ikonami naszej aplikacji, wraz z kilkoma JSON na terminalu, który wkleimy do naszej tablicy ikon w manifeście.

Tablica ikon w naszym manifeście powinna wyglądać tak:

"icons": [
    {
      "src": "public/icons/manifest-icon-192.maskable.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "public/icons/manifest-icon-192.maskable.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "maskable"
    },
    {
      "src": "public/icons/manifest-icon-512.maskable.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "public/icons/manifest-icon-512.maskable.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]

Ponadto polecenie wygenerowało łącza znaczników do wygenerowanych ikon.

Skopiuj i wklej znacznik do sekcji head znacznika w public/index.html plik.

Konfiguracja pracowników usług

Po utworzeniu naszego manifestu skonfigurujmy pracowników serwisu. Service Worker to fragment kodu JavaScript, który przeglądarka uruchamia w tle w osobnym wątku, aby obsłużyć pamięć podręczną zasobów i danych, które zapisujesz na potrzeby przyszłych żądań, aby włączyć obsługę aplikacji w trybie offline.

Utwórz więc blogger.serviceWorker.js plik w publicznym teczka. W przypadku pracownika serwisu istnieje wiele zdarzeń (wypychanie, aktywowanie, instalowanie, pobieranie, wysyłanie wiadomości, synchronizowanie), ale w przypadku demonstracji w tym samouczku omówimy instalację, aktywację i pobierz wydarzenia. Wcześniej musimy stworzyć tablicę do przechowywania wszystkich zasobów, których użyliśmy w naszej aplikacji.

const assets = [
  "/",
  "css/style.css",
  "js/app.js",
  "/images/blog1.jpg",
  "/images/blog2.jpg",
  "/images/blog3.jpg,"
];

Następnie wysłuchamy instalacji zdarzenie do zarejestrowania i zapisania naszych plików statycznych w pamięci podręcznej przeglądarki. Ten proces zajmuje trochę czasu. Aby pominąć oczekiwanie, użyjemy skipWaiting().

const BLOGGER_ASSETS = "blogger-assets";
self.addEventListener("install", (installEvt) => {
  installEvt.waitUntil(
    caches
      .open(BLOGGER_ASSETS)
      .then((cache) => {
        cache.addAll(assets);
      })
      .then(self.skipWaiting())
      .catch((e) => {
        console.log(e);
      })
  );
});
...

Następnie musimy wyczyścić pamięć podręczną, aby usunąć stare zasoby po każdej aktualizacji Service Workera. W tym celu posłuchamy aktywacji fragment kodu poniżej:

...
self.addEventListener("activate", function (evt) {
  evt.waitUntil(
    caches
      .keys()
      .then((keysList) => {
        return Promise.all(
          keysList.map((key) => {
            if (key === BLOGGER_ASSETS) {
              console.log(`Removed old cache from ${key}`);
              return caches.delete(key);
            }
          })
        );
      })
      .then(() => self.clients.claim())
  );
});

W powyższym fragmencie kodu używamy waitUntil metoda na pracownika serwisu. Ta metoda czeka na zakończenie akcji, a następnie sprawdzamy, czy zasoby, które próbujemy wyczyścić, są zasobami naszej bieżącej aplikacji, zanim je usuniemy.

Następnie potrzebujemy plików przechowywanych w naszej pamięci podręcznej, aby z nich korzystać.

self.addEventListener("fetch", function (evt) {
  evt.respondWith(
    fetch(evt.request).catch(() => {
      return caches.open(BLOGGER_ASSETS).then((cache) => {
        return cache.match(evt.request);
      });
    })
  );
})

Gdy na stronie pojawi się żądanie, PWA sprawdzi naszą pamięć podręczną i odczyta z niej, czy w pamięci podręcznej znajdują się dane, zamiast iść do sieci. Następnie za pomocą respondWith metody, nadpisujemy domyślne ustawienia przeglądarki i sprawimy, że nasze zdarzenie zwróci obietnicę. Gdy pamięć podręczna jest kompletna, możemy zwrócić pamięć podręczną odpowiadającą evt.request. Gdy pamięć podręczna jest gotowa, możemy zwrócić pamięć podręczną, która pasuje do evt.request.

Pomyślnie uruchomiliśmy naszego pracownika serwisu. Teraz udostępnijmy to w naszej aplikacji.

Zarejestruj pracownika serwisu

Teraz zarejestrujmy naszego pracownika serwisu w naszym public/js/app.js plik z fragmentem kodu poniżej:

...
if ("serviceWorker" in navigator) {
  window.addEventListener("load", function () {
    navigator.serviceWorker
      .register("/blogger.serviceWorker.js")
      .then((res) => console.log("service worker registered"))
      .catch((err) => console.log("service worker not registered", err));
  });
}

Tutaj sprawdzamy, czy przeglądarka naszej aplikacji obsługuje Service Workerów (oczywiście nie wszystkie przeglądarki obsługują Service Workerów), a następnie rejestrujemy nasz plik Service Worker.

Teraz uruchom aplikację za pomocą poniższego polecenia:

npm start

Przejdź do localhost:8000 w przeglądarce, aby uzyskać dostęp do aplikacji.

Google Lighthouse Check

Sprawdźmy teraz, czy poprawnie ustawiliśmy nasze PWA za pomocą testu Google Lighthouse. Kliknij przeglądarkę prawym przyciskiem myszy i wybierz „Sprawdź”. Na zakładkach inspekcji wybierz latarnię morską i kliknij generuj raport. Jeśli wszystko poszło dobrze z twoją aplikacją, powinieneś zobaczyć dane wyjściowe takie jak na poniższym zrzucie ekranu:

Z powodzeniem stworzyliśmy naszą pierwszą aplikację. Możesz także zatrzymać serwer, aby przetestować aplikację w trybie offline.

Wniosek

Progresywne aplikacje internetowe (PWA) korzystają z nowoczesnych interfejsów API, aby zapewnić rozszerzone możliwości, niezawodność i możliwość instalacji za pomocą jednej bazy kodu. Umożliwiają one użytkownikowi końcowemu korzystanie z aplikacji niezależnie od tego, czy ma połączenie z Internetem. Powinieneś swobodnie rozwidlić repozytorium i dodać dodatkowe funkcje do projektu. Powodzenia!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak pobrać dane z bazy danych i wyświetlić je jako ListView?

  2. Jak działa funkcja DateTime() w SQLite

  3. jak pobrać pierwszy lub (dowolny) element z listy LiveData w architekturze Android MVVM?

  4. SQLite Node.js

  5. Jak Group_Concat() działa w SQLite