Skip to content

Commit

Permalink
feat: added cache system ipx
Browse files Browse the repository at this point in the history
  • Loading branch information
pierreleripoll committed Sep 8, 2024
1 parent a565f30 commit 150d15f
Show file tree
Hide file tree
Showing 6 changed files with 625 additions and 112 deletions.
34 changes: 25 additions & 9 deletions .github/workflows/nuxtjs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# https://github.com/actions/deploy-pages#usage
name: Deploy to GitHub Pages
on:
workflow_dispatch:
Expand All @@ -10,30 +9,47 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

# Enable corepack (used for managing package managers)
- run: corepack enable

# Setup Node.js environment
- uses: actions/setup-node@v3
with:
node-version: "20"
# Pick your own package manager and build script

# Install dependencies
- run: npm install
- run: NUXT_APP_BASE_URL=/mariaclaracastioni/ npx nuxt build --preset github_pages

# Cache the IPX processed images to speed up subsequent builds
- uses: actions/cache@v3
with:
path: ./.ipx-cache
key: ${{ runner.os }}-ipx-cache-${{ hashFiles('**/*.png') }}
restore-keys: |
${{ runner.os }}-ipx-cache-
# Start the IPX server, generate the static site, then stop the IPX server
- run: |
(node ipx.js & echo $! > ipx.pid) && \
NUXT_APP_BASE_URL=/mariaclaracastioni/ npx nuxt build --preset github_pages && \
kill $(cat ipx.pid) && rm ipx.pid
# Upload the built static site to be deployed by the deploy job
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./.output/public

# Deployment job
deploy:
# Add a dependency to the build job
needs: build
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
# Deploy to the github_pages environment
pages: write
id-token: write
environment:
name: github_pages
url: ${{ steps.deployment.outputs.page_url }}
# Specify runner + deployment step
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ node_modules
.output
.data
.env
dist
dist
.ipx-cache
98 changes: 98 additions & 0 deletions ipx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { listen } from "listhen";
import express from "express";
import {
createIPX,
ipxFSStorage,
ipxHttpStorage,
createIPXNodeServer,
} from "ipx";
import fs from "fs";
import path from "path";
import { Writable, PassThrough } from "stream";

const cacheDir = "./.ipx-cache";

// Ensure cache directory exists
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir, { recursive: true });
}

// Custom Writable Stream to capture response data
class CaptureStream extends Writable {
constructor(options) {
super(options);
this.chunks = [];
}

_write(chunk, encoding, callback) {
this.chunks.push(chunk);
callback();
}

getBuffer() {
return Buffer.concat(this.chunks);
}
}

// Middleware to check and cache the response
const cacheMiddleware = (req, res, next) => {
const cacheFilePath = path.resolve(path.join(cacheDir, req.originalUrl));

console.log("Checking cache", cacheFilePath);
if (fs.existsSync(cacheFilePath)) {
console.log("Cache found", cacheFilePath);
res.sendFile(cacheFilePath);
} else {
console.log("Cache not found", cacheFilePath);
// Create a PassThrough stream to capture the response data
// Create CaptureStream to capture response data
const captureStream = new CaptureStream();
const passThrough = new PassThrough();

passThrough.pipe(captureStream);

// Override res.write and res.end to use PassThrough stream
const originalWrite = res.write.bind(res);
const originalEnd = res.end.bind(res);

res.write = (chunk, encoding, callback) => {
console.log("res.write");
passThrough.write(chunk, encoding, callback);
return originalWrite(chunk, encoding, callback);
};

res.end = (chunk, encoding, callback) => {
if (chunk) passThrough.write(chunk, encoding);
passThrough.end();
return originalEnd(chunk, encoding, callback);
};

res.on("finish", () => {
// Create dit if it doesnt exist
if (!fs.existsSync(path.dirname(cacheFilePath)))
fs.mkdirSync(path.dirname(cacheFilePath), { recursive: true });

// Write captured data to cache file
console.log("Writing cache: ", cacheFilePath);
fs.writeFile(cacheFilePath, captureStream.getBuffer(), (err) => {
if (err) {
console.error("Error writing cache file:", err);
}
});
});

// Continue with IPX processing
next();
}
};

const ipx = createIPX({
storage: ipxFSStorage({ dir: "./public" }),
httpStorage: ipxHttpStorage({ domains: ["picsum.photos"] }),
});

const app = express();
app.use(cacheMiddleware);
app.use("/", createIPXNodeServer(ipx));

listen(app, { port: 4000 });
15 changes: 13 additions & 2 deletions nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
devtools: { enabled: true },
modules: ["@nuxt/content", "@nuxt/image", "@nuxt/fonts"],
content: {
documentDriven: true,
},

image:
process.env.NODE_ENV === "production"
? {
provider: "ipx",
ipx: {
baseURL: "http://localhost:4000/", // External IPX server for production
},
}
: {},
routeRules: {
"/": { prerender: true },
"/_ipx/**":
process.env.NODE_ENV === "production"
? { proxy: { to: "http://localhost:4000/**" } }
: {},
},
nitro: {
compressPublicAssets: true,
Expand Down
Loading

0 comments on commit 150d15f

Please sign in to comment.