- 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
495 lines
24 KiB
JavaScript
495 lines
24 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "default", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return AppRouter;
|
|
}
|
|
});
|
|
const _interop_require_default = require("@swc/helpers/_/_interop_require_default");
|
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
const _jsxruntime = require("react/jsx-runtime");
|
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
const _approutercontextsharedruntime = require("../../shared/lib/app-router-context.shared-runtime");
|
|
const _routerreducertypes = require("./router-reducer/router-reducer-types");
|
|
const _createhreffromurl = require("./router-reducer/create-href-from-url");
|
|
const _hooksclientcontextsharedruntime = require("../../shared/lib/hooks-client-context.shared-runtime");
|
|
const _useactionqueue = require("./use-action-queue");
|
|
const _approuterannouncer = require("./app-router-announcer");
|
|
const _redirectboundary = require("./redirect-boundary");
|
|
const _findheadincache = require("./router-reducer/reducers/find-head-in-cache");
|
|
const _unresolvedthenable = require("./unresolved-thenable");
|
|
const _removebasepath = require("../remove-base-path");
|
|
const _hasbasepath = require("../has-base-path");
|
|
const _computechangedpath = require("./router-reducer/compute-changed-path");
|
|
const _navfailurehandler = require("./nav-failure-handler");
|
|
const _approuterinstance = require("./app-router-instance");
|
|
const _redirect = require("./redirect");
|
|
const _redirecterror = require("./redirect-error");
|
|
const _links = require("./links");
|
|
const _rooterrorboundary = /*#__PURE__*/ _interop_require_default._(require("./errors/root-error-boundary"));
|
|
const _globalerror = /*#__PURE__*/ _interop_require_default._(require("./builtin/global-error"));
|
|
const _boundarycomponents = require("../../lib/framework/boundary-components");
|
|
const _deploymentid = require("../../shared/lib/deployment-id");
|
|
const globalMutable = {};
|
|
function HistoryUpdater({ appRouterState }) {
|
|
(0, _react.useInsertionEffect)(()=>{
|
|
if (process.env.__NEXT_APP_NAV_FAIL_HANDLING) {
|
|
// clear pending URL as navigation is no longer
|
|
// in flight
|
|
window.next.__pendingUrl = undefined;
|
|
}
|
|
const { tree, pushRef, canonicalUrl, renderedSearch } = appRouterState;
|
|
const appHistoryState = {
|
|
tree,
|
|
renderedSearch
|
|
};
|
|
// TODO: Use Navigation API if available
|
|
const historyState = {
|
|
...pushRef.preserveCustomHistoryState ? window.history.state : {},
|
|
// Identifier is shortened intentionally.
|
|
// __NA is used to identify if the history entry can be handled by the app-router.
|
|
// __N is used to identify if the history entry can be handled by the old router.
|
|
__NA: true,
|
|
__PRIVATE_NEXTJS_INTERNALS_TREE: appHistoryState
|
|
};
|
|
if (pushRef.pendingPush && // Skip pushing an additional history entry if the canonicalUrl is the same as the current url.
|
|
// This mirrors the browser behavior for normal navigation.
|
|
(0, _createhreffromurl.createHrefFromUrl)(new URL(window.location.href)) !== canonicalUrl) {
|
|
// This intentionally mutates React state, pushRef is overwritten to ensure additional push/replace calls do not trigger an additional history entry.
|
|
pushRef.pendingPush = false;
|
|
window.history.pushState(historyState, '', canonicalUrl);
|
|
} else {
|
|
window.history.replaceState(historyState, '', canonicalUrl);
|
|
}
|
|
}, [
|
|
appRouterState
|
|
]);
|
|
(0, _react.useEffect)(()=>{
|
|
// The Next-Url and the base tree may affect the result of a prefetch
|
|
// task. Re-prefetch all visible links with the updated values. In most
|
|
// cases, this will not result in any new network requests, only if
|
|
// the prefetch result actually varies on one of these inputs.
|
|
(0, _links.pingVisibleLinks)(appRouterState.nextUrl, appRouterState.tree);
|
|
}, [
|
|
appRouterState.nextUrl,
|
|
appRouterState.tree
|
|
]);
|
|
return null;
|
|
}
|
|
function copyNextJsInternalHistoryState(data) {
|
|
if (data == null) data = {};
|
|
const currentState = window.history.state;
|
|
const __NA = currentState?.__NA;
|
|
if (__NA) {
|
|
data.__NA = __NA;
|
|
}
|
|
const __PRIVATE_NEXTJS_INTERNALS_TREE = currentState?.__PRIVATE_NEXTJS_INTERNALS_TREE;
|
|
if (__PRIVATE_NEXTJS_INTERNALS_TREE) {
|
|
data.__PRIVATE_NEXTJS_INTERNALS_TREE = __PRIVATE_NEXTJS_INTERNALS_TREE;
|
|
}
|
|
return data;
|
|
}
|
|
function Head({ headCacheNode }) {
|
|
// If this segment has a `prefetchHead`, it's the statically prefetched data.
|
|
// We should use that on initial render instead of `head`. Then we'll switch
|
|
// to `head` when the dynamic response streams in.
|
|
const head = headCacheNode !== null ? headCacheNode.head : null;
|
|
const prefetchHead = headCacheNode !== null ? headCacheNode.prefetchHead : null;
|
|
// If no prefetch data is available, then we go straight to rendering `head`.
|
|
const resolvedPrefetchRsc = prefetchHead !== null ? prefetchHead : head;
|
|
// We use `useDeferredValue` to handle switching between the prefetched and
|
|
// final values. The second argument is returned on initial render, then it
|
|
// re-renders with the first argument.
|
|
return (0, _react.useDeferredValue)(head, resolvedPrefetchRsc);
|
|
}
|
|
/**
|
|
* The global router that wraps the application components.
|
|
*/ function Router({ actionQueue, globalError, webSocket, staticIndicatorState }) {
|
|
const state = (0, _useactionqueue.useActionQueue)(actionQueue);
|
|
const { canonicalUrl } = state;
|
|
// Add memoized pathname/query for useSearchParams and usePathname.
|
|
const { searchParams, pathname } = (0, _react.useMemo)(()=>{
|
|
const url = new URL(canonicalUrl, typeof window === 'undefined' ? 'http://n' : window.location.href);
|
|
return {
|
|
// This is turned into a readonly class in `useSearchParams`
|
|
searchParams: url.searchParams,
|
|
pathname: (0, _hasbasepath.hasBasePath)(url.pathname) ? (0, _removebasepath.removeBasePath)(url.pathname) : url.pathname
|
|
};
|
|
}, [
|
|
canonicalUrl
|
|
]);
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
const { cache, tree } = state;
|
|
// This hook is in a conditional but that is ok because `process.env.NODE_ENV` never changes
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
(0, _react.useEffect)(()=>{
|
|
// Add `window.nd` for debugging purposes.
|
|
// This is not meant for use in applications as concurrent rendering will affect the cache/tree/router.
|
|
// @ts-ignore this is for debugging
|
|
window.nd = {
|
|
router: _approuterinstance.publicAppRouterInstance,
|
|
cache,
|
|
tree
|
|
};
|
|
}, [
|
|
cache,
|
|
tree
|
|
]);
|
|
}
|
|
(0, _react.useEffect)(()=>{
|
|
// If the app is restored from bfcache, it's possible that
|
|
// pushRef.mpaNavigation is true, which would mean that any re-render of this component
|
|
// would trigger the mpa navigation logic again from the lines below.
|
|
// This will restore the router to the initial state in the event that the app is restored from bfcache.
|
|
function handlePageShow(event) {
|
|
if (!event.persisted || !window.history.state?.__PRIVATE_NEXTJS_INTERNALS_TREE) {
|
|
return;
|
|
}
|
|
// Clear the pendingMpaPath value so that a subsequent MPA navigation to the same URL can be triggered.
|
|
// This is necessary because if the browser restored from bfcache, the pendingMpaPath would still be set to the value
|
|
// of the last MPA navigation.
|
|
globalMutable.pendingMpaPath = undefined;
|
|
(0, _useactionqueue.dispatchAppRouterAction)({
|
|
type: _routerreducertypes.ACTION_RESTORE,
|
|
url: new URL(window.location.href),
|
|
historyState: window.history.state.__PRIVATE_NEXTJS_INTERNALS_TREE
|
|
});
|
|
}
|
|
window.addEventListener('pageshow', handlePageShow);
|
|
return ()=>{
|
|
window.removeEventListener('pageshow', handlePageShow);
|
|
};
|
|
}, []);
|
|
(0, _react.useEffect)(()=>{
|
|
// Ensure that any redirect errors that bubble up outside of the RedirectBoundary
|
|
// are caught and handled by the router.
|
|
function handleUnhandledRedirect(event) {
|
|
const error = 'reason' in event ? event.reason : event.error;
|
|
if ((0, _redirecterror.isRedirectError)(error)) {
|
|
event.preventDefault();
|
|
const url = (0, _redirect.getURLFromRedirectError)(error);
|
|
const redirectType = (0, _redirect.getRedirectTypeFromError)(error);
|
|
// TODO: This should access the router methods directly, rather than
|
|
// go through the public interface.
|
|
if (redirectType === _redirecterror.RedirectType.push) {
|
|
_approuterinstance.publicAppRouterInstance.push(url, {});
|
|
} else {
|
|
_approuterinstance.publicAppRouterInstance.replace(url, {});
|
|
}
|
|
}
|
|
}
|
|
window.addEventListener('error', handleUnhandledRedirect);
|
|
window.addEventListener('unhandledrejection', handleUnhandledRedirect);
|
|
return ()=>{
|
|
window.removeEventListener('error', handleUnhandledRedirect);
|
|
window.removeEventListener('unhandledrejection', handleUnhandledRedirect);
|
|
};
|
|
}, []);
|
|
// When mpaNavigation flag is set do a hard navigation to the new url.
|
|
// Infinitely suspend because we don't actually want to rerender any child
|
|
// components with the new URL and any entangled state updates shouldn't
|
|
// commit either (eg: useTransition isPending should stay true until the page
|
|
// unloads).
|
|
//
|
|
// This is a side effect in render. Don't try this at home, kids. It's
|
|
// probably safe because we know this is a singleton component and it's never
|
|
// in <Offscreen>. At least I hope so. (It will run twice in dev strict mode,
|
|
// but that's... fine?)
|
|
const { pushRef } = state;
|
|
if (pushRef.mpaNavigation) {
|
|
// if there's a re-render, we don't want to trigger another redirect if one is already in flight to the same URL
|
|
if (globalMutable.pendingMpaPath !== canonicalUrl) {
|
|
const location = window.location;
|
|
if (pushRef.pendingPush) {
|
|
location.assign(canonicalUrl);
|
|
} else {
|
|
location.replace(canonicalUrl);
|
|
}
|
|
globalMutable.pendingMpaPath = canonicalUrl;
|
|
}
|
|
// TODO-APP: Should we listen to navigateerror here to catch failed
|
|
// navigations somehow? And should we call window.stop() if a SPA navigation
|
|
// should interrupt an MPA one?
|
|
// NOTE: This is intentionally using `throw` instead of `use` because we're
|
|
// inside an externally mutable condition (pushRef.mpaNavigation), which
|
|
// violates the rules of hooks.
|
|
throw _unresolvedthenable.unresolvedThenable;
|
|
}
|
|
(0, _react.useEffect)(()=>{
|
|
const originalPushState = window.history.pushState.bind(window.history);
|
|
const originalReplaceState = window.history.replaceState.bind(window.history);
|
|
// Ensure the canonical URL in the Next.js Router is updated when the URL is changed so that `usePathname` and `useSearchParams` hold the pushed values.
|
|
const applyUrlFromHistoryPushReplace = (url)=>{
|
|
const href = window.location.href;
|
|
const appHistoryState = window.history.state?.__PRIVATE_NEXTJS_INTERNALS_TREE;
|
|
(0, _react.startTransition)(()=>{
|
|
(0, _useactionqueue.dispatchAppRouterAction)({
|
|
type: _routerreducertypes.ACTION_RESTORE,
|
|
url: new URL(url ?? href, href),
|
|
historyState: appHistoryState
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* Patch pushState to ensure external changes to the history are reflected in the Next.js Router.
|
|
* Ensures Next.js internal history state is copied to the new history entry.
|
|
* Ensures usePathname and useSearchParams hold the newly provided url.
|
|
*/ window.history.pushState = function pushState(data, _unused, url) {
|
|
// TODO: Warn when Navigation API is available (navigation.navigate() should be used)
|
|
// Avoid a loop when Next.js internals trigger pushState/replaceState
|
|
if (data?.__NA || data?._N) {
|
|
return originalPushState(data, _unused, url);
|
|
}
|
|
data = copyNextJsInternalHistoryState(data);
|
|
if (url) {
|
|
applyUrlFromHistoryPushReplace(url);
|
|
}
|
|
return originalPushState(data, _unused, url);
|
|
};
|
|
/**
|
|
* Patch replaceState to ensure external changes to the history are reflected in the Next.js Router.
|
|
* Ensures Next.js internal history state is copied to the new history entry.
|
|
* Ensures usePathname and useSearchParams hold the newly provided url.
|
|
*/ window.history.replaceState = function replaceState(data, _unused, url) {
|
|
// TODO: Warn when Navigation API is available (navigation.navigate() should be used)
|
|
// Avoid a loop when Next.js internals trigger pushState/replaceState
|
|
if (data?.__NA || data?._N) {
|
|
return originalReplaceState(data, _unused, url);
|
|
}
|
|
data = copyNextJsInternalHistoryState(data);
|
|
if (url) {
|
|
applyUrlFromHistoryPushReplace(url);
|
|
}
|
|
return originalReplaceState(data, _unused, url);
|
|
};
|
|
/**
|
|
* Handle popstate event, this is used to handle back/forward in the browser.
|
|
* By default dispatches ACTION_RESTORE, however if the history entry was not pushed/replaced by app-router it will reload the page.
|
|
* That case can happen when the old router injected the history entry.
|
|
*/ const onPopState = (event)=>{
|
|
if (!event.state) {
|
|
// TODO-APP: this case only happens when pushState/replaceState was called outside of Next.js. It should probably reload the page in this case.
|
|
return;
|
|
}
|
|
// This case happens when the history entry was pushed by the `pages` router.
|
|
if (!event.state.__NA) {
|
|
window.location.reload();
|
|
return;
|
|
}
|
|
// TODO-APP: Ideally the back button should not use startTransition as it should apply the updates synchronously
|
|
// Without startTransition works if the cache is there for this path
|
|
(0, _react.startTransition)(()=>{
|
|
(0, _approuterinstance.dispatchTraverseAction)(window.location.href, event.state.__PRIVATE_NEXTJS_INTERNALS_TREE);
|
|
});
|
|
};
|
|
// Register popstate event to call onPopstate.
|
|
window.addEventListener('popstate', onPopState);
|
|
return ()=>{
|
|
window.history.pushState = originalPushState;
|
|
window.history.replaceState = originalReplaceState;
|
|
window.removeEventListener('popstate', onPopState);
|
|
};
|
|
}, []);
|
|
const { cache, tree, nextUrl, focusAndScrollRef, previousNextUrl } = state;
|
|
const matchingHead = (0, _react.useMemo)(()=>{
|
|
return (0, _findheadincache.findHeadInCache)(cache, tree[1]);
|
|
}, [
|
|
cache,
|
|
tree
|
|
]);
|
|
// Add memoized pathParams for useParams.
|
|
const pathParams = (0, _react.useMemo)(()=>{
|
|
return (0, _computechangedpath.getSelectedParams)(tree);
|
|
}, [
|
|
tree
|
|
]);
|
|
// Create instrumented promises for navigation hooks (dev-only)
|
|
// These are specially instrumented promises to show in the Suspense DevTools
|
|
// Promises are cached outside of render to survive suspense retries.
|
|
let instrumentedNavigationPromises = null;
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
const { createRootNavigationPromises } = require('./navigation-devtools');
|
|
instrumentedNavigationPromises = createRootNavigationPromises(tree, pathname, searchParams, pathParams);
|
|
}
|
|
const layoutRouterContext = (0, _react.useMemo)(()=>{
|
|
return {
|
|
parentTree: tree,
|
|
parentCacheNode: cache,
|
|
parentSegmentPath: null,
|
|
parentParams: {},
|
|
// This is the <Activity> "name" that shows up in the Suspense DevTools.
|
|
// It represents the root of the app.
|
|
debugNameContext: '/',
|
|
// Root node always has `url`
|
|
// Provided in AppTreeContext to ensure it can be overwritten in layout-router
|
|
url: canonicalUrl,
|
|
// Root segment is always active
|
|
isActive: true
|
|
};
|
|
}, [
|
|
tree,
|
|
cache,
|
|
canonicalUrl
|
|
]);
|
|
const globalLayoutRouterContext = (0, _react.useMemo)(()=>{
|
|
return {
|
|
tree,
|
|
focusAndScrollRef,
|
|
nextUrl,
|
|
previousNextUrl
|
|
};
|
|
}, [
|
|
tree,
|
|
focusAndScrollRef,
|
|
nextUrl,
|
|
previousNextUrl
|
|
]);
|
|
let head;
|
|
if (matchingHead !== null) {
|
|
// The head is wrapped in an extra component so we can use
|
|
// `useDeferredValue` to swap between the prefetched and final versions of
|
|
// the head. (This is what LayoutRouter does for segment data, too.)
|
|
//
|
|
// The `key` is used to remount the component whenever the head moves to
|
|
// a different segment.
|
|
const [headCacheNode, headKey, headKeyWithoutSearchParams] = matchingHead;
|
|
head = /*#__PURE__*/ (0, _jsxruntime.jsx)(Head, {
|
|
headCacheNode: headCacheNode
|
|
}, // Necessary for PPR: omit search params from the key to match prerendered keys
|
|
typeof window === 'undefined' ? headKeyWithoutSearchParams : headKey);
|
|
} else {
|
|
head = null;
|
|
}
|
|
let content = /*#__PURE__*/ (0, _jsxruntime.jsxs)(_redirectboundary.RedirectBoundary, {
|
|
children: [
|
|
head,
|
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_boundarycomponents.RootLayoutBoundary, {
|
|
children: cache.rsc
|
|
}),
|
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_approuterannouncer.AppRouterAnnouncer, {
|
|
tree: tree
|
|
})
|
|
]
|
|
});
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
// In development, we apply few error boundaries and hot-reloader:
|
|
// - DevRootHTTPAccessFallbackBoundary: avoid using navigation API like notFound() in root layout
|
|
// - HotReloader:
|
|
// - hot-reload the app when the code changes
|
|
// - render dev overlay
|
|
// - catch runtime errors and display global-error when necessary
|
|
if (typeof window !== 'undefined') {
|
|
const { DevRootHTTPAccessFallbackBoundary } = require('./dev-root-http-access-fallback-boundary');
|
|
content = /*#__PURE__*/ (0, _jsxruntime.jsx)(DevRootHTTPAccessFallbackBoundary, {
|
|
children: content
|
|
});
|
|
}
|
|
const HotReloader = require('../dev/hot-reloader/app/hot-reloader-app').default;
|
|
content = /*#__PURE__*/ (0, _jsxruntime.jsx)(HotReloader, {
|
|
globalError: globalError,
|
|
webSocket: webSocket,
|
|
staticIndicatorState: staticIndicatorState,
|
|
children: content
|
|
});
|
|
} else {
|
|
content = /*#__PURE__*/ (0, _jsxruntime.jsx)(_rooterrorboundary.default, {
|
|
errorComponent: globalError[0],
|
|
errorStyles: globalError[1],
|
|
children: content
|
|
});
|
|
}
|
|
return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
|
|
children: [
|
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(HistoryUpdater, {
|
|
appRouterState: state
|
|
}),
|
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(RuntimeStyles, {}),
|
|
/*#__PURE__*/ (0, _jsxruntime.jsx)(_hooksclientcontextsharedruntime.NavigationPromisesContext.Provider, {
|
|
value: instrumentedNavigationPromises,
|
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_hooksclientcontextsharedruntime.PathParamsContext.Provider, {
|
|
value: pathParams,
|
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_hooksclientcontextsharedruntime.PathnameContext.Provider, {
|
|
value: pathname,
|
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_hooksclientcontextsharedruntime.SearchParamsContext.Provider, {
|
|
value: searchParams,
|
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_approutercontextsharedruntime.GlobalLayoutRouterContext.Provider, {
|
|
value: globalLayoutRouterContext,
|
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_approutercontextsharedruntime.AppRouterContext.Provider, {
|
|
value: _approuterinstance.publicAppRouterInstance,
|
|
children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_approutercontextsharedruntime.LayoutRouterContext.Provider, {
|
|
value: layoutRouterContext,
|
|
children: content
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
]
|
|
});
|
|
}
|
|
function AppRouter({ actionQueue, globalErrorState, webSocket, staticIndicatorState }) {
|
|
(0, _navfailurehandler.useNavFailureHandler)();
|
|
const router = /*#__PURE__*/ (0, _jsxruntime.jsx)(Router, {
|
|
actionQueue: actionQueue,
|
|
globalError: globalErrorState,
|
|
webSocket: webSocket,
|
|
staticIndicatorState: staticIndicatorState
|
|
});
|
|
// At the very top level, use the default GlobalError component as the final fallback.
|
|
// When the app router itself fails, which means the framework itself fails, we show the default error.
|
|
return /*#__PURE__*/ (0, _jsxruntime.jsx)(_rooterrorboundary.default, {
|
|
errorComponent: _globalerror.default,
|
|
children: router
|
|
});
|
|
}
|
|
const runtimeStyles = new Set();
|
|
let runtimeStyleChanged = new Set();
|
|
globalThis._N_E_STYLE_LOAD = function(href) {
|
|
let len = runtimeStyles.size;
|
|
runtimeStyles.add(href);
|
|
if (runtimeStyles.size !== len) {
|
|
runtimeStyleChanged.forEach((cb)=>cb());
|
|
}
|
|
// TODO figure out how to get a promise here
|
|
// But maybe it's not necessary as react would block rendering until it's loaded
|
|
return Promise.resolve();
|
|
};
|
|
function RuntimeStyles() {
|
|
const [, forceUpdate] = _react.default.useState(0);
|
|
const renderedStylesSize = runtimeStyles.size;
|
|
(0, _react.useEffect)(()=>{
|
|
const changed = ()=>forceUpdate((c)=>c + 1);
|
|
runtimeStyleChanged.add(changed);
|
|
if (renderedStylesSize !== runtimeStyles.size) {
|
|
changed();
|
|
}
|
|
return ()=>{
|
|
runtimeStyleChanged.delete(changed);
|
|
};
|
|
}, [
|
|
renderedStylesSize,
|
|
forceUpdate
|
|
]);
|
|
const dplId = (0, _deploymentid.getDeploymentIdQueryOrEmptyString)();
|
|
return [
|
|
...runtimeStyles
|
|
].map((href, i)=>/*#__PURE__*/ (0, _jsxruntime.jsx)("link", {
|
|
rel: "stylesheet",
|
|
href: `${href}${dplId}`,
|
|
// @ts-ignore
|
|
precedence: "next"
|
|
}, i));
|
|
}
|
|
|
|
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
|
|
Object.defineProperty(exports.default, '__esModule', { value: true });
|
|
Object.assign(exports.default, exports);
|
|
module.exports = exports.default;
|
|
}
|
|
|
|
//# sourceMappingURL=app-router.js.map
|