Skip to content

Commit 0c0e981

Browse files
committed
Enable React Refresh for all dependencies
1 parent c4955fb commit 0c0e981

File tree

6 files changed

+179
-144
lines changed

6 files changed

+179
-144
lines changed

packages/app/src/sandbox/compile.ts

Lines changed: 55 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import createCodeSandboxOverlay from './codesandbox-overlay';
2121
import getPreset from './eval';
2222
import { consumeCache, deleteAPICache, saveCache } from './eval/cache';
2323
import { Module } from './eval/entities/module';
24-
import Manager, { Manifest } from './eval/manager';
24+
import Manager from './eval/manager';
2525
import TranspiledModule from './eval/transpiled-module';
2626
import handleExternalResources from './external-resources';
27-
import { loadDependencies } from './npm';
27+
import { loadDependencies, NPMDependencies } from './npm';
2828
import { resetScreen } from './status-screen';
2929
import { showRunOnClick } from './status-screen/run-on-click';
3030

@@ -198,7 +198,11 @@ const PREINSTALLED_DEPENDENCIES = [
198198
...BABEL_DEPENDENCIES,
199199
];
200200

201-
function getDependencies(parsedPackage, templateDefinition, configurations) {
201+
function getDependencies(
202+
parsedPackage,
203+
templateDefinition,
204+
configurations
205+
): NPMDependencies {
202206
const {
203207
dependencies: d = {},
204208
peerDependencies = {},
@@ -305,38 +309,27 @@ function getDependencies(parsedPackage, templateDefinition, configurations) {
305309
return returnedDependencies;
306310
}
307311

308-
async function updateManager(
312+
function initializeManager(
309313
sandboxId: string,
310314
template: TemplateType,
311-
managerModules: { [path: string]: Module },
312-
manifest: Manifest,
315+
modules: { [path: string]: Module },
313316
configurations: ParsedConfigurationFiles,
314-
isNewCombination: boolean,
315-
hasFileResolver: boolean
316-
): Promise<TranspiledModule[]> {
317-
let newManager = false;
318-
if (!manager || manager.id !== sandboxId) {
319-
newManager = true;
320-
manager = new Manager(
321-
sandboxId,
322-
getPreset(template, configurations.package.parsed),
323-
managerModules,
324-
{
325-
hasFileResolver,
326-
}
327-
);
328-
}
329-
330-
if (isNewCombination || newManager) {
331-
manager.setManifest(manifest);
332-
}
333-
334-
if (firstLoad && newManager) {
335-
// We save the state of transpiled modules, and load it here again. Gives
336-
// faster initial loads.
337-
await consumeCache(manager);
338-
}
317+
{ hasFileResolver = false }: { hasFileResolver?: boolean } = {}
318+
) {
319+
return new Manager(
320+
sandboxId,
321+
getPreset(template, configurations.package.parsed),
322+
modules,
323+
{
324+
hasFileResolver,
325+
}
326+
);
327+
}
339328

329+
async function updateManager(
330+
managerModules: { [path: string]: Module },
331+
configurations: ParsedConfigurationFiles
332+
): Promise<TranspiledModule[]> {
340333
manager.updateConfigurations(configurations);
341334
await manager.preset.setup(manager);
342335
return manager.updateData(managerModules).then(x => {
@@ -408,7 +401,6 @@ interface CompileOptions {
408401
skipEval?: boolean;
409402
hasFileResolver?: boolean;
410403
disableDependencyPreprocessing?: boolean;
411-
showFullScreen?: boolean;
412404
}
413405

414406
async function compile({
@@ -423,7 +415,6 @@ async function compile({
423415
skipEval = false,
424416
hasFileResolver = false,
425417
disableDependencyPreprocessing = false,
426-
showFullScreen = false,
427418
}: CompileOptions) {
428419
dispatch({
429420
type: 'start',
@@ -477,12 +468,20 @@ async function compile({
477468

478469
dispatch({ type: 'status', status: 'installing-dependencies' });
479470

480-
const dependencies = getDependencies(
471+
manager =
472+
manager ||
473+
initializeManager(sandboxId, template, modules, configurations, {
474+
hasFileResolver,
475+
});
476+
477+
let dependencies: NPMDependencies = getDependencies(
481478
parsedPackageJSON,
482479
templateDefinition,
483480
configurations
484481
);
485482

483+
dependencies = await manager.preset.processDependencies(dependencies);
484+
486485
const { manifest, isNewCombination } = await loadDependencies(
487486
dependencies,
488487
{
@@ -492,25 +491,34 @@ async function compile({
492491
}
493492
);
494493

495-
if (isNewCombination && !firstLoad) {
494+
const shouldReloadManager =
495+
(isNewCombination && !firstLoad) || manager.id !== sandboxId;
496+
497+
if (shouldReloadManager) {
496498
// Just reset the whole manager if it's a new combination
497-
if (manager) {
498-
manager.dispose();
499-
}
500-
manager = null;
501-
}
502-
const t = Date.now();
499+
manager.dispose();
503500

504-
const updatedModules =
505-
(await updateManager(
501+
manager = initializeManager(
506502
sandboxId,
507503
template,
508504
modules,
509-
manifest,
510505
configurations,
511-
isNewCombination,
512-
hasFileResolver
513-
)) || [];
506+
{ hasFileResolver }
507+
);
508+
}
509+
510+
if (shouldReloadManager || firstLoad) {
511+
// Now initialize the data the manager can only use once dependencies are loaded
512+
513+
manager.setManifest(manifest);
514+
// We save the state of transpiled modules, and load it here again. Gives
515+
// faster initial loads.
516+
await consumeCache(manager);
517+
}
518+
519+
const t = Date.now();
520+
521+
const updatedModules = (await updateManager(modules, configurations)) || [];
514522

515523
const possibleEntries = templateDefinition.getEntries(configurations);
516524

@@ -527,9 +535,6 @@ async function compile({
527535
const main = absolute(foundMain);
528536
managerModuleToTranspile = modules[main];
529537

530-
// TODO: make this a separate lifecycle
531-
// await manager.preset.setup(manager);
532-
533538
dispatch({ type: 'status', status: 'transpiling' });
534539
manager.setStage('transpilation');
535540

packages/app/src/sandbox/eval/presets/create-react-app/utils.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,12 @@ import { getAbsoluteDependencies } from '@codesandbox/common/lib/utils/dependenc
33
import Manager from 'sandbox/eval/manager';
44

55
export async function isMinimalReactVersion(
6-
dependencies: object = {},
7-
devDependencies: object = {},
6+
version: string,
87
minimalVersion: string
98
) {
10-
const allDependencies = { ...dependencies, ...devDependencies };
11-
12-
if (allDependencies['react-dom']) {
9+
if (version) {
1310
const absoluteDependencies = await getAbsoluteDependencies({
14-
'react-dom': allDependencies['react-dom'],
11+
'react-dom': version,
1512
});
1613

1714
return (
@@ -23,14 +20,19 @@ export async function isMinimalReactVersion(
2320
return false;
2421
}
2522

23+
/**
24+
* Decide whether React Refresh hot module reloading strategy is supported by React
25+
*/
2626
export async function hasRefresh(
27-
dependencies: object = {},
28-
devDependencies: object = {}
27+
dependencies: { name: string; version: string }[]
2928
) {
30-
const allDependencies = { ...dependencies, ...devDependencies };
29+
const hasReactRefresh = dependencies.find(n => n.name === 'react-refresh');
30+
if (hasReactRefresh) {
31+
const reactDom = dependencies.find(dep => dep.name === 'react-dom');
3132

32-
if (allDependencies['react-refresh']) {
33-
return isMinimalReactVersion(dependencies, devDependencies, '16.9.0');
33+
if (reactDom) {
34+
return isMinimalReactVersion(reactDom.version, '16.9.0');
35+
}
3436
}
3537

3638
return false;

0 commit comments

Comments
 (0)