Blazor是微软基于.NET生态推出的前端开发框架,允许开发者使用C#替代JavaScript完成前端交互逻辑,而PWA(渐进式Web应用)可以让Web应用具备离线访问、添加到桌面、推送通知等接近原生应用的体验。将两者结合可以快速构建兼具开发效率和用户体验的应用。

创建Blazor PWA项目的基础步骤
首先我们可以通过Visual Studio或者命令行工具创建Blazor PWA项目,这里以命令行方式为例,使用.NET CLI执行以下命令创建Blazor WebAssembly PWA项目:
dotnet new blazorwasm -pwa -o BlazorPwaDemo
上述命令中-pwa参数会自动为项目添加PWA相关的默认配置,包括Manifest文件、Service Worker相关文件以及对应的注册逻辑。如果是已有的Blazor项目,也可以手动添加PWA相关配置。
核心配置文件说明
创建完成后,项目中会出现两个PWA核心配置文件,分别是manifest.webmanifest和service-worker.js,下面分别说明其作用。
Manifest配置文件
manifest.webmanifest用于定义PWA应用的基础信息,比如应用名称、图标、启动模式等,浏览器会根据这个文件的内容生成桌面快捷方式、启动屏等。默认的配置文件内容如下:
{
"name": "BlazorPwaDemo",
"short_name": "BlazorPwaDemo",
"description": "Blazor PWA Demo Application",
"start_url": "./",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#03173d",
"icons": [
{
"src": "icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
我们可以根据实际需求修改这些字段,比如更换short_name为更简短的应用名称,替换icons数组中的图标路径为自定义的应用图标,调整theme_color为应用的主题色。
Service Worker配置文件
service-worker.js是PWA的离线缓存核心,负责拦截网络请求、缓存静态资源和API响应,实现离线访问能力。Blazor PWA默认生成的Service Worker已经包含了基础的静态资源缓存逻辑,我们可以根据需要扩展缓存策略。默认的Service Worker内容如下:
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));
});
async function onInstall(event) {
const assets = self.assetsManifest.assets
.filter(asset => asset.url.indexOf('assets/') !== -1)
.map(asset => new Request(asset.url, { integrity: asset.hash }));
const cache = await caches.open('blazor-pwa-cache');
await cache.addAll(assets);
}
async function onActivate(event) {
const cacheNames = await caches.keys();
await Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== 'blazor-pwa-cache') {
return caches.delete(cacheName);
}
})
);
}
async function onFetch(event) {
const cache = await caches.open('blazor-pwa-cache');
const cachedResponse = await cache.match(event.request);
if (cachedResponse) {
return cachedResponse;
}
try {
const networkResponse = await fetch(event.request);
if (networkResponse.ok) {
await cache.put(event.request, networkResponse.clone());
}
return networkResponse;
} catch (err) {
return new Response('Network error occurred', { status: 503 });
}
}
注册PWA相关服务
在Blazor项目中,需要在Program.cs中注册PWA相关的服务,确保Manifest和Service Worker能够被正确加载。如果是通过-pwa参数创建的项目,这部分配置已经自动完成,代码如下:
using BlazorPwaDemo;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
// 注册PWA相关服务
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
同时在wwwroot/index.html中,已经自动添加了Manifest引用和Service Worker注册逻辑,代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>BlazorPwaDemo</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
<link href="BlazorPwaDemo.styles.css" rel="stylesheet" />
<!-- 引用Manifest文件 -->
<link rel="manifest" href="manifest.webmanifest" />
<link rel="apple-touch-icon" href="icon-512.png" />
</head>
<body>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
<!-- 注册Service Worker -->
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./service-worker.js');
}
</script>
</body>
</html>
测试与优化PWA应用
完成配置后,我们可以启动项目测试PWA功能。在Chrome浏览器中打开应用,打开开发者工具的Application面板,在Manifest和Service Workers选项卡中可以查看配置是否生效。如果想要测试离线功能,可以在Service Workers选项卡中勾选Offline选项,刷新页面后应用依然可以正常加载静态资源。
如果需要优化PWA的缓存策略,可以修改service-worker.js文件,比如添加API响应缓存、设置缓存过期时间等。以下是一个扩展后的缓存逻辑示例,增加了对API请求的缓存:
async function onFetch(event) {
const cache = await caches.open('blazor-pwa-cache');
const cachedResponse = await cache.match(event.request);
// 如果是API请求,缓存1小时
if (event.request.url.includes('/api/')) {
if (cachedResponse) {
const cachedDate = new Date(cachedResponse.headers.get('date'));
const now = new Date();
// 缓存超过1小时则重新请求
if (now - cachedDate < 3600000) {
return cachedResponse;
}
}
try {
const networkResponse = await fetch(event.request);
if (networkResponse.ok) {
await cache.put(event.request, networkResponse.clone());
}
return networkResponse;
} catch (err) {
return cachedResponse || new Response('API request failed', { status: 503 });
}
}
// 静态资源直接返回缓存
if (cachedResponse) {
return cachedResponse;
}
try {
const networkResponse = await fetch(event.request);
if (networkResponse.ok) {
await cache.put(event.request, networkResponse.clone());
}
return networkResponse;
} catch (err) {
return new Response('Network error occurred', { status: 503 });
}
}
另外如果需要支持PWA的更新提示,可以在Blazor组件中添加Service Worker更新检测逻辑,当检测到新版本的Service Worker时提示用户刷新页面,确保用户使用最新的应用版本。
BlazorPWAASP.NET_CoreManifestService_Worker修改时间:2026-07-05 04:00:15