{"id":13431213,"url":"https://github.com/madskristensen/WebEssentials.AspNetCore.ServiceWorker","last_synced_at":"2025-03-16T11:31:17.279Z","repository":{"id":48302523,"uuid":"109053012","full_name":"madskristensen/WebEssentials.AspNetCore.ServiceWorker","owner":"madskristensen","description":null,"archived":false,"fork":false,"pushed_at":"2024-10-09T01:26:30.000Z","size":152,"stargazers_count":341,"open_issues_count":58,"forks_count":61,"subscribers_count":26,"default_branch":"master","last_synced_at":"2025-03-13T18:05:56.753Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/madskristensen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"madskristensen"}},"created_at":"2017-10-31T21:15:07.000Z","updated_at":"2025-02-25T14:53:09.000Z","dependencies_parsed_at":"2022-09-12T07:00:59.879Z","dependency_job_id":"f541f3b1-0a30-4b75-bb9f-74e5e439eab4","html_url":"https://github.com/madskristensen/WebEssentials.AspNetCore.ServiceWorker","commit_stats":{"total_commits":64,"total_committers":19,"mean_commits":"3.3684210526315788","dds":0.421875,"last_synced_commit":"344af39e2a5ad431aa47b6567cc50ccdcd207141"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madskristensen%2FWebEssentials.AspNetCore.ServiceWorker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madskristensen%2FWebEssentials.AspNetCore.ServiceWorker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madskristensen%2FWebEssentials.AspNetCore.ServiceWorker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/madskristensen%2FWebEssentials.AspNetCore.ServiceWorker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/madskristensen","download_url":"https://codeload.github.com/madskristensen/WebEssentials.AspNetCore.ServiceWorker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243862779,"owners_count":20360210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T02:01:01.392Z","updated_at":"2025-03-16T11:31:16.912Z","avatar_url":"https://github.com/madskristensen.png","language":"C#","funding_links":["https://github.com/sponsors/madskristensen"],"categories":["Frameworks, Libraries and Tools","others","框架, 库和工具"],"sub_categories":["Misc","大杂烩"],"readme":"# ASP.NET Core Progressive Web Apps\n\n[![Build status](https://ci.appveyor.com/api/projects/status/033jspebqrwao5o4?svg=true)](https://ci.appveyor.com/project/madskristensen/webessentials-aspnetcore-serviceworker)\n[![NuGet](https://img.shields.io/nuget/v/WebEssentials.AspNetCore.PWA.svg)](https://nuget.org/packages/WebEssentials.AspNetCore.PWA/)\n\nA [Progressive Web App](https://developers.google.com/web/progressive-web-apps/) (PWA) is a set of technologies that can be applied to any type of website and web application, and it consist of 3 components:\n\n1. Any website served over HTTPS\n2. A [Web App Manifest](http://www.w3.org/TR/appmanifest/) (simple JSON file)\n3. A [Service Worker](https://developers.google.com/web/fundamentals/primers/service-workers/) JavaScript file\n\nThis components makes Web App Manifest a natural and integrated part of any ASP.NET Core web application and it comes with pre-built service workers so you don't have to write your own.\n\n![PWA install prompt](art/app-install.png)\n\nBuilding Progressive Web Apps have never been easier!\n\n## Install\nTo add the PWA service to your ASP.NET Core 2.0 application, simply add the NuGet package [WebEssentials.AspNetCore.PWA](https://www.nuget.org/packages/WebEssentials.AspNetCore.PWA/).\n\nEither do that through Visual Studio's NuGet Package Manager or the command line like this:\n\n```cmd\ndotnet add package WebEssentials.AspNetCore.PWA\n```\n\n## Getting started\nYou need to do a few things to turn your website into a PWA:\n\n1. Add two image icons to your project (192x192 and 512x512)\n2. Add a `manifest.json` file in the root of the `wwwroot` folder\n3. Register a service in `Startup.cs`\n4. Make sure it works\n\n### Step 1 - Icons\nGet as many icons in various sizes as you want, but you MUST have both a 192x192 and a 512x512 size icon. Use PNG or JPEG. \n\nPlace the icons somewhere in the `wwwroot` folder. \n\n\u003e Listing the size in the file names makes them easy to identify. Example: `wwwroot/img/icon192x192.png`\n\u003e [Consider using Real Favicon Generator](https://realfavicongenerator.net/) to generate images for different platforms and sizes.\n\n### Step 2 - manifest JSON file\nAdd the file `wwwroot/manifest.json` to your project and fill it in. It could look like this:\n\n```json\n{\n  \"name\": \"Awesome Application\",\n  \"short_name\": \"Awesome\",\n  \"description\": \"The most awesome application in the world\",\n  \"icons\": [\n    {\n      \"src\": \"/img/icon192x192.png\",\n      \"sizes\": \"192x192\"\n    },\n    {\n      \"src\": \"/img/icon512x512.png\",\n      \"sizes\": \"512x512\"\n    }\n  ],\n  \"display\": \"standalone\",\n  \"start_url\": \"/\"\n}\n```\n\nRead more about the various properties in the [W3C specificiation](http://www.w3.org/TR/appmanifest/).\n\nNow your file structure will look something like this:\n\n![Solution Explorer](art/solution-explorer.png)\n\n### Step 3 - register the service\nInside the `ConfigureServices` method in `Startup.cs`, add a call to `services.AddProgressiveWebApp()` like so:\n\n```c#\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddProgressiveWebApp();\n}\n```\n\n\u003e A `WebManifest` object is now available in the Dependency Injection system in ASP.NET Core that allows you to access the contents of the manifest.json file through the strongly typed object.\n\nYou are now done converting your website into a PWA!\n\n### Step 4 - verify it works\nIf you've followed steps 1-3 then it's time to run your app in the browser and test that it is in fact a PWA. Here's how to verify it works:\n\n**Turn off JavaScript debugging** in Visual Studio for the service worker to successfully register or follow this [workaround](https://stackoverflow.com/a/46128895).\n\nTurn off JavaScript debugging from **Tools \u003e Options**:\n\n![Debugger options](art/debugger-options.png)\n\n**Launch the app** in the Chrome browser.\n\n**View source** and ensure the following element is present in `\u003chead\u003e`:\n\n```html\n\u003clink rel=\"manifest\" href=\"/manifest.webmanifest\" /\u003e\n```\n\nThe file name is `manifest.webmanifest` and not `manifest.json` because this component is handling the request instead of serving `manifest.json` directly as a static file.\n\nIf you filled in the property `theme_color` in `manifest.json` then you'll also see this meta tag:\n\n```html\n\u003cmeta name=\"theme-color\" content=\"#ffffff\" /\u003e\n```\n\nJust before the `\u003c/body\u003e` end tag you'll see a script tag registering the service worker:\n\n```html\n\u003cscript\u003e'serviceWorker'in navigator\u0026\u0026navigator.serviceWorker.register('/serviceworker')\u003c/script\u003e\n```\n\n**Open the Chrome developer tools (F12)** and navigate to the **Application** tab and select **Service Workers**. It should look somehting like this:\n\n![Chrome Dev Tools Application](art/chrome-devtools-application.png)\n\nIf you see a service worker listed, then it was registered successfully. You may have to refresh the page in the browser to see it.\n\n\u003e Pro tip: Make sure to check the checkbox name **Update on reload** for a better development time experience.\n\nClicking **Manifest** should show something like this:\n\n![Chrome Dev Tools Manifest](art/chrome-devtools-manifest.png)\n\nIf you see both the service worker and the manifest information then it's all working and you have now successfully converted your site to a PWA!\n\n## Customize\nYou can customize various settings related to both the service worker and the Web App Manifest by passing in a `PwaOptions` object.\n\n```c#\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddProgressiveWebApp(new PwaOptions\n    {\n        RoutesToPreCache = \"/, /contact.html, data.json\",\n        Strategy = ServiceWorkerStrategy.CacheFirst\n    });\n}\n```\n\nThe same options can be set through the ASP.NET Core configuration system in appsettings.json:\n\n```json\n{\n  \"pwa\": {\n    \"registerWebmanifest\":  true,\n    \"routesToPreCache\": \"/, /contact.html, data.json\",\n    \"strategy\": \"cacheFirst\"\n  }\n}\n```\n\nThis means you can have settings specific to each of your environments (development, staging, production, etc.) by using various `appsettings.\u003cenvironment\u003e.json` files or by using environment variables.\n\n\u003e If you use Visual Studio then you should get full Intellisense inside the `pwa` object in appsettings.json.\n\n## Customizing the Web App Manifest\nYou can use the Web App Manifest alone without the service worker by calling `services.AddWebAppManifest()` instead of `services.AddProgressiveWebApp()`.\n\n```c#\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddWebAppManifest();\n}\n```\n\nBy default it looks for a file named `manifest.json` in the `wwwroot` folder, but you can change the file name to whatever you like - just make sure it is located in the root of the `wwwroot` folder.\n\nIf you name it `manifest.webmanifest` then you are bypassing the middleware that handles the serving of the file and instead using the Static File middleware like it was any other static file. This can be desired for certain cases, but if you're in doubt then don't name it `manifest.webmanifest`. \n\n## Customizing the service worker\nYou can use the service worker alone without the Web App Manifest by calling `services.AddServiceWorker()` instead of `services.AddProgressiveWebApp()`.\n\n```c#\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddServiceWorker();\n}\n```\n\n### Configure the service worker\nThe options can be configured either in `Startup.cs`:\n\n```c#\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddServiceWorker(new PwaOptions\n    {\n        CacheId = \"v3\",\n        RoutesToPreCache = \"foo.css, bar.js\"\n    });\n}\n```\n\n...or in `appsettings.json`:\n\n```json\n{\n  \"pwa\": {\n    \"cacheId\": \"v1.0\",\n    \"routesToPreCache\": \"foo.css, bar.js\"\n  }\n}\n```\n\n## Caching strategies\nSpecify which caching strategy you want to use if you want a different one than the default (CacheFirstSafe):\n\n```c#\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddServiceWorker(new PwaOptions\n    {\n        Strategy = ServiceWorkerStrategy.CacheFirst\n    });\n}\n```\n\n...or in `appsettings.json`:\n\n```json\n{\n  \"serviceworker\": {\n    \"strategy\": \"cacheFirst\"\n  }\n}\n```\n\nThe options are:\n\n### CacheFirst\nThis strategy will add all requested resources to the service worker cache and serve it from the cache every time. If the cache doesn't have the requested resource it will fall back to the network and if that succeeds it will put the response in the cache.\n\n### CacheFirstSafe (default)\nThis strategy, like CacheFirst, will add all requested resources to the service worker cache. Unlike CacheFirst, it has special handling for HTML files and fingerprinted resources (resources with a `v` querystring parameter such as `site.css?v=8udsfsaufd09sud0809sd_ds`).\n\nIt will always attempt the network for HTML files (content type `text/html`) and fall back to the cache when the user is offline. That way the user always gets the latest from the live Internet when online.\n\nFor fingerprinted resources (the ones with a `v` querystring parameter) it will always try the cache first and fall back to the network.\n\n### CacheFingerprinted\nThis strategy only adds fingerprinted resources (resources with a `v` querystring parameter such as `site.css?v=8udsfsaufd09sud0809sd_ds) to the cache.\n\nIt will always try the cache for fingerprinted resources, then fall back to the network. For all other resources, it will use the network.\n\nThis strategy is useful for scenarios in which you don't wish to cache certain resources -- large video or audio files, for example -- but still wish to cache the app core assets (HTML, CSS, JS).\n\n### Minimal\nThe minimal strategy does nothing and is good for when you only want a service worker in order for browsers to suggest installing your Progressive Web App. For this to work, you need to add a [web manifest](https://medium.com/dev-channel/how-to-add-a-web-app-manifest-and-mobile-proof-your-site-450e6e485638) file.\n\n### NetworkFirst\nThis strategy will always try the network first for all resources and then fall back to the cache when offline. When the network call succeeds, it will put the response in the cache.\n\nThis strategy is completely safe to use and is primarily useful for offline-only scenarios since it isn't giving any performance benefits.\n\n### CustomStrategy\nThis strategy will allow the user to specify their own implementation as a Javascript(.js) file.  By default the app will search for a file named `customserviceworker.js` in the wwwroot folder.   \nA filename may be explicitly set by providing it as an option when registering the service in the `Startup.cs` or `appsettings.json` file.\n\n```C#\npublic void ConfigureServices(IServiceCollection services)\n        {\n            services.AddMvc();\n            services.AddProgressiveWebApp(new PwaOptions { RegisterServiceWorker = true, Strategy = ServiceWorkerStrategy.CustomStrategy, CustomServiceWorkerStrategyFileName = \"myCustomServiceworkerStrategy.js\"});\n        }\n```\n\nWhen creating the `customserviceworker.js` by providing {version}, {routes}, {ignoreRoutes} and {offlineRoute} values within the javascript file string, interpolation will be used to replace these values with option values as set in the `Startup.cs` or `appsettings.json` file.\n\n```javascript\n(function () {\n    //Insert Your Service Worker In place of this one!\n\n    // Update 'version' if you need to refresh the cache\n    var version = '{version}';\n    var offlineUrl = \"{offlineRoute}\";\n    var routes = \"{routes}\";\n    var routesToIgnore = \"{ignoreRoutes}\";\n});\n```\n\n## .Net Core Application hosted as Virtual Directory\nYou can now specify a specific BaseURL if you plan to host your application as a Virtual Directory in IIS:\n\n```c#\nprivate const string _baseURL = \"/PWAApp\";\n\npublic void ConfigureServices(IServiceCollection services)\n{\n    services.AddMvc();\n    services.AddServiceWorker(new PwaOptions\n    {\n        BaseRoute = _baseURL;\n        Strategy = ServiceWorkerStrategy.CacheFirst\n    });\n}\n\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    //...\n    app.UsePathBase(_baseURL);\n    //...\n}\n```\n\n...or in `appsettings.json`:\n\n```json\n{\n  \"serviceworker\": {\n    \"baseRoute\": \"/PWAApp\",\n    \"strategy\": \"cacheFirst\"\n  }\n}\n```\n\nMake sure to update your `wwwroot/manifest.json` file:\n\n```json\n{\n  \"name\": \"Awesome Application\",\n  \"short_name\": \"Awesome\",\n  \"description\": \"The most awesome application in the world\",\n  \"icons\": [\n    {\n      \"src\": \"/PWAApp/img/icon192x192.png\",\n      \"sizes\": \"192x192\"\n    },\n    {\n      \"src\": \"/PWAApp/img/icon512x512.png\",\n      \"sizes\": \"512x512\"\n    }\n  ],\n  \"display\": \"standalone\",\n  \"start_url\": \"/PWAApp/\"\n}\n```\n\n\n## License\n[Apache 2.0](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmadskristensen%2FWebEssentials.AspNetCore.ServiceWorker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmadskristensen%2FWebEssentials.AspNetCore.ServiceWorker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmadskristensen%2FWebEssentials.AspNetCore.ServiceWorker/lists"}