UNPKG

react-cache-refresh

Version:

A simple modern utility to clear cache and reload the application.

340 lines (259 loc) 8.23 kB
# React Cache Refresh 🚀 A modern, lightweight React utility that automatically detects new app versions and clears browser caches to ensure users always get the latest version of your application. ## ✨ Features - **Automatic Version Detection**: Compares current app version with latest deployed version - **Smart Cache Clearing**: Clears all browser caches (Service Worker caches, HTTP caches) - **React 19 Compatible**: Built with modern React patterns and hooks - **TypeScript Support**: Full TypeScript support with type definitions - **Reload Protection**: Prevents infinite reload loops with built-in cooldown mechanism - **Error Resilient**: Gracefully handles missing meta.json or network errors - **Zero Dependencies**: Only requires React as a peer dependency ## 📦 Installation ```bash npm install react-cache-refresh # or yarn add react-cache-refresh # or pnpm add react-cache-refresh ``` ## 🚀 Quick Start ### 1. Create a meta.json file First, create a `meta.json` file in your `public` directory with your app version: ```json { "version": "1.0.0" } ``` ### 2. Wrap your app with CacheBuster ```tsx import React from "react"; import { CacheBuster } from "react-cache-refresh"; import App from "./App"; const VERSION = "1.0.0"; // This should match your package.json version function Root() { return ( <CacheBuster currentAppVersion={VERSION}> <App /> </CacheBuster> ); } export default Root; ``` ### 3. Update your build process Make sure to update the `meta.json` file with the new version number whenever you deploy: ```json { "version": "1.0.1" } ``` ## 📖 API Reference ### CacheBuster Component The main component that wraps your application and handles version checking. #### Props | Prop | Type | Required | Description | | ------------------- | ----------- | -------- | --------------------------------------------------- | | `children` | `ReactNode` | ✅ | Your app components | | `currentAppVersion` | `string` | ✅ | Current version of your app | | `loadingComponent` | `ReactNode` | ❌ | Custom loading component (defaults to "Loading...") | #### Example with Custom Loading ```tsx import React from "react"; import { CacheBuster } from "react-cache-refresh"; import App from "./App"; import LoadingSpinner from "./components/LoadingSpinner"; const VERSION = "1.0.0"; function Root() { return ( <CacheBuster currentAppVersion={VERSION} loadingComponent={<LoadingSpinner />} > <App /> </CacheBuster> ); } ``` ### Utility Functions #### `clearAllCaches()` Manually clear all browser caches. ```tsx import { clearAllCaches } from "react-cache-refresh/utils"; const handleClearCache = async () => { try { await clearAllCaches(); console.log("All caches cleared successfully"); } catch (error) { console.error("Error clearing caches:", error); } }; ``` ## 🔧 Advanced Usage ### Using with Environment Variables ```tsx import React from "react"; import { CacheBuster } from "react-cache-refresh"; import App from "./App"; // Get version from environment variable or package.json const VERSION = process.env.REACT_APP_VERSION || "1.0.0"; function Root() { return ( <CacheBuster currentAppVersion={VERSION}> <App /> </CacheBuster> ); } ``` ### Custom Loading Component ```tsx import React from "react"; import { CacheBuster } from "react-cache-refresh"; import App from "./App"; const LoadingComponent = () => ( <div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "100vh", }} > <div>Checking for updates...</div> </div> ); function Root() { return ( <CacheBuster currentAppVersion="1.0.0" loadingComponent={<LoadingComponent />} > <App /> </CacheBuster> ); } ``` ### Integration with CI/CD #### Basic Example (Package.json Versioning) ```yaml # GitHub Actions name: Deploy on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - run: echo '{"version":"'$(node -p "require('./package.json').version")'"}' > public/meta.json - run: npm ci && npm run build ``` #### Dynamic Versioning (Recommended) Generate unique versions using Git SHA + Pipeline ID: ```yaml # GitHub Actions name: Deploy with Dynamic Versioning on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Generate version run: | VERSION="${GITHUB_REF#refs/heads/}.$(date -u +%Y%m%d%H%M%S).$(git rev-parse --short HEAD).${{ github.run_id }}" echo '{"version":"'$VERSION'"}' > public/meta.json echo "REACT_APP_VERSION=$VERSION" > .env.production - run: npm ci && npm run build ``` ```tsx // In your React app const VERSION = process.env.REACT_APP_VERSION || "dev-local"; <CacheBuster currentAppVersion={VERSION}> <App /> </CacheBuster>; ``` <details> <summary><strong>More CI/CD Examples (GitLab, Azure, etc.)</strong></summary> #### GitLab CI ```yaml # .gitlab-ci.yml build: script: - VERSION="${CI_COMMIT_REF_NAME}.$(date -u +%Y%m%d%H%M%S).${CI_COMMIT_SHORT_SHA}.${CI_PIPELINE_ID}" - echo "{\"version\": \"${VERSION}\"}" > public/meta.json - echo "REACT_APP_VERSION=${VERSION}" > .env.production - npm ci && npm run build ``` #### Azure DevOps ```yaml # azure-pipelines.yml variables: version: $(Build.SourceBranchName).$(Build.BuildId) steps: - script: | echo "{\"version\": \"$(version)\"}" > public/meta.json echo "REACT_APP_VERSION=$(version)" > .env.production npm ci && npm run build ``` </details> #### Version Formats ```bash # Examples of generated versions: "main.20241001143022.a1b2c3d.12345" # branch.date.sha.buildid "20241001143022.a1b2c3d.12345" # date.sha.buildid (shorter) "a1b2c3d.12345" # sha.buildid (minimal) ``` #### Using with Webpack ```javascript // webpack.config.js const fs = require("fs"); const packageJson = require("./package.json"); // Update meta.json during build fs.writeFileSync( "public/meta.json", JSON.stringify({ version: packageJson.version, }) ); ``` ## 🌐 Server Configuration Ensure `meta.json` is never cached by adding these headers: **Nginx:** ```nginx location /meta.json { add_header Cache-Control "no-cache, no-store, must-revalidate"; } ``` **Apache:** ```apache <Files "meta.json"> Header set Cache-Control "no-cache, no-store, must-revalidate" </Files> ``` ## 🔍 How It Works 1. **Version Check** → Fetches `/meta.json` on app load 2. **Comparison** → Compares with current app version 3. **Cache Clear** → Clears all browser caches if versions differ 4. **Reload** → Hard reload to get latest version 5. **Cooldown** → 5-second safety to prevent reload loops ## 🛠️ Troubleshooting | Issue | Solution | | ----------------------- | ------------------------------------------------------------------ | | **Infinite reloads** | Ensure `meta.json` and app versions match during deployment | | **Version check fails** | Check `meta.json` exists and isn't cached by your server | | **404 for meta.json** | Component handles this gracefully - just add the file to `/public` | **Debug:** Check browser console for version logs and error details. ## 🐛 Issues & Support Found a bug or have a feature request? Please [open an issue](https://github.com/aravindkarteekr/react-cache-refresh/issues) on GitHub. ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## 📄 License This project is licensed under the ISC License. ## 🔗 Links - [GitHub Repository](https://github.com/aravindkarteekr/react-cache-refresh) - [NPM Package](https://www.npmjs.com/package/react-cache-refresh) - [Report Issues](https://github.com/aravindkarteekr/react-cache-refresh/issues) --- **Made with ❤️ for the React community**