const crypto = require('crypto') const fs = require('fs') const path = require('path') const getRevision = filePath => crypto.createHash('md5').update(fs.readFileSync(filePath)).digest('hex') function formatBytes (bytes, decimals = 2) { if (bytes === 0) { return '0 B' } const k = 1024 const sizes = ['B', 'KB', 'MB'] const i = Math.floor(Math.log(bytes) / Math.log(k)) const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) return `${formattedSize} ${sizes[i]}` } function generatePrecacheManifest () { const manifest = [] let size = 0 const addToManifest = (filePath, url, s) => { const revision = getRevision(filePath) manifest.push({ url, revision }) size += s } const staticDir = path.join(__dirname, '../public') const staticFiles = fs.readdirSync(staticDir) const staticMatch = f => [/\.(gif|jpe?g|ico|png|ttf|webmanifest)$/, /^darkmode\.js$/].some(m => m.test(f)) staticFiles.filter(staticMatch).forEach(file => { const filePath = path.join(staticDir, file) const stats = fs.statSync(filePath) if (stats.isFile()) { addToManifest(filePath, '/' + file, stats.size) } }) const pagesDir = path.join(__dirname, '../pages') const precacheURLs = ['/offline'] const pagesFiles = fs.readdirSync(pagesDir) const fileToUrl = f => '/' + f.replace(/\.js$/, '') const pageMatch = f => precacheURLs.some(url => fileToUrl(f) === url) pagesFiles.filter(pageMatch).forEach(file => { const filePath = path.join(pagesDir, file) const stats = fs.statSync(filePath) if (stats.isFile()) { // This is not ideal since dependencies of the pages may have changed // but we would still generate the same revision ... // The ideal solution would be to create a revision from the file generated by webpack // in .next/server/pages but the file may not exist yet when we run this script addToManifest(filePath, fileToUrl(file), stats.size) } }) const output = 'sw/precache-manifest.json' fs.writeFileSync(output, JSON.stringify(manifest, null, 2)) console.log(`Created precache manifest at ${output}. Cache will include ${manifest.length} URLs with a size of ${formatBytes(size)}.`) } module.exports = { generatePrecacheManifest }