- 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
1247 lines
58 KiB
JavaScript
1247 lines
58 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "createHotReloaderTurbopack", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return createHotReloaderTurbopack;
|
|
}
|
|
});
|
|
const _promises = require("fs/promises");
|
|
const _inspector = /*#__PURE__*/ _interop_require_wildcard(require("inspector"));
|
|
const _path = require("path");
|
|
const _url = require("url");
|
|
const _ws = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/ws"));
|
|
const _store = require("../../build/output/store");
|
|
const _hotreloadertypes = require("./hot-reloader-types");
|
|
const _swc = require("../../build/swc");
|
|
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../build/output/log"));
|
|
const _constants = require("../../shared/lib/constants");
|
|
const _middlewareturbopack = require("./middleware-turbopack");
|
|
const _utils = require("../../shared/lib/utils");
|
|
const _utils1 = require("../utils");
|
|
const _requirecache = require("./require-cache");
|
|
const _renderserver = require("../lib/render-server");
|
|
const _denormalizepagepath = require("../../shared/lib/page-path/denormalize-page-path");
|
|
const _trace = require("../../trace");
|
|
const _turbopackutils = require("./turbopack-utils");
|
|
const _setupdevbundler = require("../lib/router-utils/setup-dev-bundler");
|
|
const _manifestloader = require("../../shared/lib/turbopack/manifest-loader");
|
|
const _ondemandentryhandler = require("./on-demand-entry-handler");
|
|
const _entrykey = require("../../shared/lib/turbopack/entry-key");
|
|
const _messages = require("./messages");
|
|
const _encryptionutilsserver = require("../app-render/encryption-utils-server");
|
|
const _apppageroutedefinition = require("../route-definitions/app-page-route-definition");
|
|
const _apppaths = require("../../shared/lib/router/utils/app-paths");
|
|
const _ismetadataroute = require("../../lib/metadata/is-metadata-route");
|
|
const _patcherrorinspect = require("../patch-error-inspect");
|
|
const _getnexterrorfeedbackmiddleware = require("../../next-devtools/server/get-next-error-feedback-middleware");
|
|
const _utils2 = require("../../shared/lib/turbopack/utils");
|
|
const _getdevoverlayfontmiddleware = require("../../next-devtools/server/font/get-dev-overlay-font-middleware");
|
|
const _devindicatorserverstate = require("./dev-indicator-server-state");
|
|
const _devindicatormiddleware = require("../../next-devtools/server/dev-indicator-middleware");
|
|
const _restartdevservermiddleware = require("../../next-devtools/server/restart-dev-server-middleware");
|
|
const _compilationevents = require("../../shared/lib/turbopack/compilation-events");
|
|
const _utils3 = require("../../build/utils");
|
|
const _receivelogs = require("./browser-logs/receive-logs");
|
|
const _normalizepath = require("../../lib/normalize-path");
|
|
const _devtoolsconfigmiddleware = require("../../next-devtools/server/devtools-config-middleware");
|
|
const _attachnodejsdebuggermiddleware = require("../../next-devtools/server/attach-nodejs-debugger-middleware");
|
|
const _debugchannel = require("./debug-channel");
|
|
const _hotreloadersharedutils = require("./hot-reloader-shared-utils");
|
|
const _getmcpmiddleware = require("../mcp/get-mcp-middleware");
|
|
const _geterrors = require("../mcp/tools/get-errors");
|
|
const _getpagemetadata = require("../mcp/tools/get-page-metadata");
|
|
const _formaterrors = require("../mcp/tools/utils/format-errors");
|
|
const _mcptelemetrytracker = require("../mcp/mcp-telemetry-tracker");
|
|
const _filelogger = require("./browser-logs/file-logger");
|
|
const _serializederrors = require("./serialized-errors");
|
|
function _interop_require_default(obj) {
|
|
return obj && obj.__esModule ? obj : {
|
|
default: obj
|
|
};
|
|
}
|
|
function _getRequireWildcardCache(nodeInterop) {
|
|
if (typeof WeakMap !== "function") return null;
|
|
var cacheBabelInterop = new WeakMap();
|
|
var cacheNodeInterop = new WeakMap();
|
|
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
})(nodeInterop);
|
|
}
|
|
function _interop_require_wildcard(obj, nodeInterop) {
|
|
if (!nodeInterop && obj && obj.__esModule) {
|
|
return obj;
|
|
}
|
|
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
return {
|
|
default: obj
|
|
};
|
|
}
|
|
var cache = _getRequireWildcardCache(nodeInterop);
|
|
if (cache && cache.has(obj)) {
|
|
return cache.get(obj);
|
|
}
|
|
var newObj = {
|
|
__proto__: null
|
|
};
|
|
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
for(var key in obj){
|
|
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
if (desc && (desc.get || desc.set)) {
|
|
Object.defineProperty(newObj, key, desc);
|
|
} else {
|
|
newObj[key] = obj[key];
|
|
}
|
|
}
|
|
}
|
|
newObj.default = obj;
|
|
if (cache) {
|
|
cache.set(obj, newObj);
|
|
}
|
|
return newObj;
|
|
}
|
|
const wsServer = new _ws.default.Server({
|
|
noServer: true
|
|
});
|
|
const isTestMode = !!(process.env.NEXT_TEST_MODE || process.env.__NEXT_TEST_MODE || process.env.DEBUG);
|
|
const sessionId = Math.floor(Number.MAX_SAFE_INTEGER * Math.random());
|
|
/**
|
|
* Replaces turbopack:///[project] with the specified project in the `source` field.
|
|
*/ function rewriteTurbopackSources(projectRoot, sourceMap) {
|
|
if ('sections' in sourceMap) {
|
|
for (const section of sourceMap.sections){
|
|
rewriteTurbopackSources(projectRoot, section.map);
|
|
}
|
|
} else {
|
|
for(let i = 0; i < sourceMap.sources.length; i++){
|
|
sourceMap.sources[i] = (0, _url.pathToFileURL)((0, _path.join)(projectRoot, sourceMap.sources[i].replace(/turbopack:\/\/\/\[project\]/, ''))).toString();
|
|
}
|
|
}
|
|
}
|
|
function getSourceMapFromTurbopack(project, projectRoot, sourceURL) {
|
|
let sourceMapJson = null;
|
|
try {
|
|
sourceMapJson = project.getSourceMapSync(sourceURL);
|
|
} catch (err) {}
|
|
if (sourceMapJson === null) {
|
|
return undefined;
|
|
} else {
|
|
const payload = JSON.parse(sourceMapJson);
|
|
// The sourcemap from Turbopack is not yet written to disk so its `sources`
|
|
// are not absolute paths yet. We need to rewrite them to be absolute paths.
|
|
rewriteTurbopackSources(projectRoot, payload);
|
|
return payload;
|
|
}
|
|
}
|
|
async function createHotReloaderTurbopack(opts, serverFields, distDir, resetFetch, lockfile) {
|
|
var _opts_nextConfig_turbopack, _nextConfig_watchOptions, _opts_nextConfig_experimental;
|
|
const dev = true;
|
|
const buildId = 'development';
|
|
const { nextConfig, dir: projectPath } = opts;
|
|
const bindings = (0, _swc.getBindingsSync)();
|
|
// For the debugging purpose, check if createNext or equivalent next instance setup in test cases
|
|
// works correctly. Normally `run-test` hides output so only will be visible when `--debug` flag is used.
|
|
if (isTestMode) {
|
|
;
|
|
require('console').log('Creating turbopack project', {
|
|
dir: projectPath,
|
|
testMode: isTestMode
|
|
});
|
|
}
|
|
const hasRewrites = opts.fsChecker.rewrites.afterFiles.length > 0 || opts.fsChecker.rewrites.beforeFiles.length > 0 || opts.fsChecker.rewrites.fallback.length > 0;
|
|
const hotReloaderSpan = (0, _trace.trace)('hot-reloader', undefined, {
|
|
version: "16.1.4"
|
|
});
|
|
// Ensure the hotReloaderSpan is flushed immediately as it's the parentSpan for all processing
|
|
// of the current `next dev` invocation.
|
|
hotReloaderSpan.stop();
|
|
// Initialize log monitor for file logging
|
|
// Enable logging by default in development mode
|
|
const mcpServerEnabled = !!nextConfig.experimental.mcpServer;
|
|
const fileLogger = (0, _filelogger.getFileLogger)();
|
|
fileLogger.initialize(distDir, mcpServerEnabled);
|
|
const encryptionKey = await (0, _encryptionutilsserver.generateEncryptionKeyBase64)({
|
|
isBuild: false,
|
|
distDir
|
|
});
|
|
// TODO: Implement
|
|
let clientRouterFilters;
|
|
if (nextConfig.experimental.clientRouterFilter) {
|
|
// TODO this need to be set correctly for filesystem cache to work
|
|
}
|
|
const supportedBrowsers = (0, _utils3.getSupportedBrowsers)(projectPath, dev);
|
|
const currentNodeJsVersion = process.versions.node;
|
|
const rootPath = ((_opts_nextConfig_turbopack = opts.nextConfig.turbopack) == null ? void 0 : _opts_nextConfig_turbopack.root) || opts.nextConfig.outputFileTracingRoot || projectPath;
|
|
const project = await bindings.turbo.createProject({
|
|
rootPath,
|
|
projectPath: (0, _normalizepath.normalizePath)((0, _path.relative)(rootPath, projectPath) || '.'),
|
|
distDir,
|
|
nextConfig: opts.nextConfig,
|
|
watch: {
|
|
enable: dev,
|
|
pollIntervalMs: (_nextConfig_watchOptions = nextConfig.watchOptions) == null ? void 0 : _nextConfig_watchOptions.pollIntervalMs
|
|
},
|
|
dev,
|
|
env: process.env,
|
|
defineEnv: (0, _swc.createDefineEnv)({
|
|
isTurbopack: true,
|
|
clientRouterFilters,
|
|
config: nextConfig,
|
|
dev,
|
|
distDir,
|
|
projectPath,
|
|
fetchCacheKeyPrefix: opts.nextConfig.experimental.fetchCacheKeyPrefix,
|
|
hasRewrites,
|
|
// TODO: Implement
|
|
middlewareMatchers: undefined,
|
|
rewrites: opts.fsChecker.rewrites
|
|
}),
|
|
buildId,
|
|
encryptionKey,
|
|
previewProps: opts.fsChecker.prerenderManifest.preview,
|
|
browserslistQuery: supportedBrowsers.join(', '),
|
|
noMangling: false,
|
|
writeRoutesHashesManifest: false,
|
|
currentNodeJsVersion
|
|
}, {
|
|
persistentCaching: (0, _utils2.isFileSystemCacheEnabledForDev)(opts.nextConfig),
|
|
memoryLimit: (_opts_nextConfig_experimental = opts.nextConfig.experimental) == null ? void 0 : _opts_nextConfig_experimental.turbopackMemoryLimit,
|
|
isShortSession: false
|
|
});
|
|
(0, _compilationevents.backgroundLogCompilationEvents)(project, {
|
|
eventTypes: [
|
|
'StartupCacheInvalidationEvent',
|
|
'TimingEvent'
|
|
]
|
|
});
|
|
(0, _patcherrorinspect.setBundlerFindSourceMapImplementation)(getSourceMapFromTurbopack.bind(null, project, projectPath));
|
|
opts.onDevServerCleanup == null ? void 0 : opts.onDevServerCleanup.call(opts, async ()=>{
|
|
(0, _patcherrorinspect.setBundlerFindSourceMapImplementation)(()=>undefined);
|
|
await project.onExit();
|
|
await (lockfile == null ? void 0 : lockfile.unlock());
|
|
});
|
|
const entrypointsSubscription = project.entrypointsSubscribe();
|
|
const currentWrittenEntrypoints = new Map();
|
|
const currentEntrypoints = {
|
|
global: {
|
|
app: undefined,
|
|
document: undefined,
|
|
error: undefined,
|
|
middleware: undefined,
|
|
instrumentation: undefined
|
|
},
|
|
page: new Map(),
|
|
app: new Map()
|
|
};
|
|
const currentTopLevelIssues = new Map();
|
|
const currentEntryIssues = new Map();
|
|
const manifestLoader = new _manifestloader.TurbopackManifestLoader({
|
|
buildId,
|
|
distDir,
|
|
encryptionKey
|
|
});
|
|
// Dev specific
|
|
const changeSubscriptions = new Map();
|
|
const serverPathState = new Map();
|
|
const readyIds = new Set();
|
|
let currentEntriesHandlingResolve;
|
|
let currentEntriesHandling = new Promise((resolve)=>currentEntriesHandlingResolve = resolve);
|
|
const assetMapper = new _turbopackutils.AssetMapper();
|
|
function clearRequireCache(key, writtenEndpoint, { force } = {}) {
|
|
if (force) {
|
|
for (const { path, contentHash } of writtenEndpoint.serverPaths){
|
|
// We ignore source maps
|
|
if (path.endsWith('.map')) continue;
|
|
const localKey = `${key}:${path}`;
|
|
serverPathState.set(localKey, contentHash);
|
|
serverPathState.set(path, contentHash);
|
|
}
|
|
} else {
|
|
// Figure out if the server files have changed
|
|
let hasChange = false;
|
|
for (const { path, contentHash } of writtenEndpoint.serverPaths){
|
|
// We ignore source maps
|
|
if (path.endsWith('.map')) continue;
|
|
const localKey = `${key}:${path}`;
|
|
const localHash = serverPathState.get(localKey);
|
|
const globalHash = serverPathState.get(path);
|
|
if (localHash && localHash !== contentHash || globalHash && globalHash !== contentHash) {
|
|
hasChange = true;
|
|
serverPathState.set(localKey, contentHash);
|
|
serverPathState.set(path, contentHash);
|
|
} else {
|
|
if (!localHash) {
|
|
serverPathState.set(localKey, contentHash);
|
|
}
|
|
if (!globalHash) {
|
|
serverPathState.set(path, contentHash);
|
|
}
|
|
}
|
|
}
|
|
if (!hasChange) {
|
|
return false;
|
|
}
|
|
}
|
|
resetFetch();
|
|
// Not available in:
|
|
// - Pages Router (no server-side HMR)
|
|
// - Edge Runtime (uses browser runtime which already disposes chunks individually)
|
|
if (typeof __next__clear_chunk_cache__ === 'function') {
|
|
__next__clear_chunk_cache__();
|
|
}
|
|
const serverPaths = writtenEndpoint.serverPaths.map(({ path: p })=>(0, _path.join)(distDir, p));
|
|
for (const file of serverPaths){
|
|
(0, _renderserver.clearModuleContext)(file);
|
|
(0, _requirecache.deleteCache)(file);
|
|
}
|
|
return true;
|
|
}
|
|
const buildingIds = new Set();
|
|
const startBuilding = (id, requestUrl, forceRebuild)=>{
|
|
if (!forceRebuild && readyIds.has(id)) {
|
|
return ()=>{};
|
|
}
|
|
if (buildingIds.size === 0) {
|
|
_store.store.setState({
|
|
loading: true,
|
|
trigger: id,
|
|
url: requestUrl
|
|
}, true);
|
|
}
|
|
buildingIds.add(id);
|
|
return function finishBuilding() {
|
|
if (buildingIds.size === 0) {
|
|
return;
|
|
}
|
|
readyIds.add(id);
|
|
buildingIds.delete(id);
|
|
if (buildingIds.size === 0) {
|
|
hmrEventHappened = false;
|
|
_store.store.setState({
|
|
loading: false
|
|
}, true);
|
|
}
|
|
};
|
|
};
|
|
let hmrEventHappened = false;
|
|
let hmrHash = 0;
|
|
const clientsWithoutHtmlRequestId = new Set();
|
|
const clientsByHtmlRequestId = new Map();
|
|
const cacheStatusesByHtmlRequestId = new Map();
|
|
const clientStates = new WeakMap();
|
|
function sendToClient(client, message) {
|
|
const data = typeof message.type === 'number' ? (0, _messages.createBinaryHmrMessageData)(message) : JSON.stringify(message);
|
|
client.send(data);
|
|
}
|
|
function sendEnqueuedMessages() {
|
|
for (const [, issueMap] of currentEntryIssues){
|
|
if ([
|
|
...issueMap.values()
|
|
].filter((i)=>i.severity !== 'warning').length > 0) {
|
|
// During compilation errors we want to delay the HMR events until errors are fixed
|
|
return;
|
|
}
|
|
}
|
|
for (const client of [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
]){
|
|
const state = clientStates.get(client);
|
|
if (!state) {
|
|
continue;
|
|
}
|
|
for (const [, issueMap] of state.clientIssues){
|
|
if ([
|
|
...issueMap.values()
|
|
].filter((i)=>i.severity !== 'warning').length > 0) {
|
|
// During compilation errors we want to delay the HMR events until errors are fixed
|
|
return;
|
|
}
|
|
}
|
|
for (const message of state.messages.values()){
|
|
sendToClient(client, message);
|
|
}
|
|
state.messages.clear();
|
|
if (state.turbopackUpdates.length > 0) {
|
|
sendToClient(client, {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_MESSAGE,
|
|
data: state.turbopackUpdates
|
|
});
|
|
state.turbopackUpdates.length = 0;
|
|
}
|
|
}
|
|
}
|
|
const sendEnqueuedMessagesDebounce = (0, _utils1.debounce)(sendEnqueuedMessages, 2);
|
|
const sendHmr = (id, message)=>{
|
|
for (const client of [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
]){
|
|
var _clientStates_get;
|
|
(_clientStates_get = clientStates.get(client)) == null ? void 0 : _clientStates_get.messages.set(id, message);
|
|
}
|
|
hmrEventHappened = true;
|
|
sendEnqueuedMessagesDebounce();
|
|
};
|
|
function sendTurbopackMessage(payload) {
|
|
// TODO(PACK-2049): For some reason we end up emitting hundreds of issues messages on bigger apps,
|
|
// a lot of which are duplicates.
|
|
// They are currently not handled on the client at all, so might as well not send them for now.
|
|
payload.diagnostics = [];
|
|
payload.issues = [];
|
|
for (const client of [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
]){
|
|
var _clientStates_get;
|
|
(_clientStates_get = clientStates.get(client)) == null ? void 0 : _clientStates_get.turbopackUpdates.push(payload);
|
|
}
|
|
hmrEventHappened = true;
|
|
sendEnqueuedMessagesDebounce();
|
|
}
|
|
async function subscribeToChanges(key, includeIssues, endpoint, createMessage, onError) {
|
|
if (changeSubscriptions.has(key)) {
|
|
return;
|
|
}
|
|
const { side } = (0, _entrykey.splitEntryKey)(key);
|
|
const changedPromise = endpoint[`${side}Changed`](includeIssues);
|
|
changeSubscriptions.set(key, changedPromise);
|
|
try {
|
|
const changed = await changedPromise;
|
|
for await (const change of changed){
|
|
(0, _utils2.processIssues)(currentEntryIssues, key, change, false, true);
|
|
// TODO: Get an actual content hash from Turbopack.
|
|
const message = await createMessage(change, String(++hmrHash));
|
|
if (message) {
|
|
sendHmr(key, message);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
changeSubscriptions.delete(key);
|
|
const payload = await (onError == null ? void 0 : onError(e));
|
|
if (payload) {
|
|
sendHmr(key, payload);
|
|
}
|
|
return;
|
|
}
|
|
changeSubscriptions.delete(key);
|
|
}
|
|
async function unsubscribeFromChanges(key) {
|
|
const subscription = await changeSubscriptions.get(key);
|
|
if (subscription) {
|
|
await (subscription.return == null ? void 0 : subscription.return.call(subscription));
|
|
changeSubscriptions.delete(key);
|
|
}
|
|
currentEntryIssues.delete(key);
|
|
}
|
|
async function subscribeToHmrEvents(client, id) {
|
|
const key = (0, _entrykey.getEntryKey)('assets', 'client', id);
|
|
if (!(0, _turbopackutils.hasEntrypointForKey)(currentEntrypoints, key, assetMapper)) {
|
|
// maybe throw an error / force the client to reload?
|
|
return;
|
|
}
|
|
const state = clientStates.get(client);
|
|
if (!state || state.subscriptions.has(id)) {
|
|
return;
|
|
}
|
|
const subscription = project.hmrEvents(id);
|
|
state.subscriptions.set(id, subscription);
|
|
// The subscription will always emit once, which is the initial
|
|
// computation. This is not a change, so swallow it.
|
|
try {
|
|
await subscription.next();
|
|
for await (const data of subscription){
|
|
(0, _utils2.processIssues)(state.clientIssues, key, data, false, true);
|
|
if (data.type !== 'issues') {
|
|
sendTurbopackMessage(data);
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// The client might be using an HMR session from a previous server, tell them
|
|
// to fully reload the page to resolve the issue. We can't use
|
|
// `hotReloader.send` since that would force every connected client to
|
|
// reload, only this client is out of date.
|
|
const reloadMessage = {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.RELOAD_PAGE,
|
|
data: `error in HMR event subscription for ${id}: ${e}`
|
|
};
|
|
sendToClient(client, reloadMessage);
|
|
client.close();
|
|
return;
|
|
}
|
|
}
|
|
function unsubscribeFromHmrEvents(client, id) {
|
|
const state = clientStates.get(client);
|
|
if (!state) {
|
|
return;
|
|
}
|
|
const subscription = state.subscriptions.get(id);
|
|
subscription == null ? void 0 : subscription.return();
|
|
const key = (0, _entrykey.getEntryKey)('assets', 'client', id);
|
|
state.clientIssues.delete(key);
|
|
}
|
|
async function handleEntrypointsSubscription() {
|
|
for await (const entrypoints of entrypointsSubscription){
|
|
if (!currentEntriesHandlingResolve) {
|
|
currentEntriesHandling = new Promise(// eslint-disable-next-line no-loop-func
|
|
(resolve)=>currentEntriesHandlingResolve = resolve);
|
|
}
|
|
// Always process issues/diagnostics, even if there are no entrypoints yet
|
|
(0, _turbopackutils.processTopLevelIssues)(currentTopLevelIssues, entrypoints);
|
|
// Certain crtical issues prevent any entrypoints from being constructed so return early
|
|
if (!('routes' in entrypoints)) {
|
|
(0, _utils3.printBuildErrors)(entrypoints, true);
|
|
currentEntriesHandlingResolve();
|
|
currentEntriesHandlingResolve = undefined;
|
|
continue;
|
|
}
|
|
const routes = entrypoints.routes;
|
|
const existingRoutes = [
|
|
...currentEntrypoints.app.keys(),
|
|
...currentEntrypoints.page.keys()
|
|
];
|
|
const newRoutes = [
|
|
...routes.keys()
|
|
];
|
|
const addedRoutes = newRoutes.filter((route)=>!currentEntrypoints.app.has(route) && !currentEntrypoints.page.has(route));
|
|
const removedRoutes = existingRoutes.filter((route)=>!routes.has(route));
|
|
await (0, _turbopackutils.handleEntrypoints)({
|
|
entrypoints: entrypoints,
|
|
currentEntrypoints,
|
|
currentEntryIssues,
|
|
manifestLoader,
|
|
devRewrites: opts.fsChecker.rewrites,
|
|
productionRewrites: undefined,
|
|
logErrors: true,
|
|
dev: {
|
|
assetMapper,
|
|
changeSubscriptions,
|
|
clients: [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
],
|
|
clientStates,
|
|
serverFields,
|
|
hooks: {
|
|
handleWrittenEndpoint: (id, result, forceDeleteCache)=>{
|
|
currentWrittenEntrypoints.set(id, result);
|
|
return clearRequireCache(id, result, {
|
|
force: forceDeleteCache
|
|
});
|
|
},
|
|
propagateServerField: _setupdevbundler.propagateServerField.bind(null, opts),
|
|
sendHmr,
|
|
startBuilding,
|
|
subscribeToChanges,
|
|
unsubscribeFromChanges,
|
|
unsubscribeFromHmrEvents
|
|
}
|
|
}
|
|
});
|
|
// Reload matchers when the files have been compiled
|
|
await (0, _setupdevbundler.propagateServerField)(opts, 'reloadMatchers', undefined);
|
|
if (addedRoutes.length > 0 || removedRoutes.length > 0) {
|
|
// When the list of routes changes a new manifest should be fetched for Pages Router.
|
|
hotReloader.send({
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.DEV_PAGES_MANIFEST_UPDATE,
|
|
data: [
|
|
{
|
|
devPagesManifest: true
|
|
}
|
|
]
|
|
});
|
|
}
|
|
for (const route of addedRoutes){
|
|
hotReloader.send({
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.ADDED_PAGE,
|
|
data: [
|
|
route
|
|
]
|
|
});
|
|
}
|
|
for (const route of removedRoutes){
|
|
hotReloader.send({
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REMOVED_PAGE,
|
|
data: [
|
|
route
|
|
]
|
|
});
|
|
}
|
|
currentEntriesHandlingResolve();
|
|
currentEntriesHandlingResolve = undefined;
|
|
}
|
|
}
|
|
await (0, _promises.mkdir)((0, _path.join)(distDir, 'server'), {
|
|
recursive: true
|
|
});
|
|
await (0, _promises.mkdir)((0, _path.join)(distDir, 'static', buildId), {
|
|
recursive: true
|
|
});
|
|
await (0, _promises.writeFile)((0, _path.join)(distDir, 'package.json'), JSON.stringify({
|
|
type: 'commonjs'
|
|
}, null, 2));
|
|
const middlewares = [
|
|
(0, _middlewareturbopack.getOverlayMiddleware)({
|
|
project,
|
|
projectPath,
|
|
isSrcDir: opts.isSrcDir
|
|
}),
|
|
(0, _middlewareturbopack.getSourceMapMiddleware)(project),
|
|
(0, _getnexterrorfeedbackmiddleware.getNextErrorFeedbackMiddleware)(opts.telemetry),
|
|
(0, _getdevoverlayfontmiddleware.getDevOverlayFontMiddleware)(),
|
|
(0, _devindicatormiddleware.getDisableDevIndicatorMiddleware)(),
|
|
(0, _restartdevservermiddleware.getRestartDevServerMiddleware)({
|
|
telemetry: opts.telemetry,
|
|
turbopackProject: project
|
|
}),
|
|
(0, _devtoolsconfigmiddleware.devToolsConfigMiddleware)({
|
|
distDir,
|
|
sendUpdateSignal: (data)=>{
|
|
hotReloader.send({
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.DEVTOOLS_CONFIG,
|
|
data
|
|
});
|
|
}
|
|
}),
|
|
(0, _attachnodejsdebuggermiddleware.getAttachNodejsDebuggerMiddleware)(),
|
|
...nextConfig.experimental.mcpServer ? [
|
|
(0, _getmcpmiddleware.getMcpMiddleware)({
|
|
projectPath,
|
|
distDir,
|
|
nextConfig,
|
|
pagesDir: opts.pagesDir,
|
|
appDir: opts.appDir,
|
|
sendHmrMessage: (message)=>hotReloader.send(message),
|
|
getActiveConnectionCount: ()=>clientsWithoutHtmlRequestId.size + clientsByHtmlRequestId.size,
|
|
getDevServerUrl: ()=>process.env.__NEXT_PRIVATE_ORIGIN
|
|
})
|
|
] : []
|
|
];
|
|
(0, _formaterrors.setStackFrameResolver)(async (request)=>{
|
|
return (0, _middlewareturbopack.getOriginalStackFrames)({
|
|
project,
|
|
projectPath,
|
|
isServer: request.isServer,
|
|
isEdgeServer: request.isEdgeServer,
|
|
isAppDirectory: request.isAppDirectory,
|
|
frames: request.frames
|
|
});
|
|
});
|
|
let versionInfoCached;
|
|
// This fetch, even though not awaited, is not kicked off eagerly because the first `fetch()` in
|
|
// Node.js adds roughly 20ms main-thread blocking to load the SSL certificate cache
|
|
// We don't want that blocking time to be in the hot path for the `ready in` logging.
|
|
// Instead, the fetch is kicked off lazily when the first `getVersionInfoCached()` is called.
|
|
const getVersionInfoCached = ()=>{
|
|
if (!versionInfoCached) {
|
|
versionInfoCached = (0, _hotreloadersharedutils.getVersionInfo)();
|
|
}
|
|
return versionInfoCached;
|
|
};
|
|
let devtoolsFrontendUrl;
|
|
const inspectorURLRaw = _inspector.url();
|
|
if (inspectorURLRaw !== undefined) {
|
|
const inspectorURL = new URL(inspectorURLRaw);
|
|
let debugInfo;
|
|
try {
|
|
const debugInfoList = await fetch(`http://${inspectorURL.host}/json/list`).then((res)=>res.json());
|
|
debugInfo = debugInfoList[0];
|
|
} catch {}
|
|
if (debugInfo) {
|
|
devtoolsFrontendUrl = debugInfo.devtoolsFrontendUrl;
|
|
}
|
|
}
|
|
const hotReloader = {
|
|
turbopackProject: project,
|
|
activeWebpackConfigs: undefined,
|
|
serverStats: null,
|
|
edgeServerStats: null,
|
|
async run (req, res, _parsedUrl) {
|
|
var _req_url;
|
|
// intercept page chunks request and ensure them with turbopack
|
|
if ((_req_url = req.url) == null ? void 0 : _req_url.startsWith('/_next/static/chunks/pages/')) {
|
|
const params = (0, _hotreloadersharedutils.matchNextPageBundleRequest)(req.url);
|
|
if (params) {
|
|
const decodedPagePath = `/${params.path.map((param)=>decodeURIComponent(param)).join('/')}`;
|
|
const denormalizedPagePath = (0, _denormalizepagepath.denormalizePagePath)(decodedPagePath);
|
|
await hotReloader.ensurePage({
|
|
page: denormalizedPagePath,
|
|
clientOnly: false,
|
|
definition: undefined,
|
|
url: req.url
|
|
}).catch(console.error);
|
|
}
|
|
}
|
|
for (const middleware of middlewares){
|
|
let calledNext = false;
|
|
await middleware(req, res, ()=>{
|
|
calledNext = true;
|
|
});
|
|
if (!calledNext) {
|
|
return {
|
|
finished: true
|
|
};
|
|
}
|
|
}
|
|
// Request was not finished.
|
|
return {
|
|
finished: undefined
|
|
};
|
|
},
|
|
// TODO: Figure out if socket type can match the NextJsHotReloaderInterface
|
|
onHMR (req, socket, head, onUpgrade) {
|
|
wsServer.handleUpgrade(req, socket, head, (client)=>{
|
|
const clientIssues = new Map();
|
|
const subscriptions = new Map();
|
|
const htmlRequestId = req.url ? new URL(req.url, 'http://n').searchParams.get('id') : null;
|
|
// Clients with a request ID are inferred App Router clients. If Cache
|
|
// Components is not enabled, we consider those legacy clients. Pages
|
|
// Router clients are also considered legacy clients. TODO: Maybe mark
|
|
// clients as App Router / Pages Router clients explicitly, instead of
|
|
// inferring it from the presence of a request ID.
|
|
if (htmlRequestId) {
|
|
clientsByHtmlRequestId.set(htmlRequestId, client);
|
|
const enableCacheComponents = nextConfig.cacheComponents;
|
|
if (enableCacheComponents) {
|
|
onUpgrade(client, {
|
|
isLegacyClient: false
|
|
});
|
|
const cacheStatus = cacheStatusesByHtmlRequestId.get(htmlRequestId);
|
|
if (cacheStatus !== undefined) {
|
|
sendToClient(client, {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.CACHE_INDICATOR,
|
|
state: cacheStatus
|
|
});
|
|
cacheStatusesByHtmlRequestId.delete(htmlRequestId);
|
|
}
|
|
} else {
|
|
onUpgrade(client, {
|
|
isLegacyClient: true
|
|
});
|
|
}
|
|
(0, _debugchannel.connectReactDebugChannelForHtmlRequest)(htmlRequestId, sendToClient.bind(null, client));
|
|
(0, _serializederrors.sendSerializedErrorsToClientForHtmlRequest)(htmlRequestId, sendToClient.bind(null, client));
|
|
} else {
|
|
clientsWithoutHtmlRequestId.add(client);
|
|
onUpgrade(client, {
|
|
isLegacyClient: true
|
|
});
|
|
}
|
|
clientStates.set(client, {
|
|
clientIssues,
|
|
messages: new Map(),
|
|
turbopackUpdates: [],
|
|
subscriptions
|
|
});
|
|
client.on('close', ()=>{
|
|
// Remove active subscriptions
|
|
for (const subscription of subscriptions.values()){
|
|
subscription.return == null ? void 0 : subscription.return.call(subscription);
|
|
}
|
|
clientStates.delete(client);
|
|
if (htmlRequestId) {
|
|
clientsByHtmlRequestId.delete(htmlRequestId);
|
|
(0, _debugchannel.deleteReactDebugChannelForHtmlRequest)(htmlRequestId);
|
|
} else {
|
|
clientsWithoutHtmlRequestId.delete(client);
|
|
}
|
|
});
|
|
client.addEventListener('message', async ({ data })=>{
|
|
const parsedData = JSON.parse(typeof data !== 'string' ? data.toString() : data);
|
|
// Next.js messages
|
|
switch(parsedData.event){
|
|
case 'span-end':
|
|
{
|
|
hotReloaderSpan.manualTraceChild(parsedData.spanName, (0, _turbopackutils.msToNs)(parsedData.startTime), (0, _turbopackutils.msToNs)(parsedData.endTime), parsedData.attributes);
|
|
break;
|
|
}
|
|
case 'client-hmr-latency':
|
|
hotReloaderSpan.manualTraceChild(parsedData.event, (0, _turbopackutils.msToNs)(parsedData.startTime), (0, _turbopackutils.msToNs)(parsedData.endTime), {
|
|
updatedModules: parsedData.updatedModules,
|
|
page: parsedData.page,
|
|
isPageHidden: parsedData.isPageHidden
|
|
});
|
|
break;
|
|
case 'client-error':
|
|
case 'client-warning':
|
|
case 'client-success':
|
|
case 'server-component-reload-page':
|
|
case 'client-reload-page':
|
|
case 'client-removed-page':
|
|
case 'client-full-reload':
|
|
const { hadRuntimeError, dependencyChain } = parsedData;
|
|
if (hadRuntimeError) {
|
|
_log.warn(_messages.FAST_REFRESH_RUNTIME_RELOAD);
|
|
}
|
|
if (Array.isArray(dependencyChain) && typeof dependencyChain[0] === 'string') {
|
|
const cleanedModulePath = dependencyChain[0].replace(/^\[project\]/, '.').replace(/ \[.*\] \(.*\)$/, '');
|
|
_log.warn(`Fast Refresh had to perform a full reload when ${cleanedModulePath} changed. Read more: https://nextjs.org/docs/messages/fast-refresh-reload`);
|
|
}
|
|
break;
|
|
case 'client-added-page':
|
|
break;
|
|
case 'browser-logs':
|
|
{
|
|
if (nextConfig.experimental.browserDebugInfoInTerminal) {
|
|
await (0, _receivelogs.receiveBrowserLogsTurbopack)({
|
|
entries: parsedData.entries,
|
|
router: parsedData.router,
|
|
sourceType: parsedData.sourceType,
|
|
project,
|
|
projectPath,
|
|
distDir,
|
|
config: nextConfig.experimental.browserDebugInfoInTerminal
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
case 'client-file-logs':
|
|
{
|
|
// Always log to file regardless of terminal flag
|
|
await (0, _receivelogs.handleClientFileLogs)(parsedData.logs);
|
|
break;
|
|
}
|
|
case 'ping':
|
|
{
|
|
break;
|
|
}
|
|
case 'mcp-error-state-response':
|
|
{
|
|
(0, _geterrors.handleErrorStateResponse)(parsedData.requestId, parsedData.errorState, parsedData.url);
|
|
break;
|
|
}
|
|
case 'mcp-page-metadata-response':
|
|
{
|
|
(0, _getpagemetadata.handlePageMetadataResponse)(parsedData.requestId, parsedData.segmentTrieData, parsedData.url);
|
|
break;
|
|
}
|
|
default:
|
|
// Might be a Turbopack message...
|
|
if (!parsedData.type) {
|
|
throw Object.defineProperty(new Error(`unrecognized HMR message "${data}"`), "__NEXT_ERROR_CODE", {
|
|
value: "E155",
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
}
|
|
}
|
|
// Turbopack messages
|
|
switch(parsedData.type){
|
|
case 'turbopack-subscribe':
|
|
subscribeToHmrEvents(client, parsedData.path);
|
|
break;
|
|
case 'turbopack-unsubscribe':
|
|
unsubscribeFromHmrEvents(client, parsedData.path);
|
|
break;
|
|
default:
|
|
if (!parsedData.event) {
|
|
throw Object.defineProperty(new Error(`unrecognized Turbopack HMR message "${data}"`), "__NEXT_ERROR_CODE", {
|
|
value: "E492",
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
}
|
|
}
|
|
});
|
|
const turbopackConnectedMessage = {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_CONNECTED,
|
|
data: {
|
|
sessionId
|
|
}
|
|
};
|
|
sendToClient(client, turbopackConnectedMessage);
|
|
const errors = [];
|
|
for (const entryIssues of currentEntryIssues.values()){
|
|
for (const issue of entryIssues.values()){
|
|
if (issue.severity !== 'warning') {
|
|
errors.push({
|
|
message: (0, _utils2.formatIssue)(issue)
|
|
});
|
|
} else {
|
|
(0, _turbopackutils.printNonFatalIssue)(issue);
|
|
}
|
|
}
|
|
}
|
|
if (_devindicatorserverstate.devIndicatorServerState.disabledUntil < Date.now()) {
|
|
_devindicatorserverstate.devIndicatorServerState.disabledUntil = 0;
|
|
}
|
|
;
|
|
(async function() {
|
|
const versionInfo = await getVersionInfoCached();
|
|
const devToolsConfig = await (0, _devtoolsconfigmiddleware.getDevToolsConfig)(distDir);
|
|
const syncMessage = {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SYNC,
|
|
errors,
|
|
warnings: [],
|
|
hash: '',
|
|
versionInfo,
|
|
debug: {
|
|
devtoolsFrontendUrl
|
|
},
|
|
devIndicator: _devindicatorserverstate.devIndicatorServerState,
|
|
devToolsConfig
|
|
};
|
|
sendToClient(client, syncMessage);
|
|
})();
|
|
});
|
|
},
|
|
send (action) {
|
|
const payload = JSON.stringify(action);
|
|
for (const client of [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
]){
|
|
client.send(payload);
|
|
}
|
|
},
|
|
sendToLegacyClients (action) {
|
|
const payload = JSON.stringify(action);
|
|
// Clients with a request ID are inferred App Router clients. If Cache
|
|
// Components is not enabled, we consider those legacy clients. Pages
|
|
// Router clients are also considered legacy clients. TODO: Maybe mark
|
|
// clients as App Router / Pages Router clients explicitly, instead of
|
|
// inferring it from the presence of a request ID.
|
|
if (!nextConfig.cacheComponents) {
|
|
for (const client of clientsByHtmlRequestId.values()){
|
|
client.send(payload);
|
|
}
|
|
}
|
|
for (const client of clientsWithoutHtmlRequestId){
|
|
client.send(payload);
|
|
}
|
|
},
|
|
setCacheStatus (status, htmlRequestId) {
|
|
// Legacy clients don't have Cache Components.
|
|
const client = clientsByHtmlRequestId.get(htmlRequestId);
|
|
if (client !== undefined) {
|
|
sendToClient(client, {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.CACHE_INDICATOR,
|
|
state: status
|
|
});
|
|
} else {
|
|
// If the client is not connected, store the status so that we can send it
|
|
// when the client connects.
|
|
cacheStatusesByHtmlRequestId.set(htmlRequestId, status);
|
|
}
|
|
},
|
|
setReactDebugChannel (debugChannel, htmlRequestId, requestId) {
|
|
const client = clientsByHtmlRequestId.get(htmlRequestId);
|
|
if (htmlRequestId === requestId) {
|
|
// The debug channel is for the HTML request.
|
|
if (client) {
|
|
// If the client is connected, we can connect the debug channel for
|
|
// the HTML request immediately.
|
|
(0, _debugchannel.connectReactDebugChannel)(htmlRequestId, debugChannel, sendToClient.bind(null, client));
|
|
} else {
|
|
// Otherwise, we'll do that when the client connects and just store
|
|
// the debug channel.
|
|
(0, _debugchannel.setReactDebugChannelForHtmlRequest)(htmlRequestId, debugChannel);
|
|
}
|
|
} else if (client) {
|
|
// The debug channel is for a subsequent request (e.g. client-side
|
|
// navigation for server function call). If the client is not connected
|
|
// anymore, we don't need to connect the debug channel.
|
|
(0, _debugchannel.connectReactDebugChannel)(requestId, debugChannel, sendToClient.bind(null, client));
|
|
}
|
|
},
|
|
sendErrorsToBrowser (errorsRscStream, htmlRequestId) {
|
|
const client = clientsByHtmlRequestId.get(htmlRequestId);
|
|
if (client) {
|
|
// If the client is connected, we can send the errors immediately.
|
|
(0, _serializederrors.sendSerializedErrorsToClient)(errorsRscStream, sendToClient.bind(null, client));
|
|
} else {
|
|
// Otherwise, store the errors stream so that we can send it when the
|
|
// client connects.
|
|
(0, _serializederrors.setErrorsRscStreamForHtmlRequest)(htmlRequestId, errorsRscStream);
|
|
}
|
|
},
|
|
setHmrServerError (_error) {
|
|
// Not implemented yet.
|
|
},
|
|
clearHmrServerError () {
|
|
// Not implemented yet.
|
|
},
|
|
async start () {},
|
|
async getCompilationErrors (page) {
|
|
const appEntryKey = (0, _entrykey.getEntryKey)('app', 'server', page);
|
|
const pagesEntryKey = (0, _entrykey.getEntryKey)('pages', 'server', page);
|
|
const topLevelIssues = currentTopLevelIssues.values();
|
|
const thisEntryIssues = currentEntryIssues.get(appEntryKey) ?? currentEntryIssues.get(pagesEntryKey);
|
|
if (thisEntryIssues !== undefined && thisEntryIssues.size > 0) {
|
|
// If there is an error related to the requesting page we display it instead of the first error
|
|
return [
|
|
...topLevelIssues,
|
|
...thisEntryIssues.values()
|
|
].map((issue)=>{
|
|
const formattedIssue = (0, _utils2.formatIssue)(issue);
|
|
if (issue.severity === 'warning') {
|
|
(0, _turbopackutils.printNonFatalIssue)(issue);
|
|
return null;
|
|
} else if ((0, _utils2.isWellKnownError)(issue)) {
|
|
_log.error(formattedIssue);
|
|
}
|
|
return Object.defineProperty(new Error(formattedIssue), "__NEXT_ERROR_CODE", {
|
|
value: "E394",
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
}).filter((error)=>error !== null);
|
|
}
|
|
// Otherwise, return all errors across pages
|
|
const errors = [];
|
|
for (const issue of topLevelIssues){
|
|
if (issue.severity !== 'warning') {
|
|
errors.push(Object.defineProperty(new Error((0, _utils2.formatIssue)(issue)), "__NEXT_ERROR_CODE", {
|
|
value: "E394",
|
|
enumerable: false,
|
|
configurable: true
|
|
}));
|
|
}
|
|
}
|
|
for (const entryIssues of currentEntryIssues.values()){
|
|
for (const issue of entryIssues.values()){
|
|
if (issue.severity !== 'warning') {
|
|
const message = (0, _utils2.formatIssue)(issue);
|
|
errors.push(Object.defineProperty(new Error(message), "__NEXT_ERROR_CODE", {
|
|
value: "E394",
|
|
enumerable: false,
|
|
configurable: true
|
|
}));
|
|
} else {
|
|
(0, _turbopackutils.printNonFatalIssue)(issue);
|
|
}
|
|
}
|
|
}
|
|
return errors;
|
|
},
|
|
async invalidate ({ // .env files or tsconfig/jsconfig change
|
|
reloadAfterInvalidation }) {
|
|
if (reloadAfterInvalidation) {
|
|
for (const [key, entrypoint] of currentWrittenEntrypoints){
|
|
clearRequireCache(key, entrypoint, {
|
|
force: true
|
|
});
|
|
}
|
|
await (0, _renderserver.clearAllModuleContexts)();
|
|
this.send({
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SERVER_COMPONENT_CHANGES,
|
|
hash: String(++hmrHash)
|
|
});
|
|
}
|
|
},
|
|
async buildFallbackError () {
|
|
// Not implemented yet.
|
|
},
|
|
async ensurePage ({ page: inputPage, // Unused parameters
|
|
// clientOnly,
|
|
appPaths, definition, isApp, url: requestUrl }) {
|
|
// When there is no route definition this is an internal file not a route the user added.
|
|
// Middleware and instrumentation are handled in turbpack-utils.ts handleEntrypoints instead.
|
|
if (!definition) {
|
|
if (inputPage === '/middleware') return;
|
|
if (inputPage === '/src/middleware') return;
|
|
if (inputPage === '/instrumentation') return;
|
|
if (inputPage === '/src/instrumentation') return;
|
|
}
|
|
return hotReloaderSpan.traceChild('ensure-page', {
|
|
inputPage
|
|
}).traceAsyncFn(async ()=>{
|
|
if (_constants.BLOCKED_PAGES.includes(inputPage) && inputPage !== '/_error') {
|
|
return;
|
|
}
|
|
await currentEntriesHandling;
|
|
// TODO We shouldn't look into the filesystem again. This should use the information from entrypoints
|
|
let routeDef = definition ?? await (0, _ondemandentryhandler.findPagePathData)(projectPath, inputPage, nextConfig.pageExtensions, opts.pagesDir, opts.appDir, !!nextConfig.experimental.globalNotFound);
|
|
// If the route is actually an app page route, then we should have access
|
|
// to the app route definition, and therefore, the appPaths from it.
|
|
if (!appPaths && definition && (0, _apppageroutedefinition.isAppPageRouteDefinition)(definition)) {
|
|
appPaths = definition.appPaths;
|
|
}
|
|
let page = routeDef.page;
|
|
if (appPaths) {
|
|
const normalizedPage = (0, _apppaths.normalizeAppPath)(page);
|
|
// filter out paths that are not exact matches (e.g. catchall)
|
|
const matchingAppPaths = appPaths.filter((path)=>(0, _apppaths.normalizeAppPath)(path) === normalizedPage);
|
|
// the last item in the array is the root page, if there are parallel routes
|
|
page = matchingAppPaths[matchingAppPaths.length - 1];
|
|
}
|
|
const pathname = (definition == null ? void 0 : definition.pathname) ?? inputPage;
|
|
if (page === '/_error') {
|
|
let finishBuilding = startBuilding(pathname, requestUrl, false);
|
|
try {
|
|
await (0, _turbopackutils.handlePagesErrorRoute)({
|
|
currentEntryIssues,
|
|
entrypoints: currentEntrypoints,
|
|
manifestLoader,
|
|
devRewrites: opts.fsChecker.rewrites,
|
|
productionRewrites: undefined,
|
|
logErrors: true,
|
|
hooks: {
|
|
subscribeToChanges,
|
|
handleWrittenEndpoint: (id, result, forceDeleteCache)=>{
|
|
currentWrittenEntrypoints.set(id, result);
|
|
assetMapper.setPathsForKey(id, result.clientPaths);
|
|
return clearRequireCache(id, result, {
|
|
force: forceDeleteCache
|
|
});
|
|
}
|
|
}
|
|
});
|
|
} finally{
|
|
finishBuilding();
|
|
}
|
|
return;
|
|
}
|
|
const isInsideAppDir = routeDef.bundlePath.startsWith('app/');
|
|
const isEntryMetadataRouteFile = (0, _ismetadataroute.isMetadataRouteFile)(routeDef.filename.replace(opts.appDir || '', ''), nextConfig.pageExtensions, true);
|
|
const normalizedAppPage = isEntryMetadataRouteFile ? (0, _turbopackutils.normalizedPageToTurbopackStructureRoute)(page, (0, _path.extname)(routeDef.filename)) : page;
|
|
const route = isInsideAppDir ? currentEntrypoints.app.get(normalizedAppPage) : currentEntrypoints.page.get(page);
|
|
if (!route) {
|
|
// TODO: why is this entry missing in turbopack?
|
|
if (page === '/middleware') return;
|
|
if (page === '/src/middleware') return;
|
|
if (page === '/proxy') return;
|
|
if (page === '/src/proxy') return;
|
|
if (page === '/instrumentation') return;
|
|
if (page === '/src/instrumentation') return;
|
|
throw new _utils.PageNotFoundError(`route not found ${page}`);
|
|
}
|
|
// We don't throw on ensureOpts.isApp === true for page-api
|
|
// since this can happen when app pages make
|
|
// api requests to page API routes.
|
|
if (isApp && route.type === 'page') {
|
|
throw Object.defineProperty(new Error(`mis-matched route type: isApp && page for ${page}`), "__NEXT_ERROR_CODE", {
|
|
value: "E373",
|
|
enumerable: false,
|
|
configurable: true
|
|
});
|
|
}
|
|
const finishBuilding = startBuilding(pathname, requestUrl, false);
|
|
try {
|
|
await (0, _turbopackutils.handleRouteType)({
|
|
dev,
|
|
page,
|
|
pathname,
|
|
route,
|
|
currentEntryIssues,
|
|
entrypoints: currentEntrypoints,
|
|
manifestLoader,
|
|
readyIds,
|
|
devRewrites: opts.fsChecker.rewrites,
|
|
productionRewrites: undefined,
|
|
logErrors: true,
|
|
hooks: {
|
|
subscribeToChanges,
|
|
handleWrittenEndpoint: (id, result, forceDeleteCache)=>{
|
|
currentWrittenEntrypoints.set(id, result);
|
|
assetMapper.setPathsForKey(id, result.clientPaths);
|
|
return clearRequireCache(id, result, {
|
|
force: forceDeleteCache
|
|
});
|
|
}
|
|
}
|
|
});
|
|
} finally{
|
|
finishBuilding();
|
|
}
|
|
});
|
|
},
|
|
close () {
|
|
// Report MCP telemetry if MCP server is enabled
|
|
(0, _mcptelemetrytracker.recordMcpTelemetry)(opts.telemetry);
|
|
for (const wsClient of [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
]){
|
|
// it's okay to not cleanly close these websocket connections, this is dev
|
|
wsClient.terminate();
|
|
}
|
|
clientsWithoutHtmlRequestId.clear();
|
|
clientsByHtmlRequestId.clear();
|
|
}
|
|
};
|
|
handleEntrypointsSubscription().catch((err)=>{
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|
|
// Write empty manifests
|
|
await currentEntriesHandling;
|
|
await manifestLoader.writeManifests({
|
|
devRewrites: opts.fsChecker.rewrites,
|
|
productionRewrites: undefined,
|
|
entrypoints: currentEntrypoints
|
|
});
|
|
async function handleProjectUpdates() {
|
|
for await (const updateMessage of project.updateInfoSubscribe(30)){
|
|
switch(updateMessage.updateType){
|
|
case 'start':
|
|
{
|
|
hotReloader.send({
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.BUILDING
|
|
});
|
|
break;
|
|
}
|
|
case 'end':
|
|
{
|
|
sendEnqueuedMessages();
|
|
function addToErrorsMap(errorsMap, issueMap) {
|
|
for (const [key, issue] of issueMap){
|
|
if (issue.severity === 'warning') continue;
|
|
if (errorsMap.has(key)) continue;
|
|
const message = (0, _utils2.formatIssue)(issue);
|
|
errorsMap.set(key, {
|
|
message,
|
|
details: issue.detail ? (0, _utils2.renderStyledStringToErrorAnsi)(issue.detail) : undefined
|
|
});
|
|
}
|
|
}
|
|
function addErrors(errorsMap, issues) {
|
|
for (const issueMap of issues.values()){
|
|
addToErrorsMap(errorsMap, issueMap);
|
|
}
|
|
}
|
|
const errors = new Map();
|
|
addToErrorsMap(errors, currentTopLevelIssues);
|
|
addErrors(errors, currentEntryIssues);
|
|
for (const client of [
|
|
...clientsWithoutHtmlRequestId,
|
|
...clientsByHtmlRequestId.values()
|
|
]){
|
|
const state = clientStates.get(client);
|
|
if (!state) {
|
|
continue;
|
|
}
|
|
const clientErrors = new Map(errors);
|
|
addErrors(clientErrors, state.clientIssues);
|
|
sendToClient(client, {
|
|
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.BUILT,
|
|
hash: String(++hmrHash),
|
|
errors: [
|
|
...clientErrors.values()
|
|
],
|
|
warnings: []
|
|
});
|
|
}
|
|
if (hmrEventHappened) {
|
|
const time = updateMessage.value.duration;
|
|
const timeMessage = time > 2000 ? `${Math.round(time / 100) / 10}s` : `${time}ms`;
|
|
_log.event(`Compiled in ${timeMessage}`);
|
|
hmrEventHappened = false;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
}
|
|
}
|
|
}
|
|
handleProjectUpdates().catch((err)=>{
|
|
console.error(err);
|
|
process.exit(1);
|
|
});
|
|
return hotReloader;
|
|
}
|
|
|
|
//# sourceMappingURL=hot-reloader-turbopack.js.map
|