NEXT.js PWA Fungsionalitas offline dengan pekerja layanan, tidak ada paket tambahan – Beragampengetahuan
2025-08-09 | 5 menit untuk dibaca
Dalam tutorial ini, kami akan menambahkan dukungan offline di Next.js PWA, dan tidak ada paket tambahan, jadi tidak ada PWA berikutnya, tidak ada jalur kantor langkah berikutnya, tidak ada Swiss, hanya TS biasa.
Contents
Mengapa Anda melakukan ini
Pertama, karena ini bukan tugas yang sangat kompleks, ini adalah kesempatan bagus untuk bermain dengan staf layanan dan cache, berharap untuk menghilangkan perasaan luar biasa yang biasanya terjadi ketika berbicara tentang topik.
Kedua, Anda akan memilikinya. Ini berarti bahwa begitu Anda memahami beberapa konsep kunci, Anda harus dapat sepenuhnya menyesuaikan semua detail yang Anda inginkan.
Tetapi yang paling penting, Anda dapat mengurangi permukaan pengemasan permukaan aplikasi, meningkatkan stabilitas dan mengurangi api penutup.
Apa yang perlu Anda ketahui tentang staf layanan
Staf layanan membuat banyak orang takut, jadi mari kita coba dengan cepat.
Pekerja layanan dapat ditemukan di 4 negara yang mungkin: download,,,,, install,,,,, waitingDan activate.
Ini seperti ketika Anda memiliki teman yang makan malam dan perlu memasak: Anda akan membeli beberapa bahan makanan (unduh), Anda akan memasak (menginstal), dan Anda akan menyajikan hidangan untuk teman -teman Anda sehingga mereka dapat menikmatinya (aktifkan).
Tunggu, yah, ini adalah semua waktu antara menyelesaikan memasak dan teman -teman Anda membeli bahan makanan.
Sekarang, ada fungsi waiting Dan activate Ditelepon skipWaiting.
memahami skipWaiting Saat Anda punya teman untuk makan malam, mari kita kembali ke sini.
Biasanya, Anda akan menunggu teman Anda menyelesaikan hidangan sebelum mengambil yang berikutnya. Bagus sekali, skipWaiting Saat itulah Anda kasar dan paksa teman Anda untuk makan hidangan berikutnya karena Anda terlambat untuk film.
Hindari Trauma Pekerja Layanan: Juga Dikenal Mengapa Pekerja Layanan Saya Tidak Aktif
Setelah menggunakan pekerja layanan baru, Anda mungkin melihatnya diinstal dan berpikir, “Saya akan memuat ulang halaman dan kemudian membuatnya bekerja”, tetapi kemudian tidak berhasil dan Anda mulai menangis.
Sekarang, ingat ini:
- Anda harus menutup semua Gunakan tag aplikasi Anda, dan bahkan lebih baik, tutup browser Anda
- Segarkan saja (
ctrl + r) Tidak bisa melakukannya, silakan gunakan penyegaran kerasctrl + shift + r
Asumsi dan rencana
Kami akan menggunakan expript dan output: "export", Ini berarti kami tidak akan menggunakan sisi server atau server serupa.
Saya harus memiliki file statis lama.
Kemudian, kami akan menggunakan a Cache pertama Kebijakan, yang berarti bahwa ketika diinstal, kami akan menyimpan file dan mengaktifkannya ketika kami menggunakan file yang di -cache alih -alih mendapatkannya dari server.
Juga, kami ingin menggunakan beberapa jenis API untuk data, yang berarti bahwa ketika kami di -cache static file, kami ingin dapat mencapai jaringan untuk sisanya.
Poin terakhir adalah bahwa kami akan menggunakan nomor versi package.jsonsehingga ketika pekerja layanan aktif, kami akan menghapus cache lama.
Untuk mendapatkan versi paket dan mendapatkan daftar aplikasi kami, kami akan membuat beberapa skrip khusus.
Mari kita mulai dengan perancah dan boiler selanjutnya
# scaffold
npx create-next-app@latest pwa-offline
cd pwa-offline
echo "v22.14.0" > .nvmrc
Kami menggunakan Node.js nvm Jadi tidak ada yang bingung tentang versi simpul yang kami gunakan, kami create-next-app.
Untuk membuat file statis, kami akan menambahkan output: 'export' ada next.config.js.
// next.config.js
import type NextConfig from "next";
const nextConfig: NextConfig =
output: 'export',
distDir: 'dist',
;
export default nextConfig;
Setelah ini, Anda harus memiliki sesuatu seperti ini.
.
├── README.md
├── eslint.config.mjs
├── next-env.d.ts
├── next.config.ts
├── package-lock.json
├── package.json
├── public
│ ├── file.svg
│ ├── globe.svg
│ ├── next.svg
│ ├── vercel.svg
│ └── window.svg
├── src
│ └── app
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ ├── page.module.css
│ └── page.tsx
└── tsconfig.json
Pekerja Layanan
Jadi, untuk pekerja layanan, rencananya sederhana: kami akan meminta pekerja layanan melemahkan daftar file dalam versi aplikasi. Untuk menyatukan semuanya, kami akan menggunakan beberapa skrip khusus, tsc Dan webpack Meludahkan service-worker.js.
// version.ts, app-file-list.ts will be generated by a script
version.ts |
service-worker.ts |-> service-worker.js
app-file-list.ts |
Mari kita mulai membuat perancah.
mkdir src/sw
touch src/sw/service-worker.ts
touch src/sw/app-file-list.ts
touch src/sw/version.ts
Mari kita gunakan skrip untuk menghasilkan version.ts,,,,, app-file-list.tskami menyebutnya generate.js
mkdir scripts
touch scripts/generate.js
Di sana, mari kita miliki
// generate.js
const fs = require('fs');
const path = require('path');
/*
VERSION
1 - get package
2 - export a constant VERSION
*/
const pkg = require('../package.json');
fs.writeFileSync(
'./src/sw/version.ts',
`export const VERSION = '$pkg.version';\n`
);
/*
APP FILE LIST
1 - get file list
2 - export a constant APP_FILE_LIST
*/
const folderPath = './dist';
function getAllFilesInDir(dir)
const entries = fs.readdirSync(dir, withFileTypes: true );
return entries
.flatMap((entry) =>
const fullPath = path.join(dir, entry.name);
return entry.isDirectory()
? getAllFilesInDir(fullPath)
: [fullPath];
);
fs.writeFileSync(
'./src/sw/app-file-list.ts',
`export const APP_FILE_LIST = [
"/",
$getAllFilesInDir(folderPath).map(i => "'" + i.slice(4) + "'").join(", \n")
];`
);
Jika Anda berlari sekarang node scripts/generate.js Anda harus melakukannya.
// version.ts
export const VERSION = '0.3.0';
// app-file-list.ts
export const APP_FILE_LIST = [
"/",
'/404.html',
'/_next/static/OQvQ0DovXF5ZWbrYv4Ncy/_buildManifest.js',
'/_next/static/OQvQ0DovXF5ZWbrYv4Ncy/_ssgManifest.js',
'/_next/static/chunks/4bd1b696-daa26928ff622cec.js',
'/_next/static/chunks/684-703ae9b085b41bfc.js',
'/_next/static/chunks/app/_not-found/page-88c6d7d182d9074a.js',
'/_next/static/chunks/app/layout-ca036fe7ce1c23fd.js',
'/_next/static/chunks/app/page-c3804bb37ebec7f8.js',
'/_next/static/chunks/app/template-eca6ee34e977c582.js',
'/_next/static/chunks/framework-f593a28cde54158e.js',
'/_next/static/chunks/main-app-5054e05586ea1599.js',
'/_next/static/chunks/main-c09f9dcdf4e52331.js',
'/_next/static/chunks/pages/_app-da15c11dea942c36.js',
'/_next/static/chunks/pages/_error-cc3f077a18ea1793.js',
'/_next/static/chunks/polyfills-42372ed130431b0a.js',
'/_next/static/chunks/webpack-8e1805b62d936603.js',
'/_next/static/css/34fc136d66718394.css',
'/_next/static/css/76338d74addccb7a.css',
'/_next/static/media/569ce4b8f30dc480-s.p.woff2',
'/_next/static/media/747892c23ea88013-s.woff2',
'/_next/static/media/8d697b304b401681-s.woff2',
'/_next/static/media/93f479601ee12b01-s.p.woff2',
'/_next/static/media/9610d9e46709d722-s.woff2',
'/_next/static/media/ba015fad6dcf6784-s.woff2',
'/favicon.ico',
'/file.svg',
'/globe.svg',
'/index.html',
'/index.txt',
'/next.svg',
'/vercel.svg',
'/window.svg'
];
Sekarang kita punya app-file-list.ts Dan version.ts Kita bisa fokus service-worker.ts.
// service-worker.ts
import VERSION from "./version";
import APP_FILE_LIST from "./app-file-list";
const sw: ServiceWorkerGlobalScope = self as unknown as ServiceWorkerGlobalScope;
/*
SW: INSTALL
1. open the cache scoped by version number
2. save the files in the list
*/
async function onInstall()
console.info("SW : Install : " + VERSION);
const cache = await caches.open(VERSION);
return cache.addAll(APP_FILE_LIST);
;
/*
SW: ACTIVATE
1. delete caches that are not the current one
*/
async function onActivate()
console.info("SW : Activate : " + VERSION);
const cacheNames = await caches.keys();
return Promise.all(
cacheNames
.filter(function (cacheName)
return cacheName !== VERSION;
)
.map(function (cacheName)
return caches.delete(cacheName);
)
);
;
/*
SW: FETCH
This is when the service worker intercepts an http request
If the path is in the cache, we use it
else we proceed with the request
*/
async function onFetch(event: FetchEvent)
const cache = await caches.open(VERSION);
const url = new URL(event.request.url);
const cacheResource = url.pathname;
const response = await cache.match(cacheResource);
return response ;
sw.addEventListener('install', event => event.waitUntil(onInstall()));
sw.addEventListener('activate', event => event.waitUntil(onActivate()));
sw.addEventListener('fetch', event => event.respondWith(onFetch(event)));
Untuk benar -benar membangun ini, kami masih membutuhkan file tsconfig Dan webpack.config. Jadi, selanjutnya adalah membuatnya.
touch tsconfig.sw.json
touch webpack.config.js
ada tsconfig.sw.json Kami memiliki:
"compilerOptions":
"target": "ES2020",
"module": "ESNext",
"lib": ["DOM", "webworker", "ES2020"],
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node",
"skipLibCheck": true
,
"include": ["./src/sw/service-worker.ts"]
Ini pada dasarnya mengatakan src/sw/service-worker.ts Dan masukkan hasilnya dist. Karena ini adalah pekerja web lib Kami akan menambahkan "webworker" Hal yang sama benar.
Pada saat yang sama tsconfig.json Kami akan menambahkan exclude: src/sw
.
.
.
.
"exclude": [
"node_modules",
"src/sw"
]
Dengan cara ini, ketika kami membangun solusi berikutnya, pekerja layanan tidak akan ikut campur.
ada webpack.config.js Sebaliknya, kami punya.
const path = require('path');
module.exports = {
entry: './src/sw/service-worker.ts',
module:
rules: [
test: /\.ts$/,
use:
loader: 'ts-loader',
options:
configFile: 'tsconfig.sw.json'
,
exclude: /node_modules/
]
,
resolve:
extensions: ['.ts', '.js']
,
output:
filename: 'service-worker.js',
path: path.resolve(__dirname, 'dist')
};
Sentuhan terakhir, package.json Mari kita tambahkan beberapa skrip baru
"scripts":
"x--------------------NEXT------------------------x": "Next commands",
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"x--------------------SW------------------------x": "Service Worker",
"build:sw:generate": "node scripts/generate.js",
"build:sw": "webpack",
"x--------------------VERSION------------------------x": "Bump",
"ver:patch": "npm version patch",
"ver:minor": "npm version minor",
"ver:major": "npm version major",
"x--------------------RELEASE------------------------x": "Release",
"release:patch": "npm run ver:patch && npm run build && npm run build:sw:generate && npm run build:sw",
"release:minor": "npm run ver:minor && npm run build && npm run build:sw:generate && npm run build:sw",
"release:major": "npm run ver:major && npm run build && npm run build:sw:generate && npm run build:sw"
,
Dengan ini Anda harus dapat membuat versinya npm run release:minor Itu akan package.json Maka itu akan membangun JS berikutnya dan kemudian menghasilkan app-file-list.ts Dan version.ts Akhirnya dibuat service-worker.js.
Pada akhir semua ini, Anda harus memiliki:
.
├── README.md
├── eslint.config.mjs
├── next-env.d.ts
├── next.config.ts
├── package-lock.json
├── package.json
├── public
│ ├── file.svg
│ ├── globe.svg
│ ├── next.svg
│ ├── vercel.svg
│ └── window.svg
├── src
│ ├── app
│ │ ├── favicon.ico
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ ├── page.module.css
│ │ └── page.tsx
│ └── sw
│ ├── app-file-list.ts
│ ├── service-worker.ts
│ └── version.ts
├── tsconfig.json
├── tsconfig.sw.json
└── webpack.config.js
Mari kita impor pekerja layanan di Next.js
Pada titik ini, kita harus bisa berada di yang berikutnya. dist Folder dan kami service-worker.jstetapi kita masih perlu mendaftarkan pekerja layanan dengan cara yang menggunakannya.
Untuk melakukan ini, kami akan menambahkan satu template.tsx File dalam file app Map.
"use client";
import useEffect from "react";
export default function Template( children : Readonly<children: React.ReactNode; >)
useEffect(() =>
if (document.domain === "localhost")
return;
if (!('serviceWorker' in navigator))
console.error("Service workers are not supported.");
return;
navigator
.serviceWorker
.register("/service-worker.js")
.then((registration) =>
console.log("Service worker registration succeeded:", registration);
if (registration.installing)
console.log("SW status: installing");
return;
if (registration.waiting)
console.log("SW status: waiting");
return;
if (registration.active)
console.log("SW status: active");
return;
)
.catch((error) =>
console.error(`Service worker registration failed: $error`);
);
, []);
return (<> children </>);
Ringkasan
OK, kami telah melihat beberapa konsep dasar tentang pekerja layanan, terutama unduhan status, instalasi, menunggu, kegiatan dan beberapa jebakan untuk menghindari pemisahan pekerja layanan yang gila.
Kami kemudian menambahkan dukungan untuk pekerja layanan menggunakan solusi dasar selanjutnya.js. Untuk melakukan ini, kami menggunakan skrip untuk mendapatkan daftar versi aplikasi dan file dalam pekerjaan aplikasi. Di Pekerja Layanan, kami menyimpan daftar file berdasarkan versi dan rentang waktu, dan jika sumber daya memiliki kecocokan di cache, kami mendapatkannya dari web.
Akhirnya, kami menyatukan semuanya dengan beberapa skrip baru package.json.
Setelah itu, Anda harus dapat menyelidiki pekerja layanan dan dokumen cache dan memperluas contoh saat ini.
Jika Anda menyukai apa yang Anda baca, saya sarankan Anda bermain skipWaiting,,,,, postMessage Dan controllerchange peristiwa.
Link
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#NEXT.js #PWA #Fungsionalitas #offline #dengan #pekerja #layanan #tidak #ada #paket #tambahan