Use strict equality (===) to prevent type coercion bugs
if (process.env.NODE_ENV === 'development') {
1'use strict';23// This is a server to host CDN distributed resources like Webpack bundles and SSR45const path = require('path');67// Do this as the first thing so that any code reading it knows the right env.8process.env.BABEL_ENV = process.env.NODE_ENV;910const babelRegister = require('@babel/register');11babelRegister({12 babelrc: false,13 ignore: [14 /\/(build|node_modules)\//,15 function (file) {16 if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {17 // Ignore everything in this folder18 // because it's a mix of CJS and ESM19 // and working with raw code is easier.20 return true;21 }22 return false;23 },24 ],25 presets: ['@babel/preset-react'],26});2728// Ensure environment variables are read.29require('../config/env');3031const fs = require('fs').promises;32const compress = require('compression');33const chalk = require('chalk');34const express = require('express');35const http = require('http');36const React = require('react');3738const {renderToPipeableStream} = require('react-dom/server');39const {createFromNodeStream} = require('react-server-dom-unbundled/client');40const {PassThrough} = require('stream');4142const app = express();4344app.use(compress());4546if (process.env.NODE_ENV === 'development') {47 // In development we host the Webpack server for live bundling.48 const webpack = require('webpack');49 const webpackMiddleware = require('webpack-dev-middleware');50 const webpackHotMiddleware = require('webpack-hot-middleware');51 const paths = require('../config/paths');52 const configFactory = require('../config/webpack.config');53 const getClientEnvironment = require('../config/env');5455 const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));5657 const config = configFactory('development');58 const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';59 const appName = require(paths.appPackageJson).name;6061 // Create a webpack compiler that is configured with custom messages.62 const compiler = webpack(config);63 app.use(64 webpackMiddleware(compiler, {65 publicPath: paths.publicUrlOrPath.slice(0, -1),66 serverSideRender: true,67 headers: () => {68 return {69 'Cache-Control': 'no-store, must-revalidate',70 };71 },72 })73 );74 app.use(webpackHotMiddleware(compiler));75}7677function request(options, body) {78 return new Promise((resolve, reject) => {79 const req = http.request(options, res => {80 resolve(res);81 });82 req.on('error', e => {83 reject(e);84 });85 body.pipe(req);86 });87}8889async function renderApp(req, res, next) {90 // Proxy the request to the regional server.91 const proxiedHeaders = {92 'X-Forwarded-Host': req.hostname,93 'X-Forwarded-For': req.ips,94 'X-Forwarded-Port': 3000,95 'X-Forwarded-Proto': req.protocol,96 };97 // Proxy other headers as desired.98 if (req.get('rsc-action')) {99 proxiedHeaders['Content-type'] = req.get('Content-type');100 proxiedHeaders['rsc-action'] = req.get('rsc-action');101 } else if (req.get('Content-type')) {102 proxiedHeaders['Content-type'] = req.get('Content-type');103 }104 if (req.headers['cache-control']) {105 proxiedHeaders['Cache-Control'] = req.get('cache-control');106 }107 if (req.get('rsc-request-id')) {108 proxiedHeaders['rsc-request-id'] = req.get('rsc-request-id');109 }110111 const requestsPrerender = req.path === '/prerender';112113 const promiseForData = request(114 {115 host: '127.0.0.1',116 port: 3001,117 method: req.method,118 path: requestsPrerender ? '/?prerender=1' : '/',119 headers: proxiedHeaders,120 },121 req122 );123124 if (req.accepts('text/html')) {125 try {126 const rscResponse = await promiseForData;127128 let virtualFs;129 let buildPath;130 if (process.env.NODE_ENV === 'development') {131 const {devMiddleware} = res.locals.webpack;132 virtualFs = devMiddleware.outputFileSystem.promises;133 buildPath = devMiddleware.stats.toJson().outputPath;134 } else {135 virtualFs = fs;136 buildPath = path.join(__dirname, '../build/');137 }138 // Read the module map from the virtual file system.139 const serverConsumerManifest = JSON.parse(140 await virtualFs.readFile(141 path.join(buildPath, 'react-ssr-manifest.json'),142 'utf8'143 )144 );145146 // Read the entrypoints containing the initial JS to bootstrap everything.147 // For other pages, the chunks in the RSC payload are enough.148 const mainJSChunks = JSON.parse(149 await virtualFs.readFile(150 path.join(buildPath, 'entrypoint-manifest.json'),151 'utf8'152 )153 ).main.js;154 // For HTML, we're a "client" emulator that runs the client code,155 // so we start by consuming the RSC payload. This needs a module156 // map that reverse engineers the client-side path to the SSR path.157158 // We need to get the formState before we start rendering but we also159 // need to run the Flight client inside the render to get all the preloads.160 // The API is ambivalent about what's the right one so we need two for now.161162 // Tee the response into two streams so that we can do both.163 const rscResponse1 = new PassThrough();164 const rscResponse2 = new PassThrough();165166 rscResponse.pipe(rscResponse1);167 rscResponse.pipe(rscResponse2);168169 const {formState} = await createFromNodeStream(170 rscResponse1,171 serverConsumerManifest172 );173 rscResponse1.end();174175 let cachedResult;176 let Root = () => {177 if (!cachedResult) {178 // Read this stream inside the render.179 cachedResult = createFromNodeStream(180 rscResponse2,181 serverConsumerManifest182 );183 }184 return React.use(cachedResult).root;185 };186 // Render it into HTML by resolving the client components187 res.set('Content-type', 'text/html');188 const {pipe} = renderToPipeableStream(React.createElement(Root), {189 bootstrapScripts: mainJSChunks,190 formState: formState,191 onShellReady() {192 pipe(res);193 },194 onShellError(error) {195 const {pipe: pipeError} = renderToPipeableStream(196 React.createElement('html', null, React.createElement('body')),197 {198 bootstrapScripts: mainJSChunks,199 }200 );201 pipeError(res);202 },203 });204 } catch (e) {205 console.error(`Failed to SSR: ${e.stack}`);206 res.statusCode = 500;207 res.end();208 }209 } else {210 try {211 const rscResponse = await promiseForData;212 // For other request, we pass-through the RSC payload.213 res.set('Content-type', 'text/x-component');214 rscResponse.on('data', data => {215 res.write(data);216 res.flush();217 });218 rscResponse.on('end', data => {219 res.end();220 });221 } catch (e) {222 console.error(`Failed to proxy request: ${e.stack}`);223 res.statusCode = 500;224 res.end();225 }226 }227}228229app.all('/', renderApp);230app.all('/prerender', renderApp);231232if (process.env.NODE_ENV === 'development') {233 app.use(express.static('public'));234235 app.get('/source-maps', async function (req, res, next) {236 // Proxy the request to the regional server.237 const proxiedHeaders = {238 'X-Forwarded-Host': req.hostname,239 'X-Forwarded-For': req.ips,240 'X-Forwarded-Port': 3000,241 'X-Forwarded-Proto': req.protocol,242 };243244 const promiseForData = request(245 {246 host: '127.0.0.1',247 port: 3001,248 method: req.method,249 path: req.originalUrl,250 headers: proxiedHeaders,251 },252 req253 );254255 try {256 const rscResponse = await promiseForData;257 res.set('Content-type', 'application/json');258 rscResponse.on('data', data => {259 res.write(data);260 res.flush();261 });262 rscResponse.on('end', data => {263 res.end();264 });265 } catch (e) {266 console.error(`Failed to proxy request: ${e.stack}`);267 res.statusCode = 500;268 res.end();269 }270 });271} else {272 // In production we host the static build output.273 app.use(express.static('build'));274}275276app.listen(3000, () => {277 console.log('Global Fizz/Webpack Server listening on port 3000...');278});279280app.on('error', function (error) {281 if (error.syscall !== 'listen') {282 throw error;283 }284285 switch (error.code) {286 case 'EACCES':287 console.error('port 3000 requires elevated privileges');288 process.exit(1);289 break;290 case 'EADDRINUSE':291 console.error('Port 3000 is already in use');292 process.exit(1);293 break;294 default:295 throw error;296 }297});
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.