​ UniApp 如何缓存 WASM 文件:Service Worker 与 Nginx 的协同实战

2026-08-25 09:50

UniApp H5 开发中,使用webview加载盈帆报表预览界面时,预览界面需要加载的WebAssembly (.wasm) 文件往往承载着核心计算逻辑,体积较大。如果每次加载都从服务器拉取,不仅耗时,还会造成极大的带宽浪费。要实现 WASM 文件的“秒开”体验,最稳健的方案是构建 Nginx 服务端缓存 Service Worker 客户端缓存 的双重防线。

本文将手把手带你配置这套组合拳,彻底解决 WASM 加载慢的问题。

第一道防线:Nginx 服务端配置

Nginx 是资源分发的源头。正确的配置不仅能保证浏览器原生缓存生效,更是 Service Worker 能够顺利接管请求的前提。

1. 注册 WASM MIME 类型

很多开发者部署 WASM 后报错 Failed to load module script,根源在于 Nginx 默认不认识 .wasm 后缀。必须在 nginx.conf http 块中显式声明:

http {

include       mime.types;

default_type  application/octet-stream;


# 核心:显式声明 wasm MIME 类型

types {

application/wasm wasm;

}

# ... 其他配置

}

2. 配置强缓存与流式传输支持

针对 .wasm 文件,我们需要开启长缓存,并配合 V8 引擎的流式编译特性:

location ~* \.wasm$ {

root D:\\EFReport8.2\\webapps;

types {

application/wasm wasm;

}

# 强缓存 1 年(WASM 文件更新时改文件名或加版本号)

add_header Cache-Control "public, max-age=31536000, immutable";

# 内容类型

#add_header Content-Type "application/wasm";

proxy_pass_header Cache-Control;

proxy_pass_header Content-Encoding;


# 4. 【关键】关闭 Nginx 的动态 Gzip 压缩

# 因为WASM 已经是预压缩过的,Nginx 不需要也不应该再次压缩

gzip off;

gzip_static on;

}

注:immutable 指令能告诉浏览器该文件在有效期内绝不会改变,连“验证是否过期”的请求都可以省去。

第二道防线:Service Worker 缓存策略

Nginx 解决了“存”的问题,Service Worker (SW) 则解决了“取”的效率问题。对于 WASM 这种一旦下载就极少变动的资源,“缓存优先(Cache First)” 是最佳策略。

报表EFRS目录下创建 sw.js

// sw.js

const WASM_CACHE_NAME = 'uniapp-wasm-cache-v1.0.0';


// 1. 安装阶段:可以预缓存核心 WASM 文件(可选)

self.addEventListener('install', (event) => {

event.waitUntil(

caches.open(WASM_CACHE_NAME).then((cache) => {

// 如果知道核心 wasm 文件名,可在此预缓存

// return cache.addAll(['/core/module.wasm']);

return self.skipWaiting(); // 强制激活,无需等待旧页面关闭

})

);

});


// 2. 激活阶段:清理旧版本缓存

self.addEventListener('activate', (event) => {

event.waitUntil(

caches.keys().then((keys) =>

Promise.all(keys.filter(key => key !== WASM_CACHE_NAME).map(key => caches.delete(key)))

).then(() => self.clients.claim()) // 立即接管所有页面

);

});


// 3. 拦截请求:WASM 专属的“缓存优先”策略

self.addEventListener('fetch', (event) => {

const url = new URL(event.request.url);


// 仅拦截 .wasm 文件

if (url.pathname.endsWith('.wasm')) {

event.respondWith(

caches.match(event.request).then((cached) => {

// 命中缓存,直接返回(速度极快)

if (cached) return cached;


// 未命中,走网络并写入缓存

return fetch(event.request).then((response) => {

if (!response || response.status !== 200) return response;


const responseToCache = response.clone();

caches.open(WASM_CACHE_NAME).then((cache) => {

cache.put(event.request, responseToCache);

});

return response;

});

})

);

}

});

第三道防线:UniApp 客户端注册与避坑

配置好 SW 后,必须在报表预览界面report.html完成注册。

1. 注册 Service Worker

report.html中添加:

// $(document).ready中添加


if ('serviceWorker' in navigator) {

window.addEventListener('load', () => {

navigator.serviceWorker.register('/sw.js')

.then(reg => console.log('SW 注册成功:', reg.scope))

.catch(err => console.log('SW 注册失败:', err));

});

}

2. 必须遵守的“三大铁律”

HTTPS 是硬性门槛:Service Worker 只能在 HTTPS localhost 下运行。如果你的 UniApp H5 部署在 HTTP 环境下,SW 将直接失效。

不要手动清除 SW 缓存:避免在业务代码中频繁调用 caches.delete() uni.clearStorageSync(),这会破坏精心设计的缓存体系。

总结与验证

完成上述配置后,你可以通过 Chrome DevTools Network 面板进行验证:

首次访问:状态码为200,Size显示实际文件大小。

刷新页面:Status变为200(from ServiceWorker),Size显示(disk cache)。

离线模式:勾选Network面板的Offline,刷新页面,WASM依然能正常加载。

通过 Nginx 的底层兜底与 Service Worker 的精准拦截,你的 UniApp 应用在访问报表预览界面时,将不会每次都下载wasm文件,解决了加载预览页面耗时过久的问题



电话咨询:19945086027(微信同号)
微信客服
扫码咨询