feat(blog): add file-based blog with dynamic slugs, MDX content and layout shell
- Introduced blog routing using Next.js App Router - Implemented dynamic [slug] pages for blog posts - Added MDX-based content loading via lib/posts - Integrated shared TopBar layout with navigation - Established clear content, lib and component separation
This commit is contained in:
171
apps/public-web/node_modules/next/dist/server/dev/hot-reloader-rspack.js
generated
vendored
Normal file
171
apps/public-web/node_modules/next/dist/server/dev/hot-reloader-rspack.js
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, /**
|
||||
* Rspack Persistent Cache Strategy for Next.js Development
|
||||
*
|
||||
* Rspack's persistent caching differs from Webpack in how it manages module graphs.
|
||||
* While Webpack incrementally updates modules, Rspack operates on complete module
|
||||
* graph snapshots for cache restoration.
|
||||
*
|
||||
* Problem:
|
||||
* - Next.js dev server starts with no page modules in the initial entry points
|
||||
* - When Rspack restores from persistent cache, it finds no modules and purges
|
||||
* the entire module graph
|
||||
* - Later page requests find no cached module information, preventing cache reuse
|
||||
*
|
||||
* Solution:
|
||||
* - Track successfully built page entries after each compilation
|
||||
* - Restore these entries on dev server restart to maintain module graph continuity
|
||||
* - This ensures previously compiled pages can leverage persistent cache for faster builds
|
||||
*/ "default", {
|
||||
enumerable: true,
|
||||
get: function() {
|
||||
return HotReloaderRspack;
|
||||
}
|
||||
});
|
||||
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
||||
const _promises = /*#__PURE__*/ _interop_require_default(require("fs/promises"));
|
||||
const _crypto = require("crypto");
|
||||
const _hotreloaderwebpack = /*#__PURE__*/ _interop_require_default(require("./hot-reloader-webpack"));
|
||||
const _ondemandentryhandler = require("./on-demand-entry-handler");
|
||||
const _constants = require("../../shared/lib/constants");
|
||||
function _interop_require_default(obj) {
|
||||
return obj && obj.__esModule ? obj : {
|
||||
default: obj
|
||||
};
|
||||
}
|
||||
class HotReloaderRspack extends _hotreloaderwebpack.default {
|
||||
async afterCompile(multiCompiler) {
|
||||
// Always initialize the fallback error watcher for Rspack.
|
||||
// Rspack may restore/retain the previous build's error state, so without this
|
||||
// a page that previously failed to build might not be rebuilt on the next request.
|
||||
await super.buildFallbackError();
|
||||
const rspackStartSpan = this.hotReloaderSpan.traceChild('rspack-after-compile');
|
||||
await rspackStartSpan.traceAsyncFn(async ()=>{
|
||||
const hash = (0, _crypto.createHash)('sha1');
|
||||
multiCompiler.compilers.forEach((compiler)=>{
|
||||
const cache = compiler.options.cache;
|
||||
if (typeof cache === 'object' && 'version' in cache && cache.version) {
|
||||
hash.update(cache.version);
|
||||
if (compiler.name === _constants.COMPILER_NAMES.client) {
|
||||
this.isClientCacheEnabled = true;
|
||||
} else if (compiler.name === _constants.COMPILER_NAMES.server) {
|
||||
this.isServerCacheEnabled = true;
|
||||
} else if (compiler.name === _constants.COMPILER_NAMES.edgeServer) {
|
||||
this.isEdgeServerCacheEnabled = true;
|
||||
}
|
||||
} else {
|
||||
hash.update('-');
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
this.builtEntriesCachePath = _path.default.join(this.distDir, 'cache', 'rspack', hash.digest('hex').substring(0, 16), 'built-entries.json');
|
||||
const hasBuiltEntriesCache = await _promises.default.access(this.builtEntriesCachePath).then(()=>true, ()=>false);
|
||||
if (hasBuiltEntriesCache) {
|
||||
try {
|
||||
const builtEntries = JSON.parse(await _promises.default.readFile(this.builtEntriesCachePath, 'utf-8') || '{}');
|
||||
await Promise.all(Object.keys(builtEntries).map(async (entryKey)=>{
|
||||
const entryData = builtEntries[entryKey];
|
||||
const isEntry = entryData.type === _ondemandentryhandler.EntryTypes.ENTRY;
|
||||
const isChildEntry = entryData.type === _ondemandentryhandler.EntryTypes.CHILD_ENTRY;
|
||||
// Check if the page was removed or disposed and remove it
|
||||
if (isEntry) {
|
||||
const pageExists = !entryData.dispose && await _promises.default.access(entryData.absolutePagePath).then(()=>true, ()=>false);
|
||||
if (!pageExists) {
|
||||
delete builtEntries[entryKey];
|
||||
return;
|
||||
} else if (!('hash' in builtEntries[entryKey]) || builtEntries[entryKey].hash !== await calculateFileHash(entryData.absolutePagePath)) {
|
||||
delete builtEntries[entryKey];
|
||||
return;
|
||||
}
|
||||
}
|
||||
// For child entries, if it has an entry file and it's gone, remove it
|
||||
if (isChildEntry) {
|
||||
if (entryData.absoluteEntryFilePath) {
|
||||
const pageExists = !entryData.dispose && await _promises.default.access(entryData.absoluteEntryFilePath).then(()=>true, ()=>false);
|
||||
if (!pageExists) {
|
||||
delete builtEntries[entryKey];
|
||||
return;
|
||||
} else {
|
||||
if (!('hash' in builtEntries[entryKey]) || builtEntries[entryKey].hash !== await calculateFileHash(entryData.absoluteEntryFilePath)) {
|
||||
delete builtEntries[entryKey];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
Object.assign((0, _ondemandentryhandler.getEntries)(multiCompiler.outputPath), builtEntries);
|
||||
} catch (error) {
|
||||
console.error('Rspack failed to read built entries cache: ', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
async ensurePage({ page, clientOnly, appPaths, definition, isApp, url }) {
|
||||
await super.ensurePage({
|
||||
page,
|
||||
clientOnly,
|
||||
appPaths,
|
||||
definition,
|
||||
isApp,
|
||||
url
|
||||
});
|
||||
const entries = (0, _ondemandentryhandler.getEntries)(this.multiCompiler.outputPath);
|
||||
const builtEntries = {};
|
||||
await Promise.all(Object.keys(entries).map(async (entryName)=>{
|
||||
const entry = entries[entryName];
|
||||
if (entry.status !== _ondemandentryhandler.BUILT) return;
|
||||
const result = /^(client|server|edge-server)@(app|pages|root)@(.*)/g.exec(entryName);
|
||||
const [, key /* pageType */ , , ] = result// this match should always happen
|
||||
;
|
||||
if (key === 'client' && !this.isClientCacheEnabled) return;
|
||||
if (key === 'server' && !this.isServerCacheEnabled) return;
|
||||
if (key === 'edge-server' && !this.isEdgeServerCacheEnabled) return;
|
||||
// TODO: Rspack does not store middleware entries in persistent cache, causing
|
||||
// test/integration/middleware-src/test/index.test.ts to fail. This is a temporary
|
||||
// workaround to skip middleware entry caching until Rspack properly supports it.
|
||||
if (page === '/middleware') {
|
||||
return;
|
||||
}
|
||||
let hash;
|
||||
if (entry.type === _ondemandentryhandler.EntryTypes.ENTRY) {
|
||||
hash = await calculateFileHash(entry.absolutePagePath);
|
||||
} else if (entry.absoluteEntryFilePath) {
|
||||
hash = await calculateFileHash(entry.absoluteEntryFilePath);
|
||||
}
|
||||
if (!hash) {
|
||||
return;
|
||||
}
|
||||
builtEntries[entryName] = entry;
|
||||
builtEntries[entryName].hash = hash;
|
||||
}));
|
||||
const hasBuitEntriesCache = await _promises.default.access(this.builtEntriesCachePath).then(()=>true, ()=>false);
|
||||
try {
|
||||
if (!hasBuitEntriesCache) {
|
||||
await _promises.default.mkdir(_path.default.dirname(this.builtEntriesCachePath), {
|
||||
recursive: true
|
||||
});
|
||||
}
|
||||
await _promises.default.writeFile(this.builtEntriesCachePath, JSON.stringify(builtEntries, null, 2));
|
||||
} catch (error) {
|
||||
console.error('Rspack failed to write built entries cache: ', error);
|
||||
}
|
||||
}
|
||||
constructor(...args){
|
||||
super(...args), this.isClientCacheEnabled = false, this.isServerCacheEnabled = false, this.isEdgeServerCacheEnabled = false;
|
||||
}
|
||||
}
|
||||
async function calculateFileHash(filePath, algorithm = 'sha256') {
|
||||
if (!await _promises.default.access(filePath).then(()=>true, ()=>false)) {
|
||||
return;
|
||||
}
|
||||
const fileBuffer = await _promises.default.readFile(filePath);
|
||||
const hash = (0, _crypto.createHash)(algorithm);
|
||||
hash.update(fileBuffer);
|
||||
return hash.digest('hex');
|
||||
}
|
||||
|
||||
//# sourceMappingURL=hot-reloader-rspack.js.map
|
||||
Reference in New Issue
Block a user