Coder Social home page Coder Social logo

webessentials.aspnetcore.serviceworker's Introduction

ASP.NET Core Progressive Web Apps

Build status NuGet

A Progressive Web App (PWA) is a set of technologies that can be applied to any type of website and web application, and it consist of 3 components:

  1. Any website served over HTTPS
  2. A Web App Manifest (simple JSON file)
  3. A Service Worker JavaScript file

This 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.

PWA install prompt

Building Progressive Web Apps have never been easier!

Install

To add the PWA service to your ASP.NET Core 2.0 application, simply add the NuGet package WebEssentials.AspNetCore.PWA.

Either do that through Visual Studio's NuGet Package Manager or the command line like this:

dotnet add package WebEssentials.AspNetCore.PWA

Getting started

You need to do a few things to turn your website into a PWA:

  1. Add two image icons to your project (192x192 and 512x512)
  2. Add a manifest.json file in the root of the wwwroot folder
  3. Register a service in Startup.cs
  4. Make sure it works

Step 1 - Icons

Get 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.

Place the icons somewhere in the wwwroot folder.

Listing the size in the file names makes them easy to identify. Example: wwwroot/img/icon192x192.png Consider using Real Favicon Generator to generate images for different platforms and sizes.

Step 2 - manifest JSON file

Add the file wwwroot/manifest.json to your project and fill it in. It could look like this:

{
  "name": "Awesome Application",
  "short_name": "Awesome",
  "description": "The most awesome application in the world",
  "icons": [
    {
      "src": "/img/icon192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "/img/icon512x512.png",
      "sizes": "512x512"
    }
  ],
  "display": "standalone",
  "start_url": "/"
}

Read more about the various properties in the W3C specificiation.

Now your file structure will look something like this:

Solution Explorer

Step 3 - register the service

Inside the ConfigureServices method in Startup.cs, add a call to services.AddProgressiveWebApp() like so:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddProgressiveWebApp();
}

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.

You are now done converting your website into a PWA!

Step 4 - verify it works

If 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:

Turn off JavaScript debugging in Visual Studio for the service worker to successfully register or follow this workaround.

Turn off JavaScript debugging from Tools > Options:

Debugger options

Launch the app in the Chrome browser.

View source and ensure the following element is present in <head>:

<link rel="manifest" href="/manifest.webmanifest" />

The 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.

If you filled in the property theme_color in manifest.json then you'll also see this meta tag:

<meta name="theme-color" content="#ffffff" />

Just before the </body> end tag you'll see a script tag registering the service worker:

<script>'serviceWorker'in navigator&&navigator.serviceWorker.register('/serviceworker')</script>

Open the Chrome developer tools (F12) and navigate to the Application tab and select Service Workers. It should look somehting like this:

Chrome Dev Tools Application

If you see a service worker listed, then it was registered successfully. You may have to refresh the page in the browser to see it.

Pro tip: Make sure to check the checkbox name Update on reload for a better development time experience.

Clicking Manifest should show something like this:

Chrome Dev Tools Manifest

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

Customize

You can customize various settings related to both the service worker and the Web App Manifest by passing in a PwaOptions object.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddProgressiveWebApp(new PwaOptions
    {
        RoutesToPreCache = "/, /contact.html, data.json",
        Strategy = ServiceWorkerStrategy.CacheFirst
    });
}

The same options can be set through the ASP.NET Core configuration system in appsettings.json:

{
  "pwa": {
    "registerWebmanifest":  true,
    "routesToPreCache": "/, /contact.html, data.json",
    "strategy": "cacheFirst"
  }
}

This means you can have settings specific to each of your environments (development, staging, production, etc.) by using various appsettings.<environment>.json files or by using environment variables.

If you use Visual Studio then you should get full Intellisense inside the pwa object in appsettings.json.

Customizing the Web App Manifest

You can use the Web App Manifest alone without the service worker by calling services.AddWebAppManifest() instead of services.AddProgressiveWebApp().

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddWebAppManifest();
}

By 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.

If 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.

Customizing the service worker

You can use the service worker alone without the Web App Manifest by calling services.AddServiceWorker() instead of services.AddProgressiveWebApp().

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddServiceWorker();
}

Configure the service worker

The options can be configured either in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddServiceWorker(new PwaOptions
    {
        CacheId = "v3",
        RoutesToPreCache = "foo.css, bar.js"
    });
}

...or in appsettings.json:

{
  "pwa": {
    "cacheId": "v1.0",
    "routesToPreCache": "foo.css, bar.js"
  }
}

Caching strategies

Specify which caching strategy you want to use if you want a different one than the default (CacheFirstSafe):

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddServiceWorker(new PwaOptions
    {
        Strategy = ServiceWorkerStrategy.CacheFirst
    });
}

...or in appsettings.json:

{
  "serviceworker": {
    "strategy": "cacheFirst"
  }
}

The options are:

CacheFirst

This 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.

CacheFirstSafe (default)

This 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).

It 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.

For fingerprinted resources (the ones with a v querystring parameter) it will always try the cache first and fall back to the network.

CacheFingerprinted

This strategy only adds fingerprinted resources (resources with a v querystring parameter such as `site.css?v=8udsfsaufd09sud0809sd_ds) to the cache.

It will always try the cache for fingerprinted resources, then fall back to the network. For all other resources, it will use the network.

This 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).

Minimal

The 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 file.

NetworkFirst

This 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.

This strategy is completely safe to use and is primarily useful for offline-only scenarios since it isn't giving any performance benefits.

CustomStrategy

This 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.
A filename may be explicitly set by providing it as an option when registering the service in the Startup.cs or appsettings.json file.

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddProgressiveWebApp(new PwaOptions { RegisterServiceWorker = true, Strategy = ServiceWorkerStrategy.CustomStrategy, CustomServiceWorkerStrategyFileName = "myCustomServiceworkerStrategy.js"});
        }

When 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.

(function () {
    //Insert Your Service Worker In place of this one!

    // Update 'version' if you need to refresh the cache
    var version = '{version}';
    var offlineUrl = "{offlineRoute}";
    var routes = "{routes}";
    var routesToIgnore = "{ignoreRoutes}";
});

.Net Core Application hosted as Virtual Directory

You can now specify a specific BaseURL if you plan to host your application as a Virtual Directory in IIS:

private const string _baseURL = "/PWAApp";

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddServiceWorker(new PwaOptions
    {
        BaseRoute = _baseURL;
        Strategy = ServiceWorkerStrategy.CacheFirst
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //...
    app.UsePathBase(_baseURL);
    //...
}

...or in appsettings.json:

{
  "serviceworker": {
    "baseRoute": "/PWAApp",
    "strategy": "cacheFirst"
  }
}

Make sure to update your wwwroot/manifest.json file:

{
  "name": "Awesome Application",
  "short_name": "Awesome",
  "description": "The most awesome application in the world",
  "icons": [
    {
      "src": "/PWAApp/img/icon192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "/PWAApp/img/icon512x512.png",
      "sizes": "512x512"
    }
  ],
  "display": "standalone",
  "start_url": "/PWAApp/"
}

License

Apache 2.0

webessentials.aspnetcore.serviceworker's People

Contributors

abitzer avatar afm-horizon avatar aligneddev avatar andrewabest avatar antoninkriz avatar ashleybroughton avatar ctolkien avatar darkace01 avatar dayport avatar dependabot[bot] avatar devsuperman avatar gpavlovic avatar judahgabriel avatar madskristensen avatar mashbrno avatar thewebchameleon avatar thompson-tomo avatar valeriob avatar wandrillety avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webessentials.aspnetcore.serviceworker's Issues

Provide a way to exclude certain files from the cache

Continuing from issue #8, we should provide a way for users to exclude certain request patterns from the cache.

For my scenario, I need to exclude all .mp3 files. Something like:

services.AddProgressiveWebApp(new PwaOptions
{
     // Don't cache MP3s, nor any request from mycdn.com/bigfiles
     RoutesToExcludeFromCache = ".mp3, https://mycdn.com/bigfiles/"
})

Not hard set on that syntax, opened to suggestions.

Push notifications

Thanks for the great work. Because you can only use a single service worker, it would be useful to add push notifications.

Request scheme 'chrome-extension' is unsupported

Uncaught (in promise) TypeError: Request scheme 'chrome-extension' is unsupported
at serviceworker:26

I get this error in the console from cache.put(request, copy). I don't see any way to fix it without downloading the source code and changing it.

CacheFirstSafe is no longer fetching only ?v= resources

It seems a recent update busted the cacheFirstSafe strategy: it's now caching non-versioned css and js files. For example, the Sample project is caching site.css and site.js, even though they don't have the ?v= query param.

image

Is this a bug, or is something else weird going on? I should expect to see only .html and ?v= resources inside the cache when using CacheFirstSafe, right?

Website is not working after register the servicework

I built an asp.net core test web application, then published and deployed locally and the website is working. After I followed the PWA steps to add the changes to the test web app, I built and published the web app to IIS just after added the services.AddProgressiveWebApp();, then website then is not working any more.

Could you please help me to identify what I missing to make the website works again? I am newbie to PWA.

Thank you!
Rebekah

Appsettings pwa section seems to have no effect

Hi Mads,

The documentation appears to say that we can put PWA settings inside appsettings.json. I did this but it appears to have no effect:

// inside appsettings.json
{
  "pwa": {
    "strategy": "networkFirst"
  }
}

// inside startup.cs
services.AddProgressiveWebApp();

I would expect this to make networkFirst the strategy, but it appears to have no effect.

Running the sample locally under debugger shows that the PwaOptions constructor that takes an IConfiguration never gets called. And I see it's internal, and nothing in the library calls it.

Is this a bug? Or am I misunderstanding how the PWA settings inside appsettings.json is supposed to work? If it's a bug, I'd gladly submit a PR to fix it.

Support for Google Analytics

Maybe I just missed some point, but I'm allowed to regiester only one service worker per site.
So I need to include Offline Google Analytics part inside this package:

importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.1.1/workbox-sw.js');
workbox.googleAnalytics.initialize({parameterOverrides: {cd1: 'offline'}});

It's not a nice solution, so maybe you will have an idea, how to make it better. Should I make it at least optional?

Dependency injection failure with ASP.NET Core 2.1 MVC and version 1.0.42

Every request fails with the following exception being thrown:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Http.IHttpContextAccessor' while attempting to activate 'WebEssentials.AspNetCore.Pwa.ServiceWorkerTagHelperComponent'.

Suggested that readme is updated to mention that IHttpContextAccessor needs to be registered in services inside the ConfigureServices() method for those of us who aren't using identity and forget that this isn't registered by default. Thanks.

Fingerprint

Maybe I'm just blind towards the solution, but what is men't by "fingerprinted ressources"?

Or the other way round: how can I Fingerprint a ressource?

THanks for your help

Michael

PWA with asp.net core and serving Nginx

I'm having problem with NGINX and PWA
PWA not working when i'm using static path into NGINX , manifest.webmanifest not working and also service worker not working...any help ??

Deprecation Warning: Element.createShadowRoot is deprecated

Hello,

I'm pretty new PWA and though I managed to get everything working fine using this package, I get this warning:

content.min.js:2 [Deprecation] Element.createShadowRoot is deprecated and will be removed in M73, around March 2019. Please use Element.attachShadow instead. See https://www.chromestatus.com/features/4507242028072960 for more details.

I suppose that the package has to be updated in order to work in the next Chrome version (73)... Otherwise, if there is anything I could do on my side to amend this, I'd be very happy to know it! Thanks in advance for your help :)

Can not Modify manifest.json

Hi,
I use
"WebEssentials.AspNetCore.PWA" Version="1.0.33"

With manifest.json location:
/wwwroot/manifest.json

I messed up with my first manifest.json but when I modified it nothing happened. Browser still loads the old manifest.json (manifest.webmanifest). How do I modify the manifest.json. Thanks.

Authentication

Is there a way to work around authentication? I have a default auth applied to everything, then marked a controller with [AllowAnonymous] to serve landing page, error page, etc. When the browser tries to load /serviceworker with this package it gets redirected to the login page. Any way around that?

Thanks!

Service worker does not successfully serve the manifest start_url

Hi, I followed your tutorial and I got a problem with the start_url.
I have this configuration:

{
  "name": "myName",
  "short_name": "myShortName",
  "description": "My description",
  "icons": [
    {
      "src": "/img/logo/logo192x192.png",
      "sizes": "192x192"
    },
    {
      "src": "/img/logo/logo512x512.png",
      "sizes": "512x512"
    }
  ],
  "background_color": "#fff",
  "theme_color": "#ba3030",
  "display": "standalone",
  "start_url": "/"
}

The service worker is working with the following configuration.

services.AddProgressiveWebApp(new PwaOptions { RegisterServiceWorker = true });

When I run the google audit test I'm getting a 91 score.
Only problem I have:

Service worker does not successfully serve the manifest start_url
It will now not prompt the question to install my website on a mobile phone.

What am I doing wrong?
I tried several start_url
../
/
./
.
Home/Index

All not working.

Release pls ? :D

Can you make a new release pls ?
I would use the ci feed but i can't find it, and appveyor is deleting packages after 6 months.

Thanks

While refreshing the pages other than home page gives page can't be cached

Hi,

While refreshing the pages other than home page gives page can't be cached.pls help me to fix it

below is my code

services.AddProgressiveWebApp(new PwaOptions
{
CacheId = "Worker 1.1",
Strategy = ServiceWorkerStrategy.NetworkFirst,
RoutesToPreCache = "/,/Home/Index, /Shared/_Layout,/Shared/Error",
OfflineRoute = "index.html",
});

Thanks

amp page problem

This script creates a problem with an AMP page
<script nws-csp-add-nonce='true'>'serviceWorker'in navigator&&navigator.serviceWorker.register('/serviceworker')</script>

Published Application fails with HTTP 500

Hi,

I installed the package as described in the HowTo in a Razor-Pages-Asp.Net Core 2.0-App.

In my local developer-enviroment everything works fine. But if i published my application to the production-Server i get a HTTP 500-Error. There are no errors in the stdout-Logs and there are no errors in the windows Event-log.

If I disable services.AddProgressiveWebApp(); and publish again, my web-app works fine.

What could be the cause?

Error with .NET Core 2.1 and Razor Pages

My configuration: localhost, Windows 10, Visual Studio 2017, ASP.NET Core 2.1, Razor Pages. The WebEssentials.AspNetCore.PWA package injects 2 lines into _Layout.cshtml. The first line, in the head, should be link rel="manifest" href="/manifest.webmanifest" /. Instead, in my configuration it generates link rel="manifest" href=" ~ /manifest.webmanifest" /. See the extra tilde . This causes chrome to fail to locate the manifest.webmanifest. The second line it injects, in html region, should be script nws-csp-add-nonce='true'>'serviceWorker' in navigator && navigator.serviceWorker.register('/serviceworker') /script. Instead it is injecting script nws-csp-add-nonce='true' 'serviceWorker'in navigator&&navigator.serviceWorker.register('~/serviceworker') /script>. Again, see the tilde. This cause the service worker registration to fail be cause Chrome can't locate it. My question is what do I need to do to make it generate the code correctly? Is it because I am using .NET Core 2.1 instead of .NET Core 2.0 or is there something else I need to change? Thanks.

Installability

Hi
I am the message :
No matching service worker detected.You may need to reload the page , or check that the service worker for the current page also controls the start URL from the manifest.
Thanks

Enhancements...

First I must say that this is great.

I had a bit of a problem getting the service worker to work using windows authentication, after figuring out the 401 error I modified the function updateStaticCache in the javascript files so that the credentials could be included. This seemed to work, it would be nice if on your next versions you could include this feature. The next feature I would like you to add is an exclusion list of routes that should not be cached, So I added a property "RoutesDoNotCache" to the PwaOptions class, and coppied most of the logic that the property "RoutesToPreCache" does and modified the addToCache in the javascript files.

Thanks for your great work
George

function updateStaticCache() {
        return caches.open(version)
            .then(function (cache) {
                //return cache.addAll([
                //    offlineUrl,
                //    {routes}
                //]);
                var myRoutes = [
                    offlineUrl,
                    {routes}
                ];
                return cache.addAll(myRoutes.map(url => new Request(url, { credentials: 'include' })));
            });
    }


 function addToCache(request, response) {
        if (!response.ok)
            return;

        var myRoutes = [{donotcache}];

        if (myRoutes.length) {
            var ignoreRequests = new RegExp('(' + myRoutes.join('(\/?)|\\') + ')$');
            if (ignoreRequests.test(request.url)) {
                return;
            }
        }

        var copy = response.clone();
        caches.open(version)
            .then(function (cache) {
                cache.put(request, copy);
            });
    }

Is this project dead?

Hi,

there are no commits since 3 months now, is this project still alive?
Will it ported to net core 2.1? Or will it maybe a core/build in part of .net core 2.1?

Just asking, because I'm starting a project right now and would love to build progressive web app support from the beginning, but I don't want to use a already dead horse.

Kind regards

AuthorizeFilter bypass?

Hi,

My site currently uses the following to require authorization by default and I use [AllowAnonymous] to bypass
options.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build()));

How could I handle that the /serviceworker url shouldn't be authorized, currently it's returning a 404

This nuget doesn't work with Blazor

Hi,

This nuget doesn't work with Blazor. I am getting compile time error when adding this nuget to Client Side Blazor CS Project (Targeting .NET Stanndard 2.0)

ServerSide Blazor in .net core 3.0

Should this work in ServerSide Blazor in .net core 3.0?

It seems ok, but I don't get any install promp nor the Option "send to Homescreen".

404 when manifest link element is created

When the manifest link is created th element is prefixed with a tilde ~

<link rel="manifest" href="~/manifest.webmanifest">

which is causing a 404 as per below:

GET https://localhost:5001/~/manifest.webmanifest 404 (Not Found)

Add Google Workbox support to cache all files

Hi,

Add Google Workbox support to cache all files. this very useful for a SPA app. e.g. Blazor, where i need to cache everything (including blazor pages e.g. counter, fetchdata etc.)

offline page with iOS Safari

After a power off the app goes always to offline page and I need to clear the cache of Safari. I'm developing an ASP.NET Core 3 MVC application. I'm trying every ServiceWorkerStrategy but nothing change.
Is there someone that encoutered similiar problems?

Service worker error with default Web Application template

I created an MVC Web Application without authentication with the latest version of Visual Studio 2017 (15.4.4) and .NET Core 2.0.3. But the Service Worker fails to register. Under the Application tab in chrome tools, under Service Workers I find the following error:

(unknown) #1: ServiceWorker failed to install: ServiceWorker failed to handle event (event.waitUntilPromise rejected)
#1: Uncaught (in promise) TypeError: Cannot read property 'addAll' of undefined

The service worker code is:

(function () {
    'use strict';

    // Update 'version' if you need to refresh the cache
    var version = 'v1.0::CacheFirstSafe';
    var offlineUrl = "/offline.html";

    // Store core files in a cache (including a page to display when offline)
    function updateStaticCache() {
        return caches.open(version)
            .then(function (cache) {
                return cache.addAll([
                    offlineUrl,
                    
                ]);
            });
    }

    function addToCache(request, response) {
        var copy = response.clone();
        caches.open(version)
              .then(function (cache) {
                  cache.put(request, copy);
              });
    }

    self.addEventListener('install', function (event) {
        event.waitUntil(updateStaticCache());
    });

    self.addEventListener('activate', function (event) {
        event.waitUntil(
            caches.keys()
                .then(function (keys) {
                    // Remove caches whose name is no longer valid
                    return Promise.all(keys
                        .filter(function (key) {
                            return key.indexOf(version) !== 0;
                        })
                        .map(function (key) {
                            return caches.delete(key);
                        })
                    );
                })
        );
    });

    self.addEventListener('fetch', function (event) {
        var request = event.request;

        // Always fetch non-GET requests from the network
        if (request.method !== 'GET') {
            event.respondWith(
                fetch(request)
                    .catch(function () {
                        return caches.match(offlineUrl);
                    })
            );
            return;
        }

        // For HTML requests, try the network first, fall back to the cache, finally the offline page
        if (request.headers.get('Accept').indexOf('text/html') !== -1) {
            event.respondWith(
                fetch(request)
                    .then(function (response) {
                        // Stash a copy of this page in the cache
                        addToCache(request, response);
                        return response;
                    })
                    .catch(function () {
                        return caches.match(request)
                            .then(function (response) {
                                return response || caches.match(offlineUrl);
                            });
                    })
            );
            return;
        }

        // For non-HTML requests, look in the cache first, fall back to the network
        event.respondWith(
            caches.match(request)
                .then(function (response) {
                    return response || fetch(request)
                        .then(function (response) {
                            if (request.url.match(/(\?|&)v=/ig)) {
                                // Stash a copy of this file in the cache if it contains a fingerprint ala '?v=randombits'
                                addToCache(request, response);
                            }
                            return response;
                        })
                        .catch(function () {
                            // If the request is for an image, show an offline placeholder
                            if (request.headers.get('Accept').indexOf('image') !== -1) {
                                return new Response('<svg role="img" aria-labelledby="offline-title" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg"><title id="offline-title">Offline</title><g fill="none" fill-rule="evenodd"><path fill="#D8D8D8" d="M0 0h400v300H0z"/><text fill="#9B9B9B" font-family="Helvetica Neue,Arial,Helvetica,sans-serif" font-size="72" font-weight="bold"><tspan x="93" y="172">offline</tspan></text></g></svg>', { headers: { 'Content-Type': 'image/svg+xml' } });
                            }
                        });
                })
        );
    });

})();

I made no alterations to the default Startup class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Rewrite;

namespace CorePWASample
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddProgressiveWebApp();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            var options = new RewriteOptions().AddRedirectToHttps();
            app.UseRewriter(options);

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Chrome tools marks the error on the cache.addAll() function inside updateStaticCache()

Don't know how to solve this. The cache seems to be undefined at this moment.

Adding Multiple Cache Id's

How can i add multiple cache Id's . For example dataCahcev1="/getprofiles" with NetworkFirst and normal cache like normalCache="/js, /css" with CacheFirst Strategy ?

Question about ServiceWorker endpoint cache duration

Hi,
serviceworker endpoing sets this header :
Response.Headers[HeaderNames.CacheControl] = $"max-age={60 * 60 * 24 * 30}"; // Cache for 30 days
so if we have to deploy a new version of the web application (changing the cache Id) it can't be refreshed by the browser because it will not download a new serviceworker for 30 days.
I do not think this is the most preferable behavior, can we at least make it configurable ?

Uncaught (in promise) TypeError: Request failed

I am getting the titled error once I have deployed my application to Azure, has anyone else done this with success?

I noticed that locally nothing was caching initially so I added the following to Startup.cs
services.AddProgressiveWebApp(new PwaOptions { CacheId = "Worker 1.1", Strategy = ServiceWorkerStrategy.CacheFirst, RoutesToPreCache = "/Home/Index, /Shared/_Layout,/Shared/Error" });

I was hoping all was then good as it successfully works offline on my machine but as mentioned once deployed to live environment it no longer works, feel free to take a look for yourselves at the error log in chrome: https://hello-pwa.azurewebsites.net/

VSIISExeLauncher error

Hi!

I downloaded the current master and tried to run samples project, but chrome opens, wait +- 3secs and close.
Looking at event log, i can seee this:
Application 'MACHINE/WEBROOT/APPHOST/SAMPLE' with physical root 'C:\Temp\WebEssentials.AspNetCore.ServiceWorker\sample' failed to start process with commandline 'c:\program files (x86)\microsoft visual studio\2017\enterprise\common7\ide\extensions\microsoft\web tools\projectsystem\VSIISExeLauncher.exe -argFile "C:\Users\Marcelo\AppData\Local\Temp\tmpB92F.tmp"', ErrorCode = '0x80004005 : 0.

Anyone knows why?

My enviroment:
W10 Home SL with latest updates.
Vs 201715.8.1 runing with adm

Inline service worker script fails to register with restrictive Csp policy

Using a content-security-policy of 'self' for script sources will make the <script> tag added by the following line of code to fail. At current, there appears to be no built-in way to include a nonce for this script tag.

public void ConfigureServices(IServieCollection services)
    // ...
    services.AddProgressiveWebApp();
}

How do we enable this script tag to work without allowing unsafe-inline for script sources in Csp?

PWA not working in offline mode

In Offline mode it is not working.
It shows offline. Service Worker working. But not tacking data from cache first and other options like cache first network first. How can i chose theme?
After installation how can i use all pwa benefits ?

Service Worker not registering in production environment

Hi, thanks for this nice package, it seems the service worker is not loading at the bottom of the body element in the html dom on my production environment only. Locally I can test the app and all seems ok when I test it with lighthouse.

I'm not sure what's wrong so here is the settings I'm using:

services.AddProgressiveWebApp( new PwaOptions { Strategy = ServiceWorkerStrategy.CacheFirst, RegisterServiceWorker = true, RegisterWebmanifest = true }, "manifest.json");

whithout the manifest.json string it wasn't adding the meta and link tags in the head.

Could you try to help me out with this issue please?

Raises System.InvalidOperationException on production server while working correctly in Visual Studio

While it worked like a charm running inside Visual Studio 2017 under Windows 10 I got

System.InvalidOperationException: Unable to resolve service for type 'Microsoft. AspNetCore.Http.IHttpContextAccessor' while attempting to activate 'WebEssential s.AspNetCore.Pwa.ServiceWorkerTagHelperComponent'.

while running it on one of my Windows 2012 R2 production servers. Had to add

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

to ConfigureServices.

Need a way to configure WebManifestRoute constant.

I saw in the source code that the route where the browser asks for the web manifest is configured on the WebManifestRoute constant. How do I modify it? My intellisense doesn't show any option when creasting a new PwaOptions object.

PS. Pretty new to the dotnet core side of things. Haven't used MS stack in 5 years.

This is needed due to hosting on IIS on a different base route such as domain.com/AppName

How to apply app shell architecture?

Hi,

I would like to set up an app shell architecture including dynamic content which is not cached. Therefore, I would explicitly have to cache my index.cshtml with the CacheFingerprinted strategy. This does not seem possible.
The documentation states "This strategy is useful for scenarios in which you don't wish to cache certain resources [...] but still wish to cache the app core assets (HTML, CSS, JS)."
How can HTML be cached?

Thanks in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.