Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/next/lib/init.js
Views: 687
/*1This code makes it possible to start this nextjs server as a2Custmer Server as part of a running hub. We thus combine together3a node.js express server (the hub) with a nextjs server in a4single process.56IMPORTANT: to use this from packages/hub (say), it's critical that7packages/hub *also* have its own copy of next installed.8Otherwise, you'll see an error about910"Parsing error: Cannot find module 'next/babel'"1112This is mentioned here, and it's maybe a bug in next?13https://www.gitmemory.com/issue/vercel/next.js/26127/86266181814*/1516const { join } = require("path");17const getLogger = require("@cocalc/backend/logger").default;18const next = require("next");19const conf = require("../next.config");20const winston = getLogger("next:init");2122async function init({ basePath }) {23// dev = Whether or not to run in dev mode. This features hot module reloading,24// but navigation between pages and serving pages is much slower.25const dev = process.env.NODE_ENV != "production";2627winston.info(`basePath=${basePath}`);28// this is the next.js definition of "basePath";29// it differs from what we use in cocalc and internally here too.30conf.basePath = basePath == "/" ? "" : basePath;31conf.env.BASE_PATH = basePath;3233winston.info(`creating next.js app with dev=${dev}`);34const app = next({ dev, dir: join(__dirname, ".."), conf });3536const handle = app.getRequestHandler();37winston.info("preparing next.js app...");3839// WARNING: This webpack init below is a workaround for a bug that was40// introduced in Nextjs 13. The custom server functionality described here41// https://nextjs.org/docs/advanced-features/custom-server42// which we are using to init this server from the hub for some43// reasons tries to import a build of webpack that needs to be init'd.44// I couldn't find a report of this bug anywhere, but trying to make45// a custom server with conf set to anything caused it, but without46// conf things worked fine. Somehow I tediously figured out the47// following workaround, which is just to explicitly init webpack48// before it gets used in prepare below:49require("next/dist/compiled/webpack/webpack").init(); // see comment above.5051// app.prepare sets app.upgradeHandler, etc. --52// see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/next.ts#L27653await app.prepare();5455if (!dev) {56// The following is NOT a crazy a hack -- it's the result of me (ws)57// carefully reading nextjs source code for several hours.58// In production mode, we must completely disable the nextjs websocket upgrade59// handler, since it breaks allowing users to connect to the hub via a websocket,60// as it just kills all such connection immediately. That's done via some new61// code in nextjs v14 that IMHO the author does not understand, as you can see here:62// https://github.com/vercel/next.js/blob/23eba22d02290cff0021a53f449f1d7e32a35e56/packages/next/src/server/lib/router-server.ts#L66763// where there is a comment "// TODO: allow upgrade requests to pages/app paths?".64// In dev mode we leave this, since it suppots hot module loading, though65// we use a hack (see packages/hub/proxy/handle-upgrade.ts) that involves66// removing listeners. That hack could probably be redone better by using67// app.upgradeHandler directly.68// To see the importance of this you must:69// - build in prod mode (not dev, obviously)70// - load the cocalc next landing page /71// - then try to view /projects72// Without this fix, the websocket will disconnect. With this fix, the websocket works.73winston.info("patching upgrade handler");74app.upgradeHandler = () => {};75}7677winston.info("ready to handle requests:");78return (req, res) => {79winston.http(`req.url=${req.url}`);80handle(req, res);81};82}8384module.exports = init;858687