-
Notifications
You must be signed in to change notification settings - Fork 10.4k
PWA template #18878
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
PWA template #18878
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
dda2211
Add service worker
SteveSandersonMS 79e3ab9
Add manifest
SteveSandersonMS 1820375
Bring back BaselineTest.cs
SteveSandersonMS 43b308e
Add baselines for blazorwasm templates
SteveSandersonMS 251ca60
Add publishing test for PWA template
SteveSandersonMS 176c9be
Baseline fixes
SteveSandersonMS 6b2bc43
Fix baseline test logic to allow for multi-project outputs
SteveSandersonMS 8f0afb2
Remove non-blazorwasm baselines, since this branch now only covers bl…
SteveSandersonMS a7177ee
Add test for PWA publish output
SteveSandersonMS ac4f161
Beginning generation of assets manifest
SteveSandersonMS 8fe2b09
Generate assets manifest including blazor outputs
SteveSandersonMS cd83378
Tweaks
SteveSandersonMS f34f4c0
Write assets manifest in JSON form
SteveSandersonMS c7bbf97
Publish service worker
SteveSandersonMS 6cf96c2
Better API
SteveSandersonMS 995704d
More resilience
SteveSandersonMS 1085040
Better API again
SteveSandersonMS c6537e5
Make ComputeBlazorAssetsManifestItems public as people will need to c…
SteveSandersonMS 68a6224
Exclude service worker files from assets manifest
SteveSandersonMS 35f2579
Use web standard format for hash
SteveSandersonMS 2152288
Update project template
SteveSandersonMS f198938
In assets manifest, only include items being published
SteveSandersonMS 1db62db
Renames
SteveSandersonMS accaad8
Compute default assets manifest version by combining hashes
SteveSandersonMS 2850cd0
Emit sw manifest in .js form
SteveSandersonMS c62d347
Update service worker in project
SteveSandersonMS cf1ca50
Actually isolate browser instances when requested during E2E tests
SteveSandersonMS a95170a
E2E test for published PWA operating offline
SteveSandersonMS bae9941
Fix SWAM path in template
SteveSandersonMS 1be8a95
Clarify targets
SteveSandersonMS File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
82 changes: 82 additions & 0 deletions
82
src/Components/Blazor/Build/src/Tasks/GenerateServiceWorkerAssetsManifest.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.Serialization.Json; | ||
using System.Text; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Build.Utilities; | ||
|
||
namespace Microsoft.AspNetCore.Blazor.Build | ||
{ | ||
public class GenerateServiceWorkerAssetsManifest : Task | ||
{ | ||
[Required] | ||
public string Version { get; set; } | ||
|
||
[Required] | ||
public ITaskItem[] AssetsWithHashes { get; set; } | ||
|
||
[Required] | ||
public string OutputPath { get; set; } | ||
|
||
public override bool Execute() | ||
{ | ||
using var fileStream = File.Create(OutputPath); | ||
WriteFile(fileStream); | ||
return true; | ||
} | ||
|
||
internal void WriteFile(Stream stream) | ||
{ | ||
var data = new AssetsManifestFile | ||
{ | ||
version = Version, | ||
assets = AssetsWithHashes.Select(item => new AssetsManifestFileEntry | ||
{ | ||
url = item.GetMetadata("AssetUrl"), | ||
hash = $"sha256-{item.GetMetadata("FileHash")}", | ||
}).ToArray() | ||
}; | ||
|
||
using var streamWriter = new StreamWriter(stream, Encoding.UTF8, bufferSize: 50, leaveOpen: true); | ||
streamWriter.Write("self.assetsManifest = "); | ||
streamWriter.Flush(); | ||
|
||
using var jsonWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, ownsStream: false, indent: true); | ||
new DataContractJsonSerializer(typeof(AssetsManifestFile)).WriteObject(jsonWriter, data); | ||
jsonWriter.Flush(); | ||
|
||
streamWriter.WriteLine(";"); | ||
} | ||
|
||
#pragma warning disable IDE1006 // Naming Styles | ||
public class AssetsManifestFile | ||
{ | ||
/// <summary> | ||
/// Gets or sets a version string. | ||
/// </summary> | ||
public string version { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the assets. Keys are URLs; values are base-64-formatted SHA256 content hashes. | ||
/// </summary> | ||
public AssetsManifestFileEntry[] assets { get; set; } | ||
} | ||
|
||
public class AssetsManifestFileEntry | ||
{ | ||
/// <summary> | ||
/// Gets or sets the asset URL. Normally this will be relative to the application's base href. | ||
/// </summary> | ||
public string url { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets the file content hash. This should be the base-64-formatted SHA256 value. | ||
/// </summary> | ||
public string hash { get; set; } | ||
} | ||
#pragma warning restore IDE1006 // Naming Styles | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
98 changes: 98 additions & 0 deletions
98
src/Components/Blazor/Build/src/targets/ServiceWorkerAssetsManifest.targets
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<Project> | ||
|
||
<PropertyGroup> | ||
<_BlazorCopyFilesToOutputDirectoryDependsOn> | ||
$(_BlazorCopyFilesToOutputDirectoryDependsOn); | ||
_ComputeServiceWorkerAssetsManifestInputs; | ||
_WriteServiceWorkerAssetsManifest; | ||
</_BlazorCopyFilesToOutputDirectoryDependsOn> | ||
</PropertyGroup> | ||
|
||
<Target Name="_ComputeServiceWorkerAssetsManifestInputs" | ||
Condition="'$(ServiceWorkerAssetsManifest)' != ''" | ||
DependsOnTargets="PrepareBlazorOutputs"> | ||
|
||
<PropertyGroup> | ||
<_ServiceWorkerAssetsManifestIntermediateOutputPath>$(BlazorIntermediateOutputPath)serviceworkerassets.js</_ServiceWorkerAssetsManifestIntermediateOutputPath> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<!-- Include _framework/* content --> | ||
<ServiceWorkerAssetsManifestItem | ||
Include="@(BlazorOutputWithTargetPath)" | ||
Condition="$([System.String]::Copy('%(BlazorOutputWithTargetPath.TargetOutputPath)').Replace('\','/').StartsWith('dist/'))"> | ||
<AssetUrl>$([System.String]::Copy('%(BlazorOutputWithTargetPath.TargetOutputPath)').Replace('\','/').Substring(5))</AssetUrl> | ||
</ServiceWorkerAssetsManifestItem> | ||
|
||
<!-- Include content from wwwroot --> | ||
<ServiceWorkerAssetsManifestItem | ||
Include="@(ContentWithTargetPath)" | ||
Condition=" | ||
('%(ContentWithTargetPath.CopyToPublishDirectory)' == 'Always' OR '%(ContentWithTargetPath.CopyToPublishDirectory)' == 'PreserveNewest') | ||
AND $([System.String]::Copy('%(ContentWithTargetPath.TargetPath)').Replace('\','/').StartsWith('wwwroot/'))"> | ||
<AssetUrl>$([System.String]::Copy('%(ContentWithTargetPath.TargetPath)').Replace('\','/').Substring(8))</AssetUrl> | ||
</ServiceWorkerAssetsManifestItem> | ||
|
||
<!-- Include SWA from references --> | ||
<ServiceWorkerAssetsManifestItem | ||
Include="@(StaticWebAsset)" | ||
Condition="'%(StaticWebAsset.SourceType)' != ''"> | ||
<AssetUrl>%(StaticWebAsset.BasePath)/%(StaticWebAsset.RelativePath)</AssetUrl> | ||
</ServiceWorkerAssetsManifestItem> | ||
</ItemGroup> | ||
|
||
</Target> | ||
|
||
<UsingTask TaskName="GenerateServiceWorkerAssetsManifest" AssemblyFile="$(BlazorTasksPath)" /> | ||
|
||
<Target Name="_WriteServiceWorkerAssetsManifest" | ||
Inputs="@(ServiceWorkerAssetsManifestItem)" | ||
Outputs="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" | ||
DependsOnTargets="_ComputeServiceWorkerAssetsManifestFileHashes; _ComputeDefaultServiceWorkerAssetsManifestVersion"> | ||
|
||
<GenerateServiceWorkerAssetsManifest | ||
Version="$(ServiceWorkerAssetsManifestVersion)" | ||
AssetsWithHashes="@(_ServiceWorkerAssetsManifestItemWithHash)" | ||
OutputPath="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" /> | ||
|
||
<ItemGroup> | ||
<BlazorOutputWithTargetPath | ||
Include="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" | ||
TargetOutputPath="$(BaseBlazorDistPath)$(ServiceWorkerAssetsManifest)" /> | ||
|
||
<FileWrites Include="$(_ServiceWorkerAssetsManifestIntermediateOutputPath)" /> | ||
</ItemGroup> | ||
|
||
</Target> | ||
|
||
<Target Name="_ComputeServiceWorkerAssetsManifestFileHashes"> | ||
<GetFileHash Files="@(ServiceWorkerAssetsManifestItem)" Algorithm="SHA256" HashEncoding="base64"> | ||
<Output TaskParameter="Items" ItemName="_ServiceWorkerAssetsManifestItemWithHash" /> | ||
</GetFileHash> | ||
</Target> | ||
|
||
<!-- | ||
If no ServiceWorkerAssetsManifestVersion was specified, we compute a default value by combining all the asset hashes. | ||
This is useful because then clients will only have to repopulate caches if the contents have changed. | ||
--> | ||
<Target Name="_ComputeDefaultServiceWorkerAssetsManifestVersion" | ||
Condition="'$(ServiceWorkerAssetsManifestVersion)' == ''"> | ||
<PropertyGroup> | ||
<_CombinedHashIntermediatePath>$(BlazorIntermediateOutputPath)serviceworkerhashes.txt</_CombinedHashIntermediatePath> | ||
</PropertyGroup> | ||
|
||
<WriteLinesToFile | ||
File="$(_CombinedHashIntermediatePath)" | ||
Lines="@(_ServiceWorkerAssetsManifestItemWithHash->'%(FileHash)')" | ||
Overwrite="true" /> | ||
|
||
<GetFileHash Files="$(_CombinedHashIntermediatePath)" Algorithm="SHA256" HashEncoding="base64"> | ||
<Output TaskParameter="Items" ItemName="_ServiceWorkerAssetsManifestCombinedHash" /> | ||
</GetFileHash> | ||
|
||
<PropertyGroup> | ||
<ServiceWorkerAssetsManifestVersion>$([System.String]::Copy('%(_ServiceWorkerAssetsManifestCombinedHash.FileHash)').Substring(0, 8))</ServiceWorkerAssetsManifestVersion> | ||
</PropertyGroup> | ||
</Target> | ||
|
||
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
@ECHO OFF | ||
|
||
%~dp0..\..\startvs.cmd %~dp0Components.sln | ||
%~dp0..\..\startvs.cmd %~dp0Blazor.sln |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+8.74 KB
...azorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
...plates/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/manifest.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "BlazorWasm-CSharp", | ||
"short_name": "BlazorWasm-CSharp", | ||
"start_url": "/", | ||
"display": "standalone", | ||
"background_color": "#ffffff", | ||
"theme_color": "#03173d", | ||
"icons": [ | ||
{ | ||
"src": "icon-512.png", | ||
"type": "image/png", | ||
"sizes": "512x512" | ||
} | ||
] | ||
} |
4 changes: 4 additions & 0 deletions
4
...es/BlazorWasm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/service-worker.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// In development, always fetch from the network and do not enable offline support. | ||
// This is because caching would make development more difficult (changes would not | ||
// be reflected on the first load after each change). | ||
self.addEventListener('fetch', () => { }); |
48 changes: 48 additions & 0 deletions
48
...asm.ProjectTemplates/content/BlazorWasm-CSharp/Client/wwwroot/service-worker.published.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Caution! Be sure you understand the caveats before publishing an application with | ||
// offline support. See https://aka.ms/blazor-offline-considerations | ||
|
||
self.importScripts('./service-worker-assets.js'); | ||
self.addEventListener('install', event => event.waitUntil(onInstall(event))); | ||
self.addEventListener('activate', event => event.waitUntil(onActivate(event))); | ||
self.addEventListener('fetch', event => event.respondWith(onFetch(event))); | ||
|
||
const cacheNamePrefix = 'offline-cache-'; | ||
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`; | ||
javiercn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/ ]; | ||
const offlineAssetsExclude = [ /^service-worker\.js$/ ]; | ||
|
||
javiercn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
async function onInstall(event) { | ||
console.info('Service worker: Install'); | ||
|
||
// Fetch and cache all matching items from the assets manifest | ||
const assetsRequests = self.assetsManifest.assets | ||
.filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url))) | ||
.filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url))) | ||
.map(asset => new Request(asset.url, { integrity: asset.hash })); | ||
await caches.open(cacheName).then(cache => cache.addAll(assetsRequests)); | ||
} | ||
|
||
async function onActivate(event) { | ||
console.info('Service worker: Activate'); | ||
|
||
// Delete unused caches | ||
const cacheKeys = await caches.keys(); | ||
await Promise.all(cacheKeys | ||
.filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName) | ||
.map(key => caches.delete(key))); | ||
} | ||
|
||
async function onFetch(event) { | ||
let cachedResponse = null; | ||
if (event.request.method === 'GET') { | ||
// For all navigation requests, try to serve index.html from cache | ||
// If you need some URLs to be server-rendered, edit the following check to exclude those URLs | ||
const shouldServeIndexHtml = event.request.mode === 'navigate'; | ||
|
||
const request = shouldServeIndexHtml ? 'index.html' : event.request; | ||
const cache = await caches.open(cacheName); | ||
cachedResponse = await cache.match(request); | ||
} | ||
|
||
return cachedResponse || fetch(event.request); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.