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:
PascalSchattenburg
2026-01-22 14:14:15 +01:00
parent b717952234
commit d147843c76
10412 changed files with 2475583 additions and 0 deletions

View File

@@ -0,0 +1,533 @@
// Manual additions to make the generated types below work.
import type { TurbopackResult } from './types'
export type TurboTasks = { readonly __tag: unique symbol }
export type ExternalEndpoint = { readonly __tag: unique symbol }
export type NextTurboTasks = { readonly __tag: unique symbol }
export type RefCell = { readonly __tag: unique symbol }
export type NapiRouteHas = {
type: string
key?: string
value?: string
readonly __tag: unique symbol
}
export type RcStr = string
export function lightningCssTransform(args: object): Promise<unknown>
export function lightningCssTransformStyleAttribute(
args: object
): Promise<unknown>
// GENERATED-TYPES-BELOW
// DO NOT MANUALLY EDIT THESE TYPES
// You can regenerate this file by running `pnpm swc-build-native` in the root of the repo.
/* tslint:disable */
/* eslint-disable */
/* auto-generated by NAPI-RS */
export declare class ExternalObject<T> {
readonly '': {
readonly '': unique symbol
[K: symbol]: T
}
}
export declare function lockfileTryAcquireSync(
path: string
): { __napiType: 'Lockfile' } | null
export declare function lockfileTryAcquire(
path: string
): Promise<{ __napiType: 'Lockfile' } | null>
export declare function lockfileUnlockSync(lockfile: {
__napiType: 'Lockfile'
}): void
export declare function lockfileUnlock(lockfile: {
__napiType: 'Lockfile'
}): Promise<void>
export declare function mdxCompile(
value: string,
option: Buffer,
signal?: AbortSignal | undefined | null
): Promise<unknown>
export declare function mdxCompileSync(value: string, option: Buffer): string
export interface TransformOutput {
code: string
map?: string
output?: string
diagnostics: Array<string>
}
export declare function minify(
input: Buffer,
opts: Buffer,
signal?: AbortSignal | undefined | null
): Promise<TransformOutput>
export declare function minifySync(input: Buffer, opts: Buffer): TransformOutput
export interface NapiEndpointConfig {}
export interface NapiServerPath {
path: string
contentHash: string
}
export interface NapiWrittenEndpoint {
type: string
entryPath?: string
clientPaths: Array<string>
serverPaths: Array<NapiServerPath>
config: NapiEndpointConfig
}
export declare function endpointWriteToDisk(endpoint: {
__napiType: 'Endpoint'
}): Promise<TurbopackResult>
export declare function endpointServerChangedSubscribe(
endpoint: { __napiType: 'Endpoint' },
issues: boolean,
func: (...args: any[]) => any
): { __napiType: 'RootTask' }
export declare function endpointClientChangedSubscribe(
endpoint: { __napiType: 'Endpoint' },
func: (...args: any[]) => any
): { __napiType: 'RootTask' }
export interface NapiEnvVar {
name: RcStr
value: RcStr
}
export interface NapiOptionEnvVar {
name: RcStr
value?: RcStr
}
export interface NapiDraftModeOptions {
previewModeId: RcStr
previewModeEncryptionKey: RcStr
previewModeSigningKey: RcStr
}
export interface NapiWatchOptions {
/** Whether to watch the filesystem for file changes. */
enable: boolean
/**
* Enable polling at a certain interval if the native file watching doesn't work (e.g.
* docker).
*/
pollIntervalMs?: number
}
export interface NapiProjectOptions {
/**
* An absolute root path (Unix or Windows path) from which all files must be nested under.
* Trying to access a file outside this root will fail, so think of this as a chroot.
* E.g. `/home/user/projects/my-repo`.
*/
rootPath: RcStr
/**
* A path which contains the app/pages directories, relative to [`Project::root_path`], always
* Unix path. E.g. `apps/my-app`
*/
projectPath: RcStr
/**
* A path where tracing output will be written to and/or cache is read/written.
* Usually equal to the `distDir` in next.config.js.
* E.g. `.next`
*/
distDir: RcStr
/** Filesystem watcher options. */
watch: NapiWatchOptions
/** The contents of next.config.js, serialized to JSON. */
nextConfig: RcStr
/** A map of environment variables to use when compiling code. */
env: Array<NapiEnvVar>
/**
* A map of environment variables which should get injected at compile
* time.
*/
defineEnv: NapiDefineEnv
/** The mode in which Next.js is running. */
dev: boolean
/** The server actions encryption key. */
encryptionKey: RcStr
/** The build id. */
buildId: RcStr
/** Options for draft mode. */
previewProps: NapiDraftModeOptions
/** The browserslist query to use for targeting browsers. */
browserslistQuery: RcStr
/**
* When the code is minified, this opts out of the default mangling of
* local names for variables, functions etc., which can be useful for
* debugging/profiling purposes.
*/
noMangling: boolean
/** Whether to write the route hashes manifest. */
writeRoutesHashesManifest: boolean
/** The version of Node.js that is available/currently running. */
currentNodeJsVersion: RcStr
}
/** [NapiProjectOptions] with all fields optional. */
export interface NapiPartialProjectOptions {
/**
* An absolute root path (Unix or Windows path) from which all files must be nested under.
* Trying to access a file outside this root will fail, so think of this as a chroot.
* E.g. `/home/user/projects/my-repo`.
*/
rootPath?: RcStr
/**
* A path which contains the app/pages directories, relative to [`Project::root_path`], always
* a Unix path.
* E.g. `apps/my-app`
*/
projectPath?: RcStr
/** Filesystem watcher options. */
watch?: NapiWatchOptions
/** The contents of next.config.js, serialized to JSON. */
nextConfig?: RcStr
/** A map of environment variables to use when compiling code. */
env?: Array<NapiEnvVar>
/**
* A map of environment variables which should get injected at compile
* time.
*/
defineEnv?: NapiDefineEnv
/** The mode in which Next.js is running. */
dev?: boolean
/** The server actions encryption key. */
encryptionKey?: RcStr
/** The build id. */
buildId?: RcStr
/** Options for draft mode. */
previewProps?: NapiDraftModeOptions
/** The browserslist query to use for targeting browsers. */
browserslistQuery?: RcStr
/** Whether to write the route hashes manifest. */
writeRoutesHashesManifest?: boolean
/**
* When the code is minified, this opts out of the default mangling of
* local names for variables, functions etc., which can be useful for
* debugging/profiling purposes.
*/
noMangling?: boolean
}
export interface NapiDefineEnv {
client: Array<NapiOptionEnvVar>
edge: Array<NapiOptionEnvVar>
nodejs: Array<NapiOptionEnvVar>
}
export interface NapiTurboEngineOptions {
/** Use the new backend with filesystem cache enabled. */
persistentCaching?: boolean
/** An upper bound of memory that turbopack will attempt to stay under. */
memoryLimit?: number
/** Track dependencies between tasks. If false, any change during build will error. */
dependencyTracking?: boolean
/** Whether the project is running in a CI environment. */
isCi?: boolean
/** Whether the project is running in a short session. */
isShortSession?: boolean
}
export declare function projectNew(
options: NapiProjectOptions,
turboEngineOptions: NapiTurboEngineOptions,
napiCallbacks: NapiNextTurbopackCallbacksJsObject
): Promise<{ __napiType: 'Project' }>
export declare function projectUpdate(
project: { __napiType: 'Project' },
options: NapiPartialProjectOptions
): Promise<void>
/**
* Invalidates the filesystem cache so that it will be deleted next time that a turbopack project
* is created with filesystem cache enabled.
*/
export declare function projectInvalidateFileSystemCache(project: {
__napiType: 'Project'
}): Promise<void>
/**
* Runs exit handlers for the project registered using the [`ExitHandler`] API.
*
* This is called by `project_shutdown`, so if you're calling that API, you shouldn't call this
* one.
*/
export declare function projectOnExit(project: {
__napiType: 'Project'
}): Promise<void>
/**
* Runs `project_on_exit`, and then waits for turbo_tasks to gracefully shut down.
*
* This is used in builds where it's important that we completely persist turbo-tasks to disk, but
* it's skipped in the development server (`project_on_exit` is used instead with a short timeout),
* where we prioritize fast exit and user responsiveness over all else.
*/
export declare function projectShutdown(project: {
__napiType: 'Project'
}): Promise<void>
export interface AppPageNapiRoute {
/** The relative path from project_path to the route file */
originalName?: RcStr
htmlEndpoint?: ExternalObject<ExternalEndpoint>
rscEndpoint?: ExternalObject<ExternalEndpoint>
}
export interface NapiRoute {
/** The router path */
pathname: string
/** The relative path from project_path to the route file */
originalName?: RcStr
/** The type of route, eg a Page or App */
type: string
pages?: Array<AppPageNapiRoute>
endpoint?: ExternalObject<ExternalEndpoint>
htmlEndpoint?: ExternalObject<ExternalEndpoint>
rscEndpoint?: ExternalObject<ExternalEndpoint>
dataEndpoint?: ExternalObject<ExternalEndpoint>
}
export interface NapiMiddleware {
endpoint: ExternalObject<ExternalEndpoint>
isProxy: boolean
}
export interface NapiInstrumentation {
nodeJs: ExternalObject<ExternalEndpoint>
edge: ExternalObject<ExternalEndpoint>
}
export interface NapiEntrypoints {
routes: Array<NapiRoute>
middleware?: NapiMiddleware
instrumentation?: NapiInstrumentation
pagesDocumentEndpoint: ExternalObject<ExternalEndpoint>
pagesAppEndpoint: ExternalObject<ExternalEndpoint>
pagesErrorEndpoint: ExternalObject<ExternalEndpoint>
}
export declare function projectWriteAllEntrypointsToDisk(
project: { __napiType: 'Project' },
appDirOnly: boolean
): Promise<TurbopackResult>
export declare function projectEntrypoints(project: {
__napiType: 'Project'
}): Promise<TurbopackResult>
export declare function projectEntrypointsSubscribe(
project: { __napiType: 'Project' },
func: (...args: any[]) => any
): { __napiType: 'RootTask' }
export declare function projectHmrEvents(
project: { __napiType: 'Project' },
identifier: RcStr,
func: (...args: any[]) => any
): { __napiType: 'RootTask' }
export interface HmrIdentifiers {
identifiers: Array<RcStr>
}
export declare function projectHmrIdentifiersSubscribe(
project: { __napiType: 'Project' },
func: (...args: any[]) => any
): { __napiType: 'RootTask' }
export interface NapiUpdateMessage {
updateType: string
value?: NapiUpdateInfo
}
export interface NapiUpdateInfo {
duration: number
tasks: number
}
/**
* Subscribes to lifecycle events of the compilation.
*
* Emits an [UpdateMessage::Start] event when any computation starts.
* Emits an [UpdateMessage::End] event when there was no computation for the
* specified time (`aggregation_ms`). The [UpdateMessage::End] event contains
* information about the computations that happened since the
* [UpdateMessage::Start] event. It contains the duration of the computation
* (excluding the idle time that was spend waiting for `aggregation_ms`), and
* the number of tasks that were executed.
*
* The signature of the `func` is `(update_message: UpdateMessage) => void`.
*/
export declare function projectUpdateInfoSubscribe(
project: { __napiType: 'Project' },
aggregationMs: number,
func: (...args: any[]) => any
): void
/** Subscribes to all compilation events that are not cached like timing and progress information. */
export declare function projectCompilationEventsSubscribe(
project: { __napiType: 'Project' },
func: (...args: any[]) => any,
eventTypes?: Array<string> | undefined | null
): void
export interface StackFrame {
isServer: boolean
isInternal?: boolean
originalFile?: RcStr
file: RcStr
/** 1-indexed, unlike source map tokens */
line?: number
/** 1-indexed, unlike source map tokens */
column?: number
methodName?: RcStr
}
export declare function projectTraceSource(
project: { __napiType: 'Project' },
frame: StackFrame,
currentDirectoryFileUrl: string
): Promise<StackFrame | null>
export declare function projectGetSourceForAsset(
project: { __napiType: 'Project' },
filePath: RcStr
): Promise<string | null>
export declare function projectGetSourceMap(
project: { __napiType: 'Project' },
filePath: RcStr
): Promise<string | null>
export declare function projectGetSourceMapSync(
project: { __napiType: 'Project' },
filePath: RcStr
): string | null
export declare function projectWriteAnalyzeData(
project: { __napiType: 'Project' },
appDirOnly: boolean
): Promise<TurbopackResult>
/**
* A version of [`NapiNextTurbopackCallbacks`] that can accepted as an argument to a napi function.
*
* This can be converted into a [`NapiNextTurbopackCallbacks`] with
* [`NapiNextTurbopackCallbacks::from_js`].
*/
export interface NapiNextTurbopackCallbacksJsObject {
/**
* Called when we've encountered a bug in Turbopack and not in the user's code. Constructs and
* throws a `TurbopackInternalError` type. Logs to anonymized telemetry.
*
* As a result of the use of `ErrorStrategy::CalleeHandled`, the first argument is an error if
* there's a runtime conversion error. This should never happen, but if it does, the function
* can throw it instead.
*/
throwTurbopackInternalError: (
conversionError: Error | null,
opts: TurbopackInternalErrorOpts
) => never
}
/** Arguments for [`NapiNextTurbopackCallbacks::throw_turbopack_internal_error`]. */
export interface TurbopackInternalErrorOpts {
message: string
anonymizedLocation?: string
}
export declare function rootTaskDispose(rootTask: {
__napiType: 'RootTask'
}): void
export interface NapiIssue {
severity: string
stage: string
filePath: string
title: any
description?: any
detail?: any
source?: NapiIssueSource
documentationLink: string
importTraces: any
}
export interface NapiIssueSource {
source: NapiSource
range?: NapiIssueSourceRange
}
export interface NapiIssueSourceRange {
start: NapiSourcePos
end: NapiSourcePos
}
export interface NapiSource {
ident: string
content?: string
}
export interface NapiSourcePos {
line: number
column: number
}
export interface NapiDiagnostic {
category: string
name: string
payload: Record<string, string>
}
export declare function expandNextJsTemplate(
content: Buffer,
templatePath: string,
nextPackageDirPath: string,
replacements: Record<string, string>,
injections: Record<string, string>,
imports: Record<string, string | null>
): string
export declare function parse(
src: string,
options: Buffer,
filename?: string | undefined | null,
signal?: AbortSignal | undefined | null
): Promise<string>
export declare function isReactCompilerRequired(
filename: string,
signal?: AbortSignal | undefined | null
): Promise<boolean>
export declare function getModuleNamedExports(
resourcePath: string
): Promise<string[]>
export interface NapiSourceDiagnostic {
severity: string
message: string
loc: NapiIssueSourceRange
}
export declare function warnForEdgeRuntime(
source: string,
isProduction: boolean
): Promise<NapiSourceDiagnostic[]>
export declare function transform(
src: string | Buffer | undefined,
isModule: boolean,
options: Buffer,
signal?: AbortSignal | undefined | null
): Promise<unknown>
export declare function transformSync(
src: string | Buffer | undefined,
isModule: boolean,
options: Buffer
): object
export declare function startTurbopackTraceServer(
path: string,
port?: number | undefined | null
): void
export interface NextBuildContext {
/** The root directory of the workspace. */
root?: string
/** The project's directory. */
dir?: string
/**
* next.config.js's distDir. Current there's some early stage setup
* requires this Before construct a context to read next.config.js,
* which we passes separately here.
*/
distDir?: string
/** The build ID. */
buildId?: string
/** The rewrites, as computed by Next.js. */
rewrites?: NapiRewrites
defineEnv: NapiDefineEnv
}
/** Keep in sync with [`next_core::next_config::Rewrites`] */
export interface NapiRewrites {
fallback: Array<NapiRewrite>
afterFiles: Array<NapiRewrite>
beforeFiles: Array<NapiRewrite>
}
/** Keep in sync with [`next_core::next_config::Rewrite`] */
export interface NapiRewrite {
source: string
destination: string
basePath?: boolean
locale?: boolean
has?: Array<NapiRouteHas>
missing?: Array<NapiRouteHas>
}
export declare function getTargetTriple(): string
/**
* Initialize tracing subscriber to emit traces. This configures subscribers
* for Trace Event Format <https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview>.
*/
export declare function initCustomTraceSubscriber(
traceOutFilePath?: string | undefined | null
): ExternalObject<RefCell>
/**
* Teardown currently running tracing subscriber to flush out remaining traces.
* This should be called when parent node.js process exits, otherwise generated
* trace may drop traces in the buffer.
*/
export declare function teardownTraceSubscriber(
guardExternal: ExternalObject<RefCell>
): void

View File

@@ -0,0 +1,21 @@
// DO NOT MANUALLY EDIT THESE TYPES
// You can regenerate this file by running `pnpm swc-build-wasm` in the root of the repo.
/* tslint:disable */
/* eslint-disable */
export function mdxCompileSync(value: string, opts: any): any
export function mdxCompile(value: string, opts: any): Promise<any>
export function minifySync(s: string, opts: any): any
export function minify(s: string, opts: any): Promise<any>
export function transformSync(s: any, opts: any): any
export function transform(s: any, opts: any): Promise<any>
export function parseSync(s: string, opts: any): any
export function parse(s: string, opts: any): Promise<any>
export function expandNextJsTemplate(
content: Uint8Array,
template_path: string,
next_package_dir_path: string,
replacements: any,
injections: any,
imports: any
): string

View File

@@ -0,0 +1,5 @@
export function __nextjs_pure(expr) {
return expr;
}
//# sourceMappingURL=helpers.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/swc/helpers.ts"],"sourcesContent":["export function __nextjs_pure<T>(expr: T): T {\n return expr\n}\n"],"names":["__nextjs_pure","expr"],"mappings":"AAAA,OAAO,SAASA,cAAiBC,IAAO;IACtC,OAAOA;AACT","ignoreList":[0]}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
/**
* This module provides a way to install SWC bindings without eagerly loading the entire swc/index module.
*
* The swc/index module can transitively load other modules (like webpack-config) that import React,
* and React's entry point checks process.env.NODE_ENV at require time to decide whether to load
* the development or production bundle. By deferring the require of swc/index until this function
* is called, we ensure NODE_ENV is set before React is loaded.
*/ /**
* Loads and caches the native bindings. This is idempotent and should be called early so bindings
* can be accessed synchronously later.
*
* @param useWasmBinary - Whether to use WASM bindings instead of native bindings
*/ export async function installBindings(useWasmBinary = false) {
// Lazy require to avoid loading swc/index (and transitively webpack-config/React)
// before NODE_ENV is set
const { loadBindings } = require('./index');
await loadBindings(useWasmBinary);
}
//# sourceMappingURL=install-bindings.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/build/swc/install-bindings.ts"],"sourcesContent":["/**\n * This module provides a way to install SWC bindings without eagerly loading the entire swc/index module.\n *\n * The swc/index module can transitively load other modules (like webpack-config) that import React,\n * and React's entry point checks process.env.NODE_ENV at require time to decide whether to load\n * the development or production bundle. By deferring the require of swc/index until this function\n * is called, we ensure NODE_ENV is set before React is loaded.\n */\n\n/**\n * Loads and caches the native bindings. This is idempotent and should be called early so bindings\n * can be accessed synchronously later.\n *\n * @param useWasmBinary - Whether to use WASM bindings instead of native bindings\n */\nexport async function installBindings(\n useWasmBinary: boolean = false\n): Promise<void> {\n // Lazy require to avoid loading swc/index (and transitively webpack-config/React)\n // before NODE_ENV is set\n const { loadBindings } = require('./index') as typeof import('./index')\n await loadBindings(useWasmBinary)\n}\n"],"names":["installBindings","useWasmBinary","loadBindings","require"],"mappings":"AAAA;;;;;;;CAOC,GAED;;;;;CAKC,GACD,OAAO,eAAeA,gBACpBC,gBAAyB,KAAK;IAE9B,kFAAkF;IAClF,yBAAyB;IACzB,MAAM,EAAEC,YAAY,EAAE,GAAGC,QAAQ;IACjC,MAAMD,aAAaD;AACrB","ignoreList":[0]}

View File

@@ -0,0 +1,66 @@
/*
Copyright (c) 2021 The swc Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/ import vm from 'vm';
import { transformSync } from './index';
import { getJestSWCOptions } from './options';
// Jest use the `vm` [Module API](https://nodejs.org/api/vm.html#vm_class_vm_module) for ESM.
// see https://github.com/facebook/jest/issues/9430
const isSupportEsm = 'Module' in vm;
function getJestConfig(jestConfig) {
return 'config' in jestConfig ? jestConfig.config : jestConfig;
}
function isEsm(isEsmProject, filename, jestConfig) {
var _jestConfig_extensionsToTreatAsEsm;
return /\.jsx?$/.test(filename) && isEsmProject || ((_jestConfig_extensionsToTreatAsEsm = jestConfig.extensionsToTreatAsEsm) == null ? void 0 : _jestConfig_extensionsToTreatAsEsm.some((ext)=>filename.endsWith(ext)));
}
const createTransformer = (inputOptions)=>({
process (src, filename, jestOptions) {
const jestConfig = getJestConfig(jestOptions);
const swcTransformOpts = getJestSWCOptions({
isServer: jestConfig.testEnvironment === 'node' || jestConfig.testEnvironment.includes('jest-environment-node'),
filename,
jsConfig: inputOptions == null ? void 0 : inputOptions.jsConfig,
resolvedBaseUrl: inputOptions == null ? void 0 : inputOptions.resolvedBaseUrl,
pagesDir: inputOptions == null ? void 0 : inputOptions.pagesDir,
serverComponents: inputOptions == null ? void 0 : inputOptions.serverComponents,
modularizeImports: inputOptions == null ? void 0 : inputOptions.modularizeImports,
swcPlugins: inputOptions == null ? void 0 : inputOptions.swcPlugins,
compilerOptions: inputOptions == null ? void 0 : inputOptions.compilerOptions,
serverReferenceHashSalt: '',
esm: isSupportEsm && isEsm(Boolean(inputOptions == null ? void 0 : inputOptions.isEsmProject), filename, jestConfig)
});
return transformSync(src, {
...swcTransformOpts,
filename
});
}
});
module.exports = {
createTransformer
};
//# sourceMappingURL=jest-transformer.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,355 @@
import path from 'path';
import { WEBPACK_LAYERS } from '../../lib/constants';
import { shouldUseReactServerCondition, isWebpackAppPagesLayer } from '../utils';
import { escapeStringRegexp } from '../../shared/lib/escape-regexp';
const nextDirname = path.dirname(require.resolve('next/package.json'));
const nextDistPath = new RegExp(`${escapeStringRegexp(nextDirname)}[\\/]dist[\\/](shared[\\/]lib|client|pages)`);
const nodeModulesPath = /[\\/]node_modules[\\/]/;
const regeneratorRuntimePath = require.resolve('next/dist/compiled/regenerator-runtime');
function isTypeScriptFile(filename) {
return filename.endsWith('.ts') || filename.endsWith('.tsx');
}
function isCommonJSFile(filename) {
return filename.endsWith('.cjs');
}
// Ensure Next.js internals and .cjs files are output as CJS modules,
// By default all modules are output as ESM or will treated as CJS if next-swc/auto-cjs plugin detects file is CJS.
function shouldOutputCommonJs(filename) {
return isCommonJSFile(filename) || nextDistPath.test(filename);
}
export function getParserOptions({ filename, jsConfig, ...rest }) {
var _jsConfig_compilerOptions;
const isTSFile = filename.endsWith('.ts');
const hasTsSyntax = isTypeScriptFile(filename);
const enableDecorators = Boolean(jsConfig == null ? void 0 : (_jsConfig_compilerOptions = jsConfig.compilerOptions) == null ? void 0 : _jsConfig_compilerOptions.experimentalDecorators);
return {
...rest,
syntax: hasTsSyntax ? 'typescript' : 'ecmascript',
dynamicImport: true,
decorators: enableDecorators,
// Exclude regular TypeScript files from React transformation to prevent e.g. generic parameters and angle-bracket type assertion from being interpreted as JSX tags.
[hasTsSyntax ? 'tsx' : 'jsx']: !isTSFile,
importAssertions: true
};
}
function getBaseSWCOptions({ filename, jest, development, hasReactRefresh, globalWindow, esm, modularizeImports, swcPlugins, compilerOptions, resolvedBaseUrl, jsConfig, supportedBrowsers, swcCacheDir, serverComponents, serverReferenceHashSalt, bundleLayer, isCacheComponents, cacheHandlers, useCacheEnabled, trackDynamicImports }) {
var _jsConfig_compilerOptions, _jsConfig_compilerOptions1, _jsConfig_compilerOptions2, _jsConfig_compilerOptions3, _jsConfig_compilerOptions4, _jsConfig_experimental;
const isReactServerLayer = shouldUseReactServerCondition(bundleLayer);
const isAppRouterPagesLayer = isWebpackAppPagesLayer(bundleLayer);
const parserConfig = getParserOptions({
filename,
jsConfig
});
const paths = jsConfig == null ? void 0 : (_jsConfig_compilerOptions = jsConfig.compilerOptions) == null ? void 0 : _jsConfig_compilerOptions.paths;
const enableDecorators = Boolean(jsConfig == null ? void 0 : (_jsConfig_compilerOptions1 = jsConfig.compilerOptions) == null ? void 0 : _jsConfig_compilerOptions1.experimentalDecorators);
const emitDecoratorMetadata = Boolean(jsConfig == null ? void 0 : (_jsConfig_compilerOptions2 = jsConfig.compilerOptions) == null ? void 0 : _jsConfig_compilerOptions2.emitDecoratorMetadata);
const useDefineForClassFields = Boolean(jsConfig == null ? void 0 : (_jsConfig_compilerOptions3 = jsConfig.compilerOptions) == null ? void 0 : _jsConfig_compilerOptions3.useDefineForClassFields);
const plugins = (swcPlugins ?? []).filter(Array.isArray).map(([name, options])=>[
require.resolve(name),
options
]);
return {
jsc: {
...resolvedBaseUrl && paths ? {
baseUrl: resolvedBaseUrl.baseUrl,
paths
} : {},
externalHelpers: !process.versions.pnp && !jest,
parser: parserConfig,
experimental: {
keepImportAttributes: true,
emitAssertForImportAttributes: true,
plugins,
cacheRoot: swcCacheDir
},
transform: {
// Enables https://github.com/swc-project/swc/blob/0359deb4841be743d73db4536d4a22ac797d7f65/crates/swc_ecma_ext_transforms/src/jest.rs
...jest ? {
hidden: {
jest: true
}
} : {},
legacyDecorator: enableDecorators,
decoratorMetadata: emitDecoratorMetadata,
useDefineForClassFields: useDefineForClassFields,
react: {
importSource: (jsConfig == null ? void 0 : (_jsConfig_compilerOptions4 = jsConfig.compilerOptions) == null ? void 0 : _jsConfig_compilerOptions4.jsxImportSource) ?? ((compilerOptions == null ? void 0 : compilerOptions.emotion) && !isReactServerLayer ? '@emotion/react' : 'react'),
runtime: 'automatic',
pragmaFrag: 'React.Fragment',
throwIfNamespace: true,
development: !!development,
useBuiltins: true,
refresh: !!hasReactRefresh
},
optimizer: {
simplify: false,
globals: jest ? null : {
typeofs: {
window: globalWindow ? 'object' : 'undefined'
},
envs: {
NODE_ENV: development ? '"development"' : '"production"'
}
}
},
regenerator: {
importPath: regeneratorRuntimePath
}
}
},
sourceMaps: jest ? 'inline' : undefined,
removeConsole: compilerOptions == null ? void 0 : compilerOptions.removeConsole,
// disable "reactRemoveProperties" when "jest" is true
// otherwise the setting from next.config.js will be used
reactRemoveProperties: jest ? false : compilerOptions == null ? void 0 : compilerOptions.reactRemoveProperties,
// Map the k-v map to an array of pairs.
modularizeImports: modularizeImports ? Object.fromEntries(Object.entries(modularizeImports).map(([mod, config])=>[
mod,
{
...config,
transform: typeof config.transform === 'string' ? config.transform : Object.entries(config.transform).map(([key, value])=>[
key,
value
])
}
])) : undefined,
relay: compilerOptions == null ? void 0 : compilerOptions.relay,
// Always transform styled-jsx and error when `client-only` condition is triggered
styledJsx: (compilerOptions == null ? void 0 : compilerOptions.styledJsx) ?? {
useLightningcss: (jsConfig == null ? void 0 : (_jsConfig_experimental = jsConfig.experimental) == null ? void 0 : _jsConfig_experimental.useLightningcss) ?? false
},
// Disable css-in-js libs (without client-only integration) transform on server layer for server components
...!isReactServerLayer && {
emotion: getEmotionOptions(compilerOptions == null ? void 0 : compilerOptions.emotion, development),
styledComponents: getStyledComponentsOptions(compilerOptions == null ? void 0 : compilerOptions.styledComponents, development)
},
serverComponents: serverComponents && !jest ? {
isReactServerLayer,
cacheComponentsEnabled: isCacheComponents,
useCacheEnabled
} : undefined,
serverActions: isAppRouterPagesLayer && !jest ? {
isReactServerLayer,
isDevelopment: development,
useCacheEnabled,
hashSalt: serverReferenceHashSalt,
cacheKinds: [
'default',
'remote',
'private'
].concat(cacheHandlers ? Object.keys(cacheHandlers) : [])
} : undefined,
// For app router we prefer to bundle ESM,
// On server side of pages router we prefer CJS.
preferEsm: esm,
lintCodemodComments: true,
trackDynamicImports: trackDynamicImports,
debugFunctionName: development,
...supportedBrowsers && supportedBrowsers.length > 0 ? {
cssEnv: {
targets: supportedBrowsers
}
} : {}
};
}
function getStyledComponentsOptions(styledComponentsConfig, development) {
if (!styledComponentsConfig) {
return null;
} else if (typeof styledComponentsConfig === 'object') {
return {
...styledComponentsConfig,
displayName: styledComponentsConfig.displayName ?? Boolean(development)
};
} else {
return {
displayName: Boolean(development)
};
}
}
function getEmotionOptions(emotionConfig, development) {
if (!emotionConfig) {
return null;
}
let autoLabel = !!development;
if (typeof emotionConfig === 'object' && emotionConfig.autoLabel) {
switch(emotionConfig.autoLabel){
case 'never':
autoLabel = false;
break;
case 'always':
autoLabel = true;
break;
case 'dev-only':
break;
default:
emotionConfig.autoLabel;
}
}
return {
enabled: true,
autoLabel,
sourcemap: development,
...typeof emotionConfig === 'object' && {
importMap: emotionConfig.importMap,
labelFormat: emotionConfig.labelFormat,
sourcemap: development && emotionConfig.sourceMap
}
};
}
export function getJestSWCOptions({ isServer, filename, esm, modularizeImports, swcPlugins, compilerOptions, jsConfig, resolvedBaseUrl, pagesDir, serverReferenceHashSalt }) {
let baseOptions = getBaseSWCOptions({
filename,
jest: true,
development: false,
hasReactRefresh: false,
globalWindow: !isServer,
modularizeImports,
swcPlugins,
compilerOptions,
jsConfig,
resolvedBaseUrl,
supportedBrowsers: undefined,
esm,
// Don't apply server layer transformations for Jest
// Disable server / client graph assertions for Jest
bundleLayer: undefined,
serverComponents: false,
serverReferenceHashSalt
});
const useCjsModules = shouldOutputCommonJs(filename);
return {
...baseOptions,
env: {
targets: {
// Targets the current version of Node.js
node: process.versions.node
}
},
module: {
type: esm && !useCjsModules ? 'es6' : 'commonjs'
},
disableNextSsg: true,
pagesDir
};
}
export function getLoaderSWCOptions({ // This is not passed yet as "paths" resolving is handled by webpack currently.
// resolvedBaseUrl,
filename, development, isServer, pagesDir, appDir, isPageFile, isCacheComponents, hasReactRefresh, modularizeImports, optimizeServerReact, optimizePackageImports, swcPlugins, compilerOptions, jsConfig, supportedBrowsers, swcCacheDir, relativeFilePathFromRoot, serverComponents, serverReferenceHashSalt, bundleLayer, esm, cacheHandlers, useCacheEnabled, trackDynamicImports }) {
let baseOptions = getBaseSWCOptions({
filename,
development,
globalWindow: !isServer,
hasReactRefresh,
modularizeImports,
swcPlugins,
compilerOptions,
jsConfig,
// resolvedBaseUrl,
supportedBrowsers,
swcCacheDir,
bundleLayer,
serverComponents,
serverReferenceHashSalt,
esm: !!esm,
isCacheComponents,
cacheHandlers,
useCacheEnabled,
trackDynamicImports
});
baseOptions.fontLoaders = {
fontLoaders: [
'next/font/local',
'next/font/google'
],
relativeFilePathFromRoot
};
baseOptions.cjsRequireOptimizer = {
packages: {
'next/server': {
transforms: {
NextRequest: 'next/dist/server/web/spec-extension/request',
NextResponse: 'next/dist/server/web/spec-extension/response',
ImageResponse: 'next/dist/server/web/spec-extension/image-response',
userAgentFromString: 'next/dist/server/web/spec-extension/user-agent',
userAgent: 'next/dist/server/web/spec-extension/user-agent'
}
}
}
};
if (optimizeServerReact && isServer && !development) {
baseOptions.optimizeServerReact = {
optimize_use_state: false
};
}
// Modularize import optimization for barrel files
if (optimizePackageImports) {
baseOptions.autoModularizeImports = {
packages: optimizePackageImports
};
}
const isNodeModules = nodeModulesPath.test(filename);
const isAppBrowserLayer = bundleLayer === WEBPACK_LAYERS.appPagesBrowser;
const moduleResolutionConfig = shouldOutputCommonJs(filename) ? {
module: {
type: 'commonjs'
}
} : {};
let options;
if (isServer) {
options = {
...baseOptions,
...moduleResolutionConfig,
// Disables getStaticProps/getServerSideProps tree shaking on the server compilation for pages
disableNextSsg: true,
isDevelopment: development,
isServerCompiler: isServer,
pagesDir,
appDir,
preferEsm: !!esm,
isPageFile,
env: {
targets: {
// Targets the current version of Node.js
node: process.versions.node
}
}
};
} else {
options = {
...baseOptions,
...moduleResolutionConfig,
disableNextSsg: !isPageFile,
isDevelopment: development,
isServerCompiler: isServer,
pagesDir,
appDir,
isPageFile,
...supportedBrowsers && supportedBrowsers.length > 0 ? {
env: {
targets: supportedBrowsers
}
} : {}
};
if (!options.env) {
// Matches default @babel/preset-env behavior
options.jsc.target = 'es5';
}
}
// For node_modules in app browser layer, we don't need to do any server side transformation.
// Only keep server actions transform to discover server actions from client components.
if (isAppBrowserLayer && isNodeModules) {
var _options_jsc_transform_optimizer_globals;
options.disableNextSsg = true;
options.isPageFile = false;
options.optimizeServerReact = undefined;
options.cjsRequireOptimizer = undefined;
// Disable optimizer for node_modules in app browser layer, to avoid unnecessary replacement.
// e.g. typeof window could result differently in js worker or browser.
if (((_options_jsc_transform_optimizer_globals = options.jsc.transform.optimizer.globals) == null ? void 0 : _options_jsc_transform_optimizer_globals.typeofs) && !filename.includes(nextDirname)) {
delete options.jsc.transform.optimizer.globals.typeofs.window;
}
}
return options;
}
//# sourceMappingURL=options.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
export { };
//# sourceMappingURL=types.js.map

File diff suppressed because one or more lines are too long