From 4a6a2cf4f509941346b6926500ea472c85e07f06 Mon Sep 17 00:00:00 2001 From: felixindrawan Date: Wed, 26 Jun 2024 15:40:24 -0700 Subject: [PATCH] feat: update pwa sample and docs --- hello-world/pwa/README.md | 372 +++++++++++++++------------- hello-world/pwa/helloworld-pwa.html | 167 +++++++------ hello-world/pwa/helloworld-pwa.json | 42 ++-- hello-world/pwa/service-worker.js | 13 +- 4 files changed, 308 insertions(+), 286 deletions(-) diff --git a/hello-world/pwa/README.md b/hello-world/pwa/README.md index 1ab0d32d..d8906957 100644 --- a/hello-world/pwa/README.md +++ b/hello-world/pwa/README.md @@ -1,6 +1,14 @@ # Hello World Sample for PWA -[PWA](https://web.dev/progressive-web-apps/) is short for Progressive Web Apps which stand for web applications that have been designed to behave like platform-specific (native) applications. Check out the following on how to implement Dynamsoft Barcode Reader JavaScript SDK (hereafter called "the library") into a PWA application. +[PWA](https://web.dev/progressive-web-apps/) is short for Progressive Web Apps, which are web applications designed to mimic the functionality and user experience of platform-specific (native) applications. Follow this guide to learn how to implement [Dynamsoft Barcode Reader JavaScript SDK](https://www.dynamsoft.com/barcode-reader/sdk-javascript/) (hereafter called "the library") into a PWA application. + +In this guide, we will be using [`dynamsoft-barcode-reader-bundle 10.2.1000`](https://www.npmjs.com/package/dynamsoft-barcode-reader-bundle/v/10.2.1000). + +> Note: +> +> If you’re looking to integrate DBR-JS into a framework that we don't yet have a sample, don't worry! We have a [comprehensive guide](https://www.dynamsoft.com/barcode-reader/docs/web/programming/javascript/user-guide/use-in-framework.html) that provides detailed instruction and best practices for a seamless integration into any frameworks! +> +> Additionally, we're here to help! Please don't hesitate to [contact us](#Support) for any support or questions you might have. ## Official Sample @@ -9,175 +17,172 @@ ## Preparation -We will try to turn our most basic hello world sample into a PWA. +We will try to turn our basic "Hello World" sample into a PWA. Follow these steps: -First, create a file with the name "helloworld-pwa.html" and fill it with the following code: +* Create new file named `helloworld-pwa.html` and add the following code: ```html + - - - - - Hello World - - - -

Hello World for PWA

-
-Results: -
-
- + - + - - + })(); + + ``` -Next, set up a secure environment (HTTPs) to run the page "helloworld-pwa.html". This is required because PWAs only run in secure environments. - -In our case, we use IIS to set up a secure site at "https://localhost" and the page is put at the root so that it can be accessed at "https://localhost/helloworld-pwa.html". +* Next, set up a secure environment (HTTPS) to run the page `helloworld-pwa.html`. This is required as PWAs only run in secure environments. +> Note: +> +> In this sample, we're using IIS to set up a secure site at https://localhost. The page will be located at the root of the site so that it can be accessed at https://localhost/helloworld-pwa.html. ## Make the app progressive ### Register a service worker for offline support -As the basis for PWAs, Service Workers are a virtual proxy between the browser and the network. A service worker can serve content offline, handle notifications and perform heavy calculations, etc. all on a separate thread. +Service Workers form the foundation of PWAs, acting as the virtual proxy between the browser and the network. They enable offline content delivery, manage notifications, and perform heavy calculations on a separate thread -To use a service worker, we first need to register it. In the helloworld-pwa.html file, add the following at the end of the script: +* To use a service worker, we first need to register it. In the `helloworld-pwa.html` file, add the following code at the end of the script: ```javascript +/* /helloworld-pwa.html */ if ('serviceWorker' in navigator) { navigator.serviceWorker.register('./service-worker.js'); }; ``` -Create the service-worker.js file with the following content: +* Next, create the `service-worker.js` file with the following content: ```javascript +/* /service-worker.js */ // Files to cache const cacheName = 'helloworld-pwa'; const appShellFiles = [ - './helloworld-pwa.html', + './helloworld-pwa.html', ]; // Installing Service Worker -self.addEventListener('install', (e) => { - console.log('[Service Worker] Install'); - e.waitUntil((async () => { - const cache = await caches.open(cacheName); - console.log('[Service Worker] Caching all: app shell and content'); - await cache.addAll(appShellFiles); - })()); +self.addEventListener("install", (e) => { + console.log("[Service Worker] Install"); + e.waitUntil( + (async () => { + const cache = await caches.open(cacheName); + console.log("[Service Worker] Caching all: app shell and content"); + await cache.addAll(appShellFiles); + })() + ); }); -self.addEventListener('fetch', (e) => { - e.respondWith((async () => { - const r = await caches.match(e.request); - console.log(`[Service Worker] Fetching resource: ${e.request.url}`); - if (r) { return r; } - const response = await fetch(e.request); - const cache = await caches.open(cacheName); - console.log(`[Service Worker] Caching new resource: ${e.request.url}`); - if (e.request.method !== "POST") - cache.put(e.request, response.clone()); - return response; - })()); +self.addEventListener("fetch", (e) => { + e.respondWith( + (async () => { + // Fetch cached response if exists + const cachedResponse = await caches.match(e.request); + console.log(`[Service Worker] Fetching resource: ${e.request.url}`); + if (cachedResponse) { + return cachedResponse; + } + + // Otherwise, fetch from network + const response = await fetch(e.request); + const cache = await caches.open(cacheName); + console.log(`[Service Worker] Caching new resource: ${e.request.url}`); + if (e.request.method !== "POST") { + cache.put(e.request, response.clone()); + } + return response; + })() + ); }); ``` -With the above code, the application can now work offline because the service worker will cache the page helloworld-pwa.html and its related resources. +With the above code, the application can now work offline because the service worker will cache the `helloworld-pwa.html` page and its related resources. For more information, refer to [Making PWAs work offline with Service workers](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Offline_Service_workers). -> NOTE +> Note: > -> Since the files are being cached, changes we make in later steps may not be reflected. Therefore, don't forget to clear the cache after a change is made. To do so, you can run the following in the browser console. +> Since the files are cached, changes we make in later steps may not be reflected immediately. To ensure updates are applied, clear the cache after changes are made. You can do this by running the following code in the browser console: > > ```javascript > const cacheName = 'helloworld-pwa'; @@ -186,46 +191,50 @@ For more information, refer to [Making PWAs work offline with Service workers](h ### Use a web manifest file to make the application installable -A web manifest file contains a list of information about a website in a JSON format. This information is used to present the web app correctly for installation on a device. +A web manifest file contains a list of information about a website in JSON format. This information is used to enable the web app to be installed on a device. -In our example, we first create a file "helloworld-pwa.json" with the following content: +* Create a file named `helloworld-pwa.json` with the following content: ```json +/* /helloworld-pwa.json */ { - "name": "Dynamsoft Barcode Reader Progressive Web App", - "short_name": "DBR-PWA", - "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", - "start_url": "./helloworld-pwa.html", - "scope": ".", - "display": "standalone", - "theme_color": "#B12A34", - "background_color": "#B12A34", - "icons": [ - { - "src": "./dynamsoft-512x512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "./dynamsoft-192x192.png", - "sizes": "192x192", - "type": "image/png" - } - ] + "name": "Dynamsoft Barcode Reader Progressive Web App", + "short_name": "DBR-PWA", + "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", + "start_url": "./helloworld-pwa.html", + "scope": ".", + "display": "standalone", + "theme_color": "#B12A34", + "background_color": "#B12A34", + "icons": [ + { + "src": "./dynamsoft-512x512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "./dynamsoft-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ] } ``` -> The icon files can be found in the github repository. +> Note: The icon files can be found in the github repository. -Then we include the file in the <head> block of the helloworld-pwa.html file: +* Then we include the file in the `` block of the `helloworld-pwa.html` file as such: ```html + ``` -For compatibility on safari, we need add some `meta` in ``: +* For compatibility on safari, we need add some `meta` in ``. ```html + + @@ -237,22 +246,26 @@ For compatibility on safari, we need add some `meta` in ``: Now, if you open the application again in your browser, you will notice an install icon appear on the right side of the address bar. When you click on it, a pop-up will appear asking if you want to install the app. -Once installed, you can use it like a native app. +Once installed, you can use it just like any native app. -For offline use, you need to cache more files. +To enable offline functionality for Dynamsoft Barcode Reader, you'll need to cache more files. -service-worker.js +### Enabling offline functionality for Dynamsoft Barcode Reader + +These directories below are the resources required for Dynamsoft Barcode Reader functionality. Once added, these files are cached on installation of the service worker (i.e. `install` event), wensuring the PWA remains fully functional without any internet. + +Add this code below to the `service-worker.js` ```javascript -const coreResourcesDir = - "https://cdn.jsdelivr.net/npm/dynamsoft-core@3.2.30/dist/", - utilityResourcesDir = - "https://cdn.jsdelivr.net/npm/dynamsoft-utility@1.2.20/dist/", - dbrResourcesDir = - "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader@10.2.10/dist/", - cvrResourcesDir = - "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-router@2.2.30/dist/", - dceResourcesDir = - "https://cdn.jsdelivr.net/npm/dynamsoft-camera-enhancer@4.0.3/dist/"; +/* /service-worker.js */ +const engineResourcePaths = { + std: "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-std@1.2.10/dist/", + dip: "https://cdn.jsdelivr.net/npm/dynamsoft-image-processing@2.2.30/dist/", + core: "https://cdn.jsdelivr.net/npm/dynamsoft-core@3.2.30/dist/", + license: "https://cdn.jsdelivr.net/npm/dynamsoft-license@3.2.21/dist/", + cvr: "https://cdn.jsdelivr.net/npm/dynamsoft-capture-vision-router@2.2.30/dist/", + dbr: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader@10.2.10/dist/", + dce: "https://cdn.jsdelivr.net/npm/dynamsoft-camera-enhancer@4.0.3/dist/" +}; // Files to cache const cacheName = "helloworld-pwa"; @@ -261,19 +274,24 @@ const appShellFiles = [ "./dynamsoft-192x192.png", "./dynamsoft-512x512.png", "./helloworld-pwa.json", - `${coreResourcesDir}core.js`, - `${utilityResourcesDir}utility.js`, - `${dbrResourcesDir}dbr.js`, - `${dbrResourcesDir}dbr.wasm`, - `${dbrResourcesDir}DBR-PresetTemplates.json`, - `${cvrResourcesDir}cvr.js`, - `${cvrResourcesDir}cvr.wasm`, - `${cvrResourcesDir}cvr.wasm.js`, - `${cvrResourcesDir}cvr_wasm_glue.js`, - `${cvrResourcesDir}cvr.browser.worker.js`, - `${cvrResourcesDir}dls.license.dialog.html`, - `${cvrResourcesDir}dce.js`, - `${cvrResourcesDir}dce.ui.html`, + `${engineResourcePaths.std}std.js`, + `${engineResourcePaths.std}std.wasm`, + `${engineResourcePaths.dip}dip.wasm`, + `${engineResourcePaths.core}core.js`, + `${engineResourcePaths.core}core.worker.js`, + `${engineResourcePaths.core}core.wasm`, + `${engineResourcePaths.license}license.js`, + `${engineResourcePaths.license}dls.license.dialog.html`, + `${engineResourcePaths.license}license.wasm`, + `${engineResourcePaths.utility}utility.js`, + `${engineResourcePaths.dbr}dbr.js`, + `${engineResourcePaths.dbr}dbr.wasm`, + `${engineResourcePaths.dbr}DBR-PresetTemplates.json`, + `${engineResourcePaths.cvr}cvr.js`, + `${engineResourcePaths.cvr}cvr.wasm`, + `${engineResourcePaths.cvr}cvr.worker.js`, + `${engineResourcePaths.dce}dce.js`, + `${engineResourcePaths.dce}dce.ui.html`, ]; ``` diff --git a/hello-world/pwa/helloworld-pwa.html b/hello-world/pwa/helloworld-pwa.html index dfa281ce..50addab5 100644 --- a/hello-world/pwa/helloworld-pwa.html +++ b/hello-world/pwa/helloworld-pwa.html @@ -1,98 +1,97 @@ - - - - - - Dynamsoft Barcode Reader PWA Sample - Hello World (Decode via Camera) - - - - - - - - - - + + + + + + Dynamsoft Barcode Reader PWA Sample - Hello World (Decode via Camera) + + + + + + + + + + - -

Hello World for PWA

-
- Results: -
-
- - + + - - + + diff --git a/hello-world/pwa/helloworld-pwa.json b/hello-world/pwa/helloworld-pwa.json index 67cf077d..1c6c8e42 100644 --- a/hello-world/pwa/helloworld-pwa.json +++ b/hello-world/pwa/helloworld-pwa.json @@ -1,22 +1,22 @@ { - "name": "Dynamsoft Barcode Reader Progressive Web App", - "short_name": "DBR-PWA", - "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", - "start_url": "./helloworld-pwa.html", - "scope": ".", - "display": "standalone", - "theme_color": "#B12A34", - "background_color": "#B12A34", - "icons": [ - { - "src": "./dynamsoft-512x512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "./dynamsoft-192x192.png", - "sizes": "192x192", - "type": "image/png" - } - ] -} + "name": "Dynamsoft Barcode Reader Progressive Web App", + "short_name": "DBR-PWA", + "description": "Progressive Web App that reads barcodes from a video input with Dynamsoft Barcode Reader.", + "start_url": "./helloworld-pwa.html", + "scope": ".", + "display": "standalone", + "theme_color": "#B12A34", + "background_color": "#B12A34", + "icons": [ + { + "src": "./dynamsoft-512x512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "./dynamsoft-192x192.png", + "sizes": "192x192", + "type": "image/png" + } + ] +} \ No newline at end of file diff --git a/hello-world/pwa/service-worker.js b/hello-world/pwa/service-worker.js index a46f93ba..e6b8ba3a 100644 --- a/hello-world/pwa/service-worker.js +++ b/hello-world/pwa/service-worker.js @@ -50,15 +50,20 @@ self.addEventListener("install", (e) => { self.addEventListener("fetch", (e) => { e.respondWith( (async () => { - const r = await caches.match(e.request); + // Fetch cached response if exists + const cachedResponse = await caches.match(e.request); console.log(`[Service Worker] Fetching resource: ${e.request.url}`); - if (r) { - return r; + if (cachedResponse) { + return cachedResponse; } + + // Otherwise, fetch from network const response = await fetch(e.request); const cache = await caches.open(cacheName); console.log(`[Service Worker] Caching new resource: ${e.request.url}`); - if (e.request.method !== "POST") cache.put(e.request, response.clone()); + if (e.request.method !== "POST") { + cache.put(e.request, response.clone()); + } return response; })() );