next
Version:
The React Framework
331 lines (330 loc) • 14.8 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "nextDev", {
enumerable: true,
get: function() {
return nextDev;
}
});
require("../server/lib/cpu-profile");
const _utils = require("../server/lib/utils");
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../build/output/log"));
const _getprojectdir = require("../lib/get-project-dir");
const _constants = require("../shared/lib/constants");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _shared = require("../trace/shared");
const _storage = require("../telemetry/storage");
const _config = /*#__PURE__*/ _interop_require_default(require("../server/config"));
const _findpagesdir = require("../lib/find-pages-dir");
const _fileexists = require("../lib/file-exists");
const _getnpxcommand = require("../lib/helpers/get-npx-command");
const _mkcert = require("../lib/mkcert");
const _uploadtrace = /*#__PURE__*/ _interop_require_default(require("../trace/upload-trace"));
const _env = require("@next/env");
const _child_process = require("child_process");
const _getreservedport = require("../lib/helpers/get-reserved-port");
const _os = /*#__PURE__*/ _interop_require_default(require("os"));
const _nodeevents = require("node:events");
const _timers = require("timers");
const _trace = require("../trace");
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;
}
let dir;
let child;
let config;
let isTurboSession = false;
let traceUploadUrl;
let sessionStopHandled = false;
let sessionStarted = Date.now();
let sessionSpan = (0, _trace.trace)('next-dev');
// How long should we wait for the child to cleanly exit after sending
// SIGINT/SIGTERM to the child process before sending SIGKILL?
const CHILD_EXIT_TIMEOUT_MS = parseInt(process.env.NEXT_EXIT_TIMEOUT_MS ?? '100', 10);
const handleSessionStop = async (signal)=>{
if (signal != null && (child == null ? void 0 : child.pid)) child.kill(signal);
if (sessionStopHandled) return;
sessionStopHandled = true;
if (signal != null && (child == null ? void 0 : child.pid) && child.exitCode === null && child.signalCode === null) {
let exitTimeout = setTimeout(()=>{
child == null ? void 0 : child.kill('SIGKILL');
}, CHILD_EXIT_TIMEOUT_MS);
await (0, _nodeevents.once)(child, 'exit').catch(()=>{});
(0, _timers.clearTimeout)(exitTimeout);
}
sessionSpan.stop();
await (0, _trace.flushAllTraces)({
end: true
});
try {
const { eventCliSessionStopped } = require('../telemetry/events/session-stopped');
config = config || await (0, _config.default)(_constants.PHASE_DEVELOPMENT_SERVER, dir);
let telemetry = _shared.traceGlobals.get('telemetry') || new _storage.Telemetry({
distDir: _path.default.join(dir, config.distDir)
});
let pagesDir = !!_shared.traceGlobals.get('pagesDir');
let appDir = !!_shared.traceGlobals.get('appDir');
if (typeof _shared.traceGlobals.get('pagesDir') === 'undefined' || typeof _shared.traceGlobals.get('appDir') === 'undefined') {
const pagesResult = (0, _findpagesdir.findPagesDir)(dir);
appDir = !!pagesResult.appDir;
pagesDir = !!pagesResult.pagesDir;
}
telemetry.record(eventCliSessionStopped({
cliCommand: 'dev',
turboFlag: isTurboSession,
durationMilliseconds: Date.now() - sessionStarted,
pagesDir,
appDir
}), true);
telemetry.flushDetached('dev', dir);
} catch (_) {
// errors here aren't actionable so don't add
// noise to the output
}
if (traceUploadUrl) {
(0, _uploadtrace.default)({
traceUploadUrl,
mode: 'dev',
projectDir: dir,
distDir: config.distDir,
isTurboSession
});
}
// ensure we re-enable the terminal cursor before exiting
// the program, or the cursor could remain hidden
process.stdout.write('\x1B[?25h');
process.stdout.write('\n');
process.exit(0);
};
process.on('SIGINT', ()=>handleSessionStop('SIGINT'));
process.on('SIGTERM', ()=>handleSessionStop('SIGTERM'));
// exit event must be synchronous
process.on('exit', ()=>child == null ? void 0 : child.kill('SIGKILL'));
const nextDev = async (options, portSource, directory)=>{
dir = (0, _getprojectdir.getProjectDir)(process.env.NEXT_PRIVATE_DEV_DIR || directory);
// Check if pages dir exists and warn if not
if (!await (0, _fileexists.fileExists)(dir, _fileexists.FileType.Directory)) {
(0, _utils.printAndExit)(`> No such directory exists as the project root: ${dir}`);
}
async function preflight(skipOnReboot) {
const { getPackageVersion, getDependencies } = await Promise.resolve(require('../lib/get-package-version'));
const [sassVersion, nodeSassVersion] = await Promise.all([
getPackageVersion({
cwd: dir,
name: 'sass'
}),
getPackageVersion({
cwd: dir,
name: 'node-sass'
})
]);
if (sassVersion && nodeSassVersion) {
_log.warn('Your project has both `sass` and `node-sass` installed as dependencies, but should only use one or the other. ' + 'Please remove the `node-sass` dependency from your project. ' + ' Read more: https://nextjs.org/docs/messages/duplicate-sass');
}
if (!skipOnReboot) {
const { dependencies, devDependencies } = await getDependencies({
cwd: dir
});
// Warn if @next/font is installed as a dependency. Ignore `workspace:*` to not warn in the Next.js monorepo.
if (dependencies['@next/font'] || devDependencies['@next/font'] && devDependencies['@next/font'] !== 'workspace:*') {
const command = (0, _getnpxcommand.getNpxCommand)(dir);
_log.warn('Your project has `@next/font` installed as a dependency, please use the built-in `next/font` instead. ' + 'The `@next/font` package will be removed in Next.js 14. ' + `You can migrate by running \`${command} @next/codemod@latest built-in-next-font .\`. Read more: https://nextjs.org/docs/messages/built-in-next-font`);
}
}
}
let port = options.port;
if ((0, _getreservedport.isPortIsReserved)(port)) {
(0, _utils.printAndExit)((0, _getreservedport.getReservedPortExplanation)(port), 1);
}
// If neither --port nor PORT were specified, it's okay to retry new ports.
const allowRetry = portSource === 'default';
// We do not set a default host value here to prevent breaking
// some set-ups that rely on listening on other interfaces
const host = options.hostname;
config = await (0, _config.default)(_constants.PHASE_DEVELOPMENT_SERVER, dir);
if (options.experimentalUploadTrace && !process.env.NEXT_TRACE_UPLOAD_DISABLED) {
traceUploadUrl = options.experimentalUploadTrace;
}
const devServerOptions = {
dir,
port,
allowRetry,
isDev: true,
hostname: host
};
const isTurbopack = Boolean(options.turbo || options.turbopack || process.env.IS_TURBOPACK_TEST);
if (isTurbopack) {
process.env.TURBOPACK = '1';
}
isTurboSession = isTurbopack;
const distDir = _path.default.join(dir, config.distDir ?? '.next');
(0, _shared.setGlobal)('phase', _constants.PHASE_DEVELOPMENT_SERVER);
(0, _shared.setGlobal)('distDir', distDir);
const startServerPath = require.resolve('../server/lib/start-server');
async function startServer(startServerOptions) {
return new Promise((resolve)=>{
let resolved = false;
const defaultEnv = _env.initialEnv || process.env;
const nodeOptions = (0, _utils.getParsedNodeOptionsWithoutInspect)();
const nodeDebugType = (0, _utils.getNodeDebugType)();
let maxOldSpaceSize = (0, _utils.getMaxOldSpaceSize)();
if (!maxOldSpaceSize && !process.env.NEXT_DISABLE_MEM_OVERRIDE) {
const totalMem = _os.default.totalmem();
const totalMemInMB = Math.floor(totalMem / 1024 / 1024);
maxOldSpaceSize = Math.floor(totalMemInMB * 0.5).toString();
nodeOptions['max-old-space-size'] = maxOldSpaceSize;
// Ensure the max_old_space_size is not also set.
delete nodeOptions['max_old_space_size'];
}
if (options.disableSourceMaps) {
delete nodeOptions['enable-source-maps'];
} else {
nodeOptions['enable-source-maps'] = true;
}
if (nodeDebugType) {
const address = (0, _utils.getParsedDebugAddress)();
address.port = address.port + 1;
nodeOptions[nodeDebugType] = (0, _utils.formatDebugAddress)(address);
}
child = (0, _child_process.fork)(startServerPath, {
stdio: 'inherit',
env: {
...defaultEnv,
...isTurbopack ? {
TURBOPACK: '1'
} : undefined,
NEXT_PRIVATE_WORKER: '1',
NEXT_PRIVATE_TRACE_ID: _shared.traceId,
NODE_EXTRA_CA_CERTS: startServerOptions.selfSignedCertificate ? startServerOptions.selfSignedCertificate.rootCA : defaultEnv.NODE_EXTRA_CA_CERTS,
NODE_OPTIONS: (0, _utils.formatNodeOptions)(nodeOptions),
// There is a node.js bug on MacOS which causes closing file watchers to be really slow.
// This limits the number of watchers to mitigate the issue.
// https://github.com/nodejs/node/issues/29949
WATCHPACK_WATCHER_LIMIT: _os.default.platform() === 'darwin' ? '20' : undefined
}
});
child.on('message', (msg)=>{
if (msg && typeof msg === 'object') {
if (msg.nextWorkerReady) {
child == null ? void 0 : child.send({
nextWorkerOptions: startServerOptions
});
} else if (msg.nextServerReady && !resolved) {
if (msg.port) {
// Store the used port in case a random one was selected, so that
// it can be re-used on automatic dev server restarts.
port = parseInt(msg.port, 10);
}
resolved = true;
resolve();
}
}
});
child.on('exit', async (code, signal)=>{
if (sessionStopHandled || signal) {
return;
}
if (code === _utils.RESTART_EXIT_CODE) {
// Starting the dev server will overwrite the `.next/trace` file, so we
// must upload the existing contents before restarting the server to
// preserve the metrics.
if (traceUploadUrl) {
(0, _uploadtrace.default)({
traceUploadUrl,
mode: 'dev',
projectDir: dir,
distDir: config.distDir,
isTurboSession,
sync: true
});
}
return startServer({
...startServerOptions,
port
});
}
// Call handler (e.g. upload telemetry). Don't try to send a signal to
// the child, as it has already exited.
await handleSessionStop(/* signal */ null);
});
});
}
const runDevServer = async (reboot)=>{
try {
if (!!options.experimentalHttps) {
_log.warn('Self-signed certificates are currently an experimental feature, use with caution.');
let certificate;
const key = options.experimentalHttpsKey;
const cert = options.experimentalHttpsCert;
const rootCA = options.experimentalHttpsCa;
if (key && cert) {
certificate = {
key: _path.default.resolve(key),
cert: _path.default.resolve(cert),
rootCA: rootCA ? _path.default.resolve(rootCA) : undefined
};
} else {
certificate = await (0, _mkcert.createSelfSignedCertificate)(host);
}
await startServer({
...devServerOptions,
selfSignedCertificate: certificate
});
} else {
await startServer(devServerOptions);
}
await preflight(reboot);
} catch (err) {
console.error(err);
process.exit(1);
}
};
await runDevServer(false);
};
//# sourceMappingURL=next-dev.js.map
;