next
Version:
The React Framework
98 lines (97 loc) • 3.8 kB
JavaScript
import { resolve } from 'node:path';
import { readFile } from 'node:fs/promises';
import { deregisterHook, registerHook, requireFromString } from './require-hook';
import { warn } from '../output/log';
import { installDependencies } from '../../lib/install-dependencies';
function resolveSWCOptions(cwd, compilerOptions) {
const resolvedBaseUrl = resolve(cwd, compilerOptions.baseUrl ?? '.');
return {
jsc: {
target: 'es5',
parser: {
syntax: 'typescript'
},
paths: compilerOptions.paths,
baseUrl: resolvedBaseUrl
},
module: {
type: 'commonjs'
},
isModule: 'unknown'
};
}
// Ported from next/src/lib/verify-typescript-setup.ts
// Although this overlaps with the later `verifyTypeScriptSetup`,
// it is acceptable since the time difference in the worst case is trivial,
// as we are only preparing to install the dependencies once more.
async function verifyTypeScriptSetup(cwd, configFileName) {
try {
// Quick module check.
require.resolve('typescript', {
paths: [
cwd
]
});
} catch (error) {
if (error && typeof error === 'object' && 'code' in error && error.code === 'MODULE_NOT_FOUND') {
warn(`Installing TypeScript as it was not found while loading "${configFileName}".`);
await installDependencies(cwd, [
{
pkg: 'typescript'
}
], true).catch((err)=>{
if (err && typeof err === 'object' && 'command' in err) {
console.error(`Failed to install TypeScript, please install it manually to continue:\n` + err.command + '\n');
}
throw err;
});
}
}
}
async function getTsConfig(cwd) {
const ts = require(require.resolve('typescript', {
paths: [
cwd
]
}));
// NOTE: This doesn't fully cover the edge case for setting
// "typescript.tsconfigPath" in next config which is currently
// a restriction.
const tsConfigPath = ts.findConfigFile(cwd, ts.sys.fileExists, 'tsconfig.json');
if (!tsConfigPath) {
// It is ok to not return ts.getDefaultCompilerOptions() because
// we are only lookfing for paths and baseUrl from tsConfig.
return {};
}
const configFile = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
const parsedCommandLine = ts.parseJsonConfigFileContent(configFile.config, ts.sys, cwd);
return parsedCommandLine.options;
}
export async function transpileConfig({ nextConfigPath, configFileName, cwd }) {
let hasRequire = false;
try {
// Ensure TypeScript is installed to use the API.
await verifyTypeScriptSetup(cwd, configFileName);
const compilerOptions = await getTsConfig(cwd);
const swcOptions = resolveSWCOptions(cwd, compilerOptions);
const nextConfigString = await readFile(nextConfigPath, 'utf8');
// lazy require swc since it loads React before even setting NODE_ENV
// resulting loading Development React on Production
const { transform } = require('../swc');
const { code } = await transform(nextConfigString, swcOptions);
// register require hook only if require exists
if (code.includes('require(')) {
registerHook(swcOptions);
hasRequire = true;
}
// filename & extension don't matter here
return requireFromString(code, resolve(cwd, 'next.config.compiled.js'));
} catch (error) {
throw error;
} finally{
if (hasRequire) {
deregisterHook();
}
}
}
//# sourceMappingURL=transpile-config.js.map