SQLite
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> SQLite

Xây dựng ứng dụng ưu tiên ngoại tuyến với Node.js và SQLite

"Ngoại tuyến đầu tiên" là một mô hình phát triển ứng dụng trong đó các nhà phát triển đảm bảo rằng chức năng của ứng dụng không bị ảnh hưởng do mất kết nối mạng tạm thời. Các ứng dụng web tiến bộ, giống như các ứng dụng gốc nhưng chạy giống như các ứng dụng web, thường được xây dựng trên mô hình này.

Hướng dẫn này sẽ dạy bạn cách xây dựng ứng dụng đầu tiên ngoại tuyến với Node.js và cơ sở dữ liệu SQLite. Hãy bắt đầu với phần giới thiệu về các ứng dụng web tiến bộ.

Giới thiệu về PWA

Ứng dụng web tiến bộ (PWA) là các ứng dụng web sử dụng các nhân viên dịch vụ, tệp kê khai và các tính năng khác của nền tảng web và cải tiến liên tục để cung cấp cho người dùng trải nghiệm tương đương với các ứng dụng gốc.

PWA đôi khi có thể vượt trội hơn các ứng dụng gốc về mặt hiệu quả. Chúng hoạt động theo yêu cầu và luôn có sẵn mà không tốn bộ nhớ hoặc dữ liệu quý giá của điện thoại thông minh. Người dùng sử dụng ít dữ liệu hơn khi chọn PWA trên phiên bản gốc của cùng một ứng dụng. Họ vẫn có thể lưu PWA vào màn hình chính của họ; nó có thể cài đặt mà không cần tải xuống đầy đủ.

Chúng ta đang xây dựng cái gì?

Để chứng minh sức mạnh của các ứng dụng web tiến bộ, chúng tôi sẽ xây dựng một ứng dụng blog đơn giản.

Người dùng sẽ có thể tương tác với nó giống như các PWA khác, chẳng hạn như Twitter PWA. Hãy bắt tay ngay vào việc đó.

Khởi tạo ứng dụng NodeJs

Hãy làm bẩn bàn tay của chúng ta. Để bắt đầu, chúng tôi sẽ tạo thư mục dự án của mình bằng lệnh dưới đây:

mkdir PWA && cd PWA

Sau đó, chúng tôi sẽ khởi tạo ứng dụng Node.js bằng các lệnh bên dưới:

npm init -y

Lệnh trên tạo một package.json nộp cho ứng dụng.

Tiếp theo, tạo cấu trúc thư mục sau trong thư mục dự án của chúng tôi:

Thiết lập máy chủ Express

Với thiết lập ứng dụng của chúng tôi, hãy cài đặt Express để tạo máy chủ Node.js của chúng tôi bằng lệnh dưới đây:

npm install express

Sau đó, chúng tôi sẽ tạo một vài thư mục và tệp trong thư mục chung:

  • tệp css / style.css
  • tệp js / app.js

Tiếp theo, tạo một index.js tệp trong thư mục gốc của dự án với các đoạn mã sau:

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"));

Trong đoạn mã, chúng tôi nhập express để tạo máy chủ của chúng tôi và đường dẫn mô-đun. Chúng tôi đã định cấu hình ứng dụng của mình để hiển thị các tệp tĩnh của chúng tôi bằng cách sử dụng express.static phương thức này đưa đường dẫn đến thư mục tĩnh (công khai), chúng tôi đã tạo tuyến gốc của ứng dụng và hiển thị index.html tập tin. Sau đó, chúng tôi đã định cấu hình ứng dụng để lắng nghe cổng 8000 .

Kết nối với Cơ sở dữ liệu SQLite

Với thiết lập máy chủ cho ứng dụng của chúng tôi, hãy tạo và kết nối ứng dụng của chúng tôi để lưu thông tin chi tiết về blog của chúng tôi. Để bắt đầu, hãy chạy lệnh bên dưới để cài đặt phụ thuộc sqlite3.

npm install sqlite3

Sau đó, trong điểm nhập index.js , hãy thêm đoạn mã bên dưới để tạo và kết nối ứng dụng với Cơ sở dữ liệu 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.");
  }
});

Tiếp theo, chúng tôi sẽ tạo một danh sách các blog mà chúng tôi sẽ lưu trữ trong cơ sở dữ liệu của mình và hiển thị sau cho phía máy khách bằng đoạn mã bên dưới:

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.",
  },
];

Mỗi bài đăng khối trong ứng dụng của chúng tôi sẽ có một id , tiêu đề , hình đại diện phần giới thiệu lĩnh vực.

Bây giờ, hãy tạo tên bảng cơ sở dữ liệu blog và lưu các chi tiết blog mà chúng tôi vừa tạo ở trên bằng đoạn mã bên dưới:

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}`,
        ]);
      });
    }
  }
);

Trong đoạn mã, chúng tôi đã tạo một bảng blog bằng cách sử dụng db.run. db.run phương thức nhận một truy vấn SQL làm tham số, sau đó chúng tôi lặp qua mảng blog của mình và chèn chúng vào bảng blog mà chúng tôi vừa tạo bằng cách sử dụng hàm bản đồ js.

Xem Bản ghi Cơ sở dữ liệu

Bây giờ chúng ta hãy xem các bản ghi chúng ta vừa tạo bằng Arctype. Để xem các bản ghi trong cơ sở dữ liệu SQLite của bạn bằng Arctype, hãy làm theo các bước bên dưới:

  • Cài đặt Arctype
  • Chạy Ứng dụng với node index.js để tạo cơ sở dữ liệu
  • Khởi chạy Arctype và nhấp vào tab SQLite

  • Nhấp vào Chọn tệp SQLite và tìm db.sqlite tệp được tạo khi bạn chạy máy chủ.
  • Bạn sẽ thấy bảng blog và các bản ghi chúng tôi tạo như được hiển thị trong ảnh chụp màn hình bên dưới:

Hiển thị trang

Tại thời điểm này, chúng tôi đã kết nối ứng dụng với cơ sở dữ liệu SQLite và cũng đã chèn một số bản ghi trong cơ sở dữ liệu. Bây giờ, hãy mở index.html và thêm các đoạn mã sau:

<!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>

Chúng tôi đã tạo một đánh dấu đơn giản với các liên kết đến tệp kê khai của chúng tôi trong tệp ở trên, mà chúng tôi sẽ tạo trong phần tiếp theo, kiểu app.js các tập tin.

Sau đó, chúng tôi sẽ tạo một blog trong index.js của chúng tôi để trả lại các blog về phía máy khách.

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

Trong public / js / app.js của chúng tôi tệp, chúng tôi sẽ gửi một yêu cầu nhận đến điểm cuối blog để nhận các blog từ chương trình phụ trợ của chúng tôi. Sau đó, chúng tôi duyệt qua các blog, nhắm mục tiêu vùng chứa lớp và hiển thị chúng.

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);
  });

Chúng tôi cũng sẽ thêm một số kiểu vào ứng dụng của mình trong public / css / style.css với đoạn mã bên dưới:

* {
  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;
}

Bây giờ, hãy mở package.json tập tin và thêm tập lệnh bắt đầu.

"start": "node index.js"

Tại thời điểm này, chúng tôi đã thiết lập ứng dụng của mình. Nhưng chúng tôi không thể chạy ứng dụng của mình khi máy chủ không chạy hoặc khi không có kết nối mạng để sản xuất. Hãy thiết lập điều đó trong phần tiếp theo.

Tối ưu hóa ứng dụng

Chúng ta cần làm cho ứng dụng của mình tương thích với mọi kích thước màn hình. Chúng tôi cũng sẽ thêm màu chủ đề bằng cách thêm đánh dấu bên dưới vào phần đầu của index.html của chúng tôi tập tin.

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

Tạo tệp kê khai

Chúng tôi cần mô tả ứng dụng của mình và ứng dụng sẽ hoạt động như thế nào khi được cài đặt trên thiết bị của người dùng. Chúng tôi có thể làm điều này bằng cách tạo một tệp kê khai.

Tạo tệp kê khai tệp trong thư mục gốc của dự án và thêm các cấu hình sau:

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

Trong tệp kê khai của mình, chúng tôi đã xác định các cấu hình sau:

  • tên :Điều này xác định tên hiển thị của ứng dụng.
  • short_name :Điều này xác định tên sẽ hiển thị dưới biểu tượng ứng dụng khi được cài đặt.
  • start_url :Điều này cho trình duyệt biết URL gốc của ứng dụng.
  • hiển thị :Điều này cho trình duyệt biết cách hiển thị ứng dụng.
  • background_color: Điều này xác định màu nền của ứng dụng khi được cài đặt.
  • theme_color: Điều này xác định màu sắc của thanh trạng thái.
  • định hướng: Điều này xác định hướng sử dụng trong khi hiển thị ứng dụng.
  • biểu tượng: Điều này xác định các biểu tượng hoặc hình ảnh có kích thước khác nhau sẽ được sử dụng làm biểu tượng trang chủ ứng dụng của chúng tôi.

Tạo biểu tượng màn hình chính theo cách thủ công có thể là một nhiệm vụ rất phức tạp, nhưng đừng lo lắng. Chúng tôi sẽ tận dụng mô-đun của bên thứ ba được gọi là pwa-asset-maker để tạo các biểu tượng có kích thước khác nhau từ biểu tượng ứng dụng chính của chúng tôi bên trong thư mục công khai bằng lệnh bên dưới:

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

Lệnh trên sẽ tạo biểu tượng thư mục bên trong thư mục chung với nhiều biểu tượng cho ứng dụng của chúng tôi, cùng với một số JSON trên thiết bị đầu cuối mà chúng tôi sẽ dán vào mảng biểu tượng của mình trong tệp kê khai.

Mảng biểu tượng trong tệp kê khai của chúng tôi sẽ trông giống như sau:

"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"
    }
  ]

Ngoài ra, lệnh tạo ra các liên kết đánh dấu đến các biểu tượng được tạo.

Sao chép và dán đánh dấu vào phần đầu của đánh dấu trong public / index.html tệp.

Nhân viên Dịch vụ Thiết lập

Với tệp kê khai của chúng tôi đã tạo, hãy thiết lập các nhân viên dịch vụ. Service worker là một đoạn mã JavaScript mà trình duyệt của bạn chạy ở chế độ nền trong một chuỗi riêng biệt để xử lý bộ đệm ẩn cho các nội dung và dữ liệu mà bạn lưu cho các yêu cầu trong tương lai để bật hỗ trợ ngoại tuyến cho ứng dụng của bạn.

Vì vậy, hãy tạo một blogger.serviceWorker.js gửi ở công khai thư mục. Đối với service worker, có nhiều sự kiện (đẩy, kích hoạt, cài đặt, tìm nạp, nhắn tin, đồng bộ hóa), nhưng đối với phần trình diễn trong hướng dẫn này, chúng tôi sẽ đề cập đến cài đặt, kích hoạt, tìm nạp sự kiện. Trước đó, chúng ta cần tạo một mảng để lưu trữ tất cả các tài sản mà chúng ta đã sử dụng trong ứng dụng của mình.

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

Sau đó, chúng tôi sẽ lắng nghe cài đặt sự kiện để đăng ký và lưu các tệp tĩnh của chúng tôi vào bộ nhớ cache của trình duyệt. Quá trình này mất một thời gian để hoàn thành. Để bỏ qua quá trình chờ đợi, chúng tôi sẽ sử dụng viaWaiting ().

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);
      })
  );
});
...

Sau đó, chúng ta cần xóa bộ nhớ cache để xóa nội dung cũ bất cứ khi nào service worker được cập nhật. Đối với điều đó, chúng tôi sẽ lắng nghe kích hoạt đoạn mã bên dưới:

...
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())
  );
});

Trong đoạn mã trên, chúng tôi sử dụng waitUntil trên service worker. Phương pháp này đợi hành động kết thúc và sau đó chúng tôi kiểm tra xem nội dung chúng tôi đang cố gắng xóa có phải là nội dung của ứng dụng hiện tại của chúng tôi hay không trước khi xóa chúng.

Tiếp theo, chúng tôi cần các tệp được lưu trữ trong bộ nhớ cache của chúng tôi để sử dụng chúng.

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

Khi một yêu cầu được thực hiện trên trang, PWA sẽ kiểm tra bộ nhớ cache của chúng tôi và đọc từ đó nếu có dữ liệu trong bộ nhớ cache chứ không phải vào mạng. Sau đó, sử dụng responseWith , chúng tôi ghi đè mặc định của trình duyệt và làm cho sự kiện của chúng tôi trả về một lời hứa. Khi bộ đệm hoàn tất, chúng ta có thể trả lại bộ đệm tương ứng với evt.request. Khi bộ nhớ đệm đã sẵn sàng, chúng tôi có thể trả lại bộ đệm phù hợp với evt.request.

Chúng tôi đã thiết lập thành công nhân viên dịch vụ của mình. Bây giờ, hãy làm cho nó có sẵn trong ứng dụng của chúng tôi.

Đăng ký Nhân viên Dịch vụ

Bây giờ, hãy đăng ký nhân viên dịch vụ của chúng tôi trong public / js / app.js của chúng tôi tệp với đoạn mã bên dưới:

...
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));
  });
}

Tại đây, chúng tôi kiểm tra xem trình duyệt của ứng dụng của chúng tôi có hỗ trợ service worker (tất nhiên, không phải tất cả các trình duyệt đều hỗ trợ service worker), sau đó đăng ký tệp service worker của chúng tôi.

Bây giờ hãy chạy ứng dụng bằng lệnh dưới đây:

npm start

Truy cập localhost:8000 trong trình duyệt của bạn để truy cập ứng dụng.

Google Lighthouse Check

Bây giờ, hãy kiểm tra xem chúng tôi có thiết lập PWA đúng cách hay không bằng cách sử dụng kiểm tra Google Lighthouse. Nhấp chuột phải vào trình duyệt của bạn và chọn "kiểm tra". Trên các tab kiểm tra, chọn ngọn hải đăng và nhấp vào tạo báo cáo. Nếu mọi thứ diễn ra tốt đẹp với ứng dụng của bạn, bạn sẽ thấy kết quả như trong ảnh chụp màn hình bên dưới:

Chúng tôi đã tạo thành công ứng dụng đầu tiên của mình. Bạn cũng có thể dừng máy chủ để kiểm tra ứng dụng ở chế độ ngoại tuyến.

Kết luận

Ứng dụng web tiến bộ (PWA) sử dụng các API hiện đại để cung cấp các khả năng nâng cao, độ tin cậy và khả năng cài đặt với một cơ sở mã duy nhất. Chúng cho phép người dùng cuối sử dụng ứng dụng của bạn bất kể họ có kết nối internet hay không. Bạn có thể thoải mái phân nhánh kho lưu trữ và thêm các tính năng bổ sung vào dự án. Chúc bạn thành công!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQLite Listview onclick bộ lọc db để mở dẫn đến hoạt động mới

  2. SQLite JSON_EACH ()

  3. Có thực sự cần thiết để tạo bảng SQLite mỗi khi ứng dụng khởi động?

  4. Phòng Android:Làm thế nào để di chuyển đổi tên cột?

  5. Làm thế nào để tạo bảng bằng cơ sở dữ liệu sqlite trong Android?