Layui 本身不内置 PWA 支持,但可通过标准 Service Worker 方案缓存其静态资源(如 layui.css、layui.js、图标字体、模块 JS 等)实现离线加载页面骨架和基础 UI;关键在于让使用 Layui 构建的页面支持离线优先,而非依赖 Layui 自身提供 PWA 功能。

直接说结论:Layui 本身不内置 PWA 支持,但你可以用标准 Service Worker 方案缓存 Layui 的静态资源(layui.css、layui.js、图标、模块 JS 等),实现离线加载页面骨架和基础 UI。关键不是“Layui 怎么做 PWA”,而是“你如何让用 Layui 构建的页面支持离线优先”。
注册 Service Worker 前必须确认的三件事
很多 Layui 项目卡在这一步就失败了,不是代码问题,是环境没达标:
- 必须部署在
https协议下(本地localhost也允许,但http://127.0.0.1或文件协议file://不行) -
sw.js文件必须放在网站根目录(比如https://example.com/sw.js),否则navigator.serviceWorker.register('/sw.js')会因 scope 限制无法控制子路径下的页面 - Layui 页面的 HTML 必须显式调用注册逻辑——Layui 不自动注册 SW,得你自己加
缓存 Layui 资源时最容易漏掉的路径
Layui 的资源分散在多个位置,只缓存 /layui/css/layui.css 和 /layui/layui.js 是不够的。常见遗漏点:
- 图标字体文件:
/layui/font/iconfont.woff2、/layui/font/iconfont.woff、/layui/font/iconfont.ttf(缺一个,按钮图标就变成方块) - 模块 JS 文件:如果你用了
laydate、upload、table等模块,它们可能按需加载,路径如/layui/modules/laydate.js,必须显式加入urlsToCache - 自定义皮肤 CSS:
/css/your-theme.css如果覆盖了 Layui 样式,也得进缓存列表 - 如果用了 Layui 的图片资源(如
/images/xxx.png),路径要写全,不能只写images/目录——Cache API 不支持通配符或目录递归
fetch 事件里处理 Layui 模块动态加载的坑
Layui 的 layui.use() 是异步加载模块的,它发的请求也会被 Service Worker 拦截。但默认的 caches.match(event.request) 只能匹配完全相同的 URL,而模块加载时可能带时间戳参数(如 /layui/modules/table.js?t=1727726760),导致缓存失效。
解决办法是在 fetch 事件中标准化请求 URL:
self.addEventListener('fetch', event => {
const url = new URL(event.request.url);
// 去掉 ?t=xxx 这类干扰参数,只保留路径
if (url.pathname.startsWith('/layui/modules/')) {
const cleanUrl = url.origin + url.pathname;
event.respondWith(
caches.match(cleanUrl)
.then(response => response || fetch(event.request))
);
return;
}
event.respondWith(
caches.match(event.request).then(r => r || fetch(event.request))
);
});
注意:cleanUrl 构造必须包含协议+域名+路径,不能只传 url.pathname,否则 caches.match() 查不到。
激活新版本 SW 后旧缓存不清理导致 Layui 样式错乱
当你更新 Layui 版本(比如从 v2.8.18 升到 v2.9.0),但没清理旧缓存,浏览器可能混用老 CSS 和新 JS,造成布局错位、组件不渲染等诡异问题。
务必在 activate 事件里删除旧缓存:
self.addEventListener('activate', event => {
const cacheWhitelist = ['layui-v2.9.0']; // 当前版本缓存名
event.waitUntil(
caches.keys().then(keys => {
return Promise.all(keys.map(key => {
if (!cacheWhitelist.includes(key)) {
return caches.delete(key); // 删除所有非白名单缓存
}
}));
})
);
});
缓存名建议带 Layui 版本号(如 'layui-v2.9.0'),而不是固定用 'layui-cache'——这是最常被忽略的兼容性细节。
真正麻烦的不是写几行 sw.js,而是每次 Layui 升级后,你要同步更新缓存列表、清理策略、URL 标准化逻辑。离线能力越强,版本管理责任越重。











