You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel10+Vue3+InertiaJs1.x项目转PWA的改造咨询

改造Laravel 10 + Inertia + Vue3项目为PWA(仅离线功能)

一、先搞定Web App Manifest(和Inertia完全不冲突)

manifest只是定义PWA的基础元数据,和Inertia的路由、数据传递逻辑完全无关,放心加就行:

  • 在项目public目录下创建manifest.json,示例内容:
{
  "name": "你的项目名称",
  "short_name": "短名称",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#3b82f6",
  "icons": [
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
  • 在Laravel的主模板(比如resources/views/app.blade.php)的<head>里添加:
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#3b82f6">
  • 把图标文件放到public/icons目录下,尺寸按manifest里的要求准备。

二、配置Service Worker(核心,处理离线缓存)

这部分是重点,要适配Inertia的请求逻辑,避免冲突:

1. 注册Service Worker

在Vue入口文件(resources/js/app.js)里添加注册代码,注意只在生产环境启用:

if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(registration => {
        console.log('SW registered: ', registration);
      })
      .catch(registrationError => {
        console.log('SW registration failed: ', registrationError);
      });
  });
}

2. 编写Service Worker逻辑(public/sw.js)

因为你的项目没有独立API,都是Inertia的页面请求(带X-Inertia请求头),所以缓存策略要区分静态资源和页面请求:

const CACHE_NAME = 'your-app-cache-v1';
const STATIC_ASSETS = [
  '/',
  '/app.js', // 注意如果用Vite,文件名可能带哈希,需要调整
  '/app.css',
  '/manifest.json',
  '/icons/icon-192x192.png',
  '/icons/icon-512x512.png'
];

// 安装阶段:缓存核心静态资源
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(STATIC_ASSETS))
      .then(() => self.skipWaiting())
  );
});

// 激活阶段:清理旧缓存
self.addEventListener('activate', (event) => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.filter(name => name !== CACHE_NAME)
          .map(name => caches.delete(name))
      );
    })
  );
});

// Fetch事件:处理请求缓存
self.addEventListener('fetch', (event) => {
  const request = event.request;

  // 跳过非GET请求(Inertia的页面请求都是GET)
  if (request.method !== 'GET') return;

  // 处理Inertia页面请求(带X-Inertia头)
  if (request.headers.get('X-Inertia')) {
    event.respondWith(
      caches.match(request)
        .then(cachedResponse => {
          // 离线时用缓存,在线时更新缓存
          const fetchPromise = fetch(request)
            .then(networkResponse => {
              caches.open(CACHE_NAME)
                .then(cache => cache.put(request, networkResponse.clone()));
              return networkResponse;
            });
          return cachedResponse || fetchPromise;
        })
    );
    return;
  }

  // 处理静态资源(优先用缓存)
  event.respondWith(
    caches.match(request)
      .then(cachedResponse => cachedResponse || fetch(request))
  );
});

三、避免Inertia和Service Worker冲突的关键细节

  • 区分Inertia请求:通过X-Inertia请求头识别页面请求,单独处理缓存,不要把Inertia的请求当成普通静态资源缓存
  • 静态资源哈希:确保Vite/Mix生成的静态资源文件名带哈希(比如app.abc123.js),这样Service Worker能正确识别资源更新,避免缓存旧资源
  • 开发环境禁用:开发时可以注释掉Service Worker注册代码,或者用Chrome DevTools的Application面板手动注销,避免缓存影响开发
  • 不要缓存错误页面:可以在fetch事件里判断响应状态码,比如只缓存200的响应,避免把404/500页面缓存下来

四、测试离线功能

  1. 打包生产环境代码(npm run build + php artisan optimize)
  2. 用HTTPS部署(或者用localhost,Chrome允许localhost的PWA)
  3. 打开Chrome DevTools → Application → Service Workers,确认SW已注册
  4. 勾选"Offline"选项,刷新页面,测试页面和静态资源是否能正常加载
  5. 导航到几个页面后离线,测试页面跳转是否正常

内容的提问来源于stack exchange,提问作者Christian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:58:28