@elken/next-offline
Version:
<h1 align="center"> next-offline </h1>
66 lines (54 loc) • 2.4 kB
JavaScript
const glob = require('glob');
const { readFile, writeFile } = require('fs-extra');
const { resolve } = require('path');
const nextUrlPrefix = '/_next/';
const excludeFiles = ['react-loadable-manifest.json', 'build-manifest.json'];
const manifestDest = 'precache-manifest.*.js';
const manifestImportRegex = /(,\s*(\r\n|\r|\n)\s*)?"precache-manifest\.[^.]*\.js"(,\s*)?/;
/**
* Workbox already generates a pretty good precache manifest for all the emitted
* assets. There are a few things different though:
* - there are emitted files that are not used and don't need to be cached
* - all emitted assets need to be prefixed with /_next/
* - we don't need the revision as all the precacheable files are versioned
*
* At the end replace old manifest reference with new inlined one.
*/
async function generateNextManifest(options) {
const manifestFilePath = resolve(options.outputPath, manifestDest);
const swFilePath = resolve(options.outputPath, options.swDest);
const originalManifest = await getOriginalManifest(manifestFilePath);
const nextManifest = buildNextManifest(originalManifest, options.urlPrefix);
await inlineManifest(nextManifest, swFilePath);
}
function getOriginalManifest(manifestFilePath) {
return new Promise((resolve, reject) => {
glob(manifestFilePath, async (err, files = []) => {
if (err) {
return reject(err);
}
// Pick first and only as we've clean old ones.
const file = await readFile(files[0], 'utf-8');
// Execute file with a self variable in the scope/context.
const self = {};
new Function('self', file)(self);
resolve(self.__precacheManifest);
});
});
}
function buildNextManifest(originalManifest, urlPrefix = '') {
return originalManifest.filter(entry => !excludeFiles.includes(entry.url)).map(entry => ({
url: `${urlPrefix}${nextUrlPrefix}${entry.url}`,
}));
}
async function inlineManifest(manifest, swFilePath) {
const originalSw = await readFile(swFilePath, 'utf8');
// Prepend/inline newly generated precache manifest and remove import for old one.
const newSw = `self.__precacheManifest = ${JSON.stringify(
manifest,
null,
2,
)};\n\n${originalSw.replace(manifestImportRegex, '')}`;
await writeFile(swFilePath, newSw, 'utf8');
}
module.exports = generateNextManifest;