mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
This lets us put it in the same server that would be serving this content in a more real world scenario. I also de-CRA:ified this a bit by simplifying pieces we don't need. I have more refactors coming for the SSR pieces but since many are eyeing these fixtures right now I figured I'd push earlier. The design here is that there are two servers: - Global - representing a "CDN" which will also include the SSR server. - Regional - representing something close to the data with low waterfall costs which include the RSC server. This is just an example. These are using the "unbundled" strategy for the RSC server just to show a simple case, but an implementation can use a bundled SSR server. A smart SSR bundler could also put RSC and SSR in the same server and even the same JS environment. It just need to ensure that the module graphs are kept separately - so that the `react-server` condition is respected. This include `react` itself. React will start breaking if this isn't respected because the runtime will get the wrong copy of `react`. Technically, you don't need the *entire* module graph to be separated. It just needs to be any part of the graph that depends on a fork. Like if "Client A" -> "foo" and "Server B" -> "foo", then it's ok for the module "foo" to be shared. However if "foo" -> "bar", and "bar" is forked by the "react-server" condition, then "foo" also needs to be duplicated in the module graph so that it can get two copies of "bar".
135 lines
3.4 KiB
JavaScript
135 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const paths = require('./paths');
|
|
const chalk = require('chalk');
|
|
const resolve = require('resolve');
|
|
|
|
/**
|
|
* Get additional module paths based on the baseUrl of a compilerOptions object.
|
|
*
|
|
* @param {Object} options
|
|
*/
|
|
function getAdditionalModulePaths(options = {}) {
|
|
const baseUrl = options.baseUrl;
|
|
|
|
if (!baseUrl) {
|
|
return '';
|
|
}
|
|
|
|
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
|
|
|
|
// We don't need to do anything if `baseUrl` is set to `node_modules`. This is
|
|
// the default behavior.
|
|
if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {
|
|
return null;
|
|
}
|
|
|
|
// Allow the user set the `baseUrl` to `appSrc`.
|
|
if (path.relative(paths.appSrc, baseUrlResolved) === '') {
|
|
return [paths.appSrc];
|
|
}
|
|
|
|
// If the path is equal to the root directory we ignore it here.
|
|
// We don't want to allow importing from the root directly as source files are
|
|
// not transpiled outside of `src`. We do allow importing them with the
|
|
// absolute path (e.g. `src/Components/Button.js`) but we set that up with
|
|
// an alias.
|
|
if (path.relative(paths.appPath, baseUrlResolved) === '') {
|
|
return null;
|
|
}
|
|
|
|
// Otherwise, throw an error.
|
|
throw new Error(
|
|
chalk.red.bold(
|
|
"Your project's `baseUrl` can only be set to `src` or `node_modules`." +
|
|
' Create React App does not support other values at this time.'
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get webpack aliases based on the baseUrl of a compilerOptions object.
|
|
*
|
|
* @param {*} options
|
|
*/
|
|
function getWebpackAliases(options = {}) {
|
|
const baseUrl = options.baseUrl;
|
|
|
|
if (!baseUrl) {
|
|
return {};
|
|
}
|
|
|
|
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
|
|
|
|
if (path.relative(paths.appPath, baseUrlResolved) === '') {
|
|
return {
|
|
src: paths.appSrc,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get jest aliases based on the baseUrl of a compilerOptions object.
|
|
*
|
|
* @param {*} options
|
|
*/
|
|
function getJestAliases(options = {}) {
|
|
const baseUrl = options.baseUrl;
|
|
|
|
if (!baseUrl) {
|
|
return {};
|
|
}
|
|
|
|
const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
|
|
|
|
if (path.relative(paths.appPath, baseUrlResolved) === '') {
|
|
return {
|
|
'^src/(.*)$': '<rootDir>/src/$1',
|
|
};
|
|
}
|
|
}
|
|
|
|
function getModules() {
|
|
// Check if TypeScript is setup
|
|
const hasTsConfig = fs.existsSync(paths.appTsConfig);
|
|
const hasJsConfig = fs.existsSync(paths.appJsConfig);
|
|
|
|
if (hasTsConfig && hasJsConfig) {
|
|
throw new Error(
|
|
'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'
|
|
);
|
|
}
|
|
|
|
let config;
|
|
|
|
// If there's a tsconfig.json we assume it's a
|
|
// TypeScript project and set up the config
|
|
// based on tsconfig.json
|
|
if (hasTsConfig) {
|
|
const ts = require(resolve.sync('typescript', {
|
|
basedir: paths.appNodeModules,
|
|
}));
|
|
config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
|
|
// Otherwise we'll check if there is jsconfig.json
|
|
// for non TS projects.
|
|
} else if (hasJsConfig) {
|
|
config = require(paths.appJsConfig);
|
|
}
|
|
|
|
config = config || {};
|
|
const options = config.compilerOptions || {};
|
|
|
|
const additionalModulePaths = getAdditionalModulePaths(options);
|
|
|
|
return {
|
|
additionalModulePaths: additionalModulePaths,
|
|
webpackAliases: getWebpackAliases(options),
|
|
jestAliases: getJestAliases(options),
|
|
hasTsConfig,
|
|
};
|
|
}
|
|
|
|
module.exports = getModules();
|