Decouple synchronous IO and console file tracking from node-environment setup
The random, date, web-crypto, and node-crypto environment extensions imported io-utils.tsx which pulled in dynamic-rendering, work-unit-async-storage, and other server runtime modules. Similarly, console-file imported formatConsoleArgs and getFileLogger. These modules should be bundled when used — not loaded as raw Node.js requires from the environment setup path where module aliasing and React resolution aren't configured.
This splits the IO and console-file tracking into thin dispatchers and registered handlers:
- sync-io-utils.external.tsx exports syncIO() (a no-op until registered) and registerSyncIOHandler(). The extensions call syncIO() without importing any server runtime modules.
- sync-io-handler.tsx in app-render/ contains the full sync IO implementation with all server runtime dependencies. It's intentionally not .external so its imports go through the bundler.
- console-file.external.tsx exports registerConsoleFileHandler() and dispatches to the registered handler. The formatting and file logger logic moves to console-file-handler.tsx in app-render/.
- attach-node-environment-handlers.tsx in app-render/ is a single module that wires up all handlers. Both app-page/module.ts and app-route/module.ts import it with one line.
All node-environment files and extensions are renamed with the .external suffix so the bundler always externalizes them via commonjs require(). Each extension imports node-environment.external directly so the environment is guaranteed to be ready regardless of load order. next-server.ts no longer imports node-environment since the extensions handle their own setup.