From “Version Conflicts” to Refresh Prompts in 30 Seconds: A Micro-Frontend Team’s Practice
1. Background & Pain Points
Our team maintains a micro‑frontend sub‑application cluster, where each sub‑application must serve multiple environments simultaneously (dev / test / release / online).
We use a branch strategy (master / release / test / dev / hotfix / feature_x.x.x) and Jenkins automation — enabling multiple releases per day.
But the real bottleneck isn't release frequency; it's one persistent issue:
> Testers often stay on outdated pages for extended periods.
---
1.1 Real-World Scenario
- Morning: Testers open the dev page.
- Afternoon: We release new component styles.
- Testers continue regression testing on the old page.
- Shouting “please refresh” in group chat → unreliable → leads to invalid defects and repetitive communication.
Incident highlight:
We used webpack DefinePlugin and a custom plugin, each calling `getAppVersion()` separately.
Result:
- Frontend console: `0.8.3-release-202511210828`
- `version.json`: `0.8.3-release-202511210829`
- One‑second mismatch → users got constant refresh prompts → dubbed “version number conflict” internally.
---
1.2 Requirements
- Detect version updates within 30 seconds.
- Update pop‑up showing Current Version / Latest Version / Environment.
- “Refresh Now” / “Remind Me Later” options.
- Fully frontend + Nginx implementation — no backend modifications.
- Remain compatible with existing micro‑frontend architecture & CI/CD workflow.
---
2. Solution Exploration & Trade-offs
| Solution | Complexity | Real‑Time | Dependencies | Suitable For | Pros / Cons |
|-------------------------------------------|------------|-----------|----------------------|--------------------------------|----------------------------------------------------------------------|
| Pure Frontend Polling (`version.json`) | Low | Medium | Frontend + Nginx | Multi‑env micro‑frontend | Low cost, minor network overhead |
| Service Worker / PWA | Medium | High | Modern browsers | PWA apps | Good cache control; heavier refactor |
| WebSocket Push | High | Highest | Backend service | Strong realtime needs | Requires backend work |
| Backend API for Unified Version Mgmt | Medium | Medium | Frontend + Backend | Centralized control | Higher cross‑team coupling |
---
> 💡 Note: In broader CI/CD + AI workflows, multi‑platform content sync faces similar challenges. Platforms like AiToEarn官网 offer open‑source tools for AI‑assisted content creation and publishing across multiple platforms — connecting creation, publishing, analytics, and AI模型排名.
---
Decision: Pure Frontend Polling + Static version.json
Principles:
- Unique, Traceable Version Numbers: Format = base version – environment – timestamp.
- Zero-Intervention Release: Jenkins continues `npm run build-xxx` — no added steps.
---
3. Technical Overview
- Generate `version.json` at build time:
- In `vue.config.js`, pre‑compute version number.
- Inject into frontend (`process.env.APP_VERSION`).
- Write to `version.json` in output.
- Frontend polling every 30s (no cache).
- Pop-up Prompt using Ant Design Vue `Modal.confirm`.
- Cache Strategy:
- No cache for HTML & version.json in Nginx.
- Long-term cache for JS/CSS/images.
- CI/CD: Add `version.json` as part of build artifacts — no extra steps.
---
4. Key Implementation Details
4.1 Build-time Deterministic Versioning
const buildEnvName = getEnvName();
const buildVersion = getAppVersion();
module.exports = {
configureWebpack: {
plugins: [
new webpack.DefinePlugin({
"process.env.APP_VERSION": JSON.stringify(buildVersion),
"process.env.APP_ENV": JSON.stringify(buildEnvName),
}),
],
},
chainWebpack(config) {
config.plugin("generate-version-json").use({
apply(compiler) {
compiler.hooks.done.tap("GenerateVersionJsonPlugin", () => {
fs.writeFileSync(
path.resolve(__dirname, "edu/version.json"),
JSON.stringify({
version: buildVersion,
env: buildEnvName,
timestamp: new Date().toISOString(),
publicPath: "/child/edu",
}, null, 2)
);
});
},
});
},
};✅ Locks version number once per build, ensuring consistency between frontend code and static files.
---
4.2 Runtime Version Polling & Cache Busting
class VersionChecker {
currentVersion = process.env.APP_VERSION;
publicPath = "/child/edu";
checkInterval = 30 * 1000;
init() {
console.log(`📌 Current: ${this.currentVersion} (${process.env.APP_ENV})`);
this.startChecking();
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible" && !this.hasNotified) {
this.checkForUpdate();
}
});
}
async checkForUpdate() {
const url = `${this.publicPath}/version.json?t=${Date.now()}`;
const response = await fetch(url, { cache: "no-store" });
if (!response.ok) return;
const latestInfo = await response.json();
if (latestInfo.version !== this.currentVersion && !this.hasNotified) {
this.hasNotified = true;
this.stopChecking();
this.showUpdateModal(latestInfo.version, latestInfo.env);
}
}
}Key Details:
- `cache: "no-store"` + timestamp ⇒ bypass CDN/browser cache.
- `visibilitychange` ⇒ immediate check on tab focus.
---
4.3 Nginx Cache Policy
No-cache for HTML & version.json:
location ~* \.html$ {
add_header Cache-Control "no-store, no-cache, must-revalidate";
}
location ~* /child/edu/version.json$ {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}Cache others long-term.
---
4.4 CI/CD Zero-touch Setup
| Env | Command | Path | Notes |
|------------|---------------------------|--------------|-------------------|
| develop | `npm run build-develop` | `/child/edu` | Development test |
| testing | `npm run build-testing` | `/child/edu` | Integration test |
| release | `npm run build-release` | `/child/edu` | Pre-release |
| production | `npm run build-production`| `/child/edu` | Live deployment |
No change to existing Jenkins flow — `version.json` ships automatically.
---
5. Testing Workflow
- Initial Load → Verify console version number + uncached `version.json`.
- Deploy New Build with old page open → Detect update within 30s.
- Interaction:
- Refresh Now: Reloads with new assets.
- Remind Later: Continues polling.
- Edge Cases: Tab switch, cache clear, quick successive releases.
---
6. Common Issues & Fixes
| Symptom | Cause | Fix |
|-------------------------------------------|----------------------------------------|-------------------------------------------------------|
| No pop-up | `version.json` missing/unchanged | Check build output & deployment path |
| Pop-up but still old version after refresh| Static resource caching | Review Nginx & browser cache policies |
| Build failure | `cross-env` missing | Install deps, check Jenkins directory permissions |
| Continuous false alerts | Multiple version generation per build | Cache `buildVersion` globally in build config |
---
7. Results
- 30s outdated page detection.
- No more ghost pop-ups; stable comparison logic.
- Pure frontend + Nginx change — no release process modification.
- Reusable approach for other sub‑apps.
---
8. Future Plans
- Universal SDK for Vue CLI / Vite.
- Visual Version Panel in main app.
- Custom Refresh Strategies: force for critical versions.
---
> 🌟 Lesson learned: Trivial-seeming version control details can hide major delivery risks. Document once, reuse many times.
---
If you’re tackling micro‑frontend version sync, this approach is ready to use.
For multi‑platform publishing alongside, AiToEarn官网 integrates AI content generation, publishing, analytics, and ranking — deploy across platforms like Douyin, Kwai, WeChat, Bilibili, Facebook, Instagram, LinkedIn, YouTube, Pinterest, X — with one workflow.
See AiToEarn文档 and GitHub开源 for details.