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

如何在Vite构建过程中获取构建产物资源?

实现自定义Vite Service Worker插件(含资源注入与Git Hash更新)

核心思路

利用Vite/Rollup的构建钩子直接获取产物资源列表,无需额外构建后脚本;通过Git Commit Hash作为Service Worker的更新标识,确保资源更新时SW能触发重新安装。


步骤1:编写自定义Vite插件

在插件中完成三件事:获取Git Commit Hash、收集构建产物资源、将两者注入到Service Worker文件中。

import { execSync } from 'child_process';
import fs from 'fs';
import path from 'path';

export default function vitePluginCustomSW() {
  let commitHash = '';
  let assetList = [];

  return {
    name: 'vite-plugin-custom-sw',
    // 初始化时获取Git Commit Hash
    buildStart() {
      try {
        commitHash = execSync('git rev-parse HEAD').toString().trim();
      } catch (e) {
        // 本地无Git环境时用随机字符串兜底
        commitHash = Math.random().toString(36).substring(2, 10);
      }
    },
    // 收集所有构建产物资源(chunk和静态资源)
    generateBundle(_, bundle) {
      assetList = Object.values(bundle).map(item => {
        // 排除SW自身文件,避免循环缓存
        if (item.fileName.includes('sw.js')) return null;
        return item.fileName;
      }).filter(Boolean);
    },
    // 生产环境:修改SW文件,注入资源列表和Commit Hash
    writeBundle() {
      const swPath = path.resolve(__dirname, 'src/sw.js');
      let swContent = fs.readFileSync(swPath, 'utf-8');
      
      // 替换占位符为实际数据
      swContent = swContent.replace(
        '__COMMIT_HASH__',
        JSON.stringify(commitHash)
      ).replace(
        '__ASSET_LIST__',
        JSON.stringify(assetList)
      );

      // 写入最终的SW文件到构建目录
      fs.writeFileSync(path.resolve(__dirname, 'dist/sw.js'), swContent);
    },
    // 开发环境:注入资源列表到SW(可选,开发环境也支持离线)
    configureServer(server) {
      server.middlewares.use((req, res, next) => {
        if (req.url === '/sw.js') {
          let swContent = fs.readFileSync(path.resolve(__dirname, 'src/sw.js'), 'utf-8');
          // 开发环境下资源路径可能不同,这里可以动态获取当前编译的资源
          // 简单处理:直接列出src下的静态资源和入口文件
          const devAssets = ['/src/main.js', '/index.html'];
          swContent = swContent.replace(
            '__COMMIT_HASH__',
            JSON.stringify(commitHash)
          ).replace(
            '__ASSET_LIST__',
            JSON.stringify(devAssets)
          );
          res.setHeader('Content-Type', 'application/javascript');
          res.end(swContent);
          return;
        }
        next();
      });
    }
  };
}

步骤2:编写Service Worker核心逻辑

在src/sw.js中使用占位符,接收插件注入的资源列表和Commit Hash:

const COMMIT_HASH = __COMMIT_HASH__;
const CACHE_NAME = `app-cache-${COMMIT_HASH}`;
const ASSET_LIST = __ASSET_LIST__;

// 安装阶段:缓存所有指定资源
self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      return cache.addAll(ASSET_LIST);
    }).then(() => self.skipWaiting())
  );
});

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

// 联网时处理资源请求(这里用缓存优先策略,可根据需求调整)
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then(cachedResponse => {
      // 优先返回缓存,同时后台更新资源
      const fetchPromise = fetch(event.request).then(networkResponse => {
        caches.open(CACHE_NAME).then(cache => {
          cache.put(event.request, networkResponse.clone());
        });
        return networkResponse;
      });
      return cachedResponse || fetchPromise;
    })
  );
});

步骤3:在Vite配置中注册插件

在vite.config.js中引入并使用自定义插件:

import { defineConfig } from 'vite';
import vitePluginCustomSW from './vite-plugin-custom-sw';

export default defineConfig({
  plugins: [vitePluginCustomSW()],
  // 可选:如果有静态资源需要被收集,确保build.assetsDir配置正确
  build: {
    assetsDir: 'assets'
  }
});

关键说明

  1. 资源收集逻辑:通过Rollup的generateBundle钩子直接获取构建后的所有产物,无需额外遍历目录,完全依赖Vite的构建流程。
  2. 更新机制:每次构建时Git Commit Hash变化,会生成新的缓存名称,SW安装时会缓存新资源,激活阶段自动清理旧缓存,实现无缝更新。
  3. 开发环境支持:通过configureServer钩子动态注入开发环境的资源列表,开发时也能体验离线功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 22:07:22