Umami是开源、轻量、隐私优先的自托管网站分析工具,支持动态import()按需加载ESM统计脚本,不依赖Cookie、默认不存IP、数据自主可控,提供GDPR合规的GA替代方案。

动态导入第三方统计脚本,核心是用 import() 按需加载,避免阻塞首屏、提升初始性能,同时确保脚本加载完成后再执行统计逻辑。
用 import() 加载远程 ESM 统计脚本
现代统计 SDK(如 Plausible、Umami、自托管的轻量脚本)若支持 ES 模块格式,可直接通过动态 import() 加载:
- URL 必须是合法模块地址(同源或带 CORS 头),例如:
https://plausible.io/js/script.js(Plausible 官方已支持 ESM) - 调用后返回 Promise,resolve 出模块对象(部分 SDK 会导出初始化函数)
- 示例:
async function loadPlausible() {
try {
const { default: plausible } = await import('https://plausible.io/js/script.js');
plausible('pageview'); // 手动触发 PV
} catch (err) {
console.warn('Plausible load failed:', err);
}
}
// 页面就绪后调用
document.addEventListener('DOMContentLoaded', loadPlausible);
兼容非 ESM 脚本:动态创建 script 标签 + Promise 封装
多数传统统计脚本(如百度统计、腾讯分析、旧版 GA)仍是 IIFE 或全局变量形式,不能直接 import()。此时应手动注入 script 标签,并用 Promise 包装加载完成时机:
- 创建
<script>元素,设置src和async - 监听
load事件,resolve Promise;监听error,reject - 加载完成后检查全局变量是否就位(如
window._hmt、window.gaq),再执行初始化
function loadBaiduAnalytics() {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = 'https://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion=' + ~(-new Date() / 3600000);
script.async = true;
script.onload = () => {
if (typeof window._hmt !== 'undefined') {
resolve();
} else {
reject(new Error('Baidu Analytics API not available'));
}
};
script.onerror = reject;
document.head.appendChild(script);
});
}
// 使用
loadBaiduAnalytics().then(() => {
window._hmt.push(['_trackPageview']);
}).catch(console.warn);
封装成可复用的按需加载器
为多个统计服务统一管理,可抽象一个加载器函数,支持配置 URL、校验逻辑、失败重试等:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 接收脚本 URL、校验函数(如
() => !!window.gtag)、超时时间 - 自动处理重复加载(缓存 Promise)
- 支持 fallback:加载失败时降级到 CDN 备用地址或跳过
const scriptLoader = new Map();
function loadScript(url, check, timeout = 10000) {
if (scriptLoader.has(url)) return scriptLoader.get(url);
const promise = new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('Script load timeout')), timeout);
const script = document.createElement('script');
script.src = url;
script.async = true;
script.onload = () => {
clearTimeout(timer);
if (check()) resolve();
else reject(new Error('Script loaded but check failed'));
};
script.onerror = () => {
clearTimeout(timer);
reject(new Error('Script load error'));
};
document.head.appendChild(script);
});
scriptLoader.set(url, promise);
return promise;
}
// 使用示例
loadScript(
'https://www.googletagmanager.com/gtag/js?id=G-XXXXXX',
() => typeof gtag === 'function'
).then(() => {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXX');
});
结合业务场景控制加载时机
不是所有统计都需要立即加载。可根据用户行为或页面状态延迟触发:
- 仅在用户停留超过 3 秒后加载(减少误触/爬虫请求)
- 只在特定路由(如 `/blog/*`)中加载内容分析脚本
- 隐私合规前提下,等用户点击“同意统计”后再加载
- SPA 中,在路由切换后调用
pageview,而非仅靠初始加载
不复杂但容易忽略。关键是把“加载”和“使用”解耦,让统计真正按需发生。

















