Skip to content

Commit 38ff9b4

Browse files
authored
Put new packager full on (codesandbox#261)
* Put new packager full on * Add some documentation * Cache resolver paths
1 parent ca4e7dd commit 38ff9b4

File tree

8 files changed

+147
-300
lines changed

8 files changed

+147
-300
lines changed

src/app/components/sandbox/Preview/index.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,6 @@ export default class Preview extends React.PureComponent<Props, State> {
264264
template,
265265
hasActions: !!runActionFromPreview,
266266
isModuleView: !isInProjectView,
267-
// TODO remove this in 2 weeks
268-
experimentalPackager: preferences.newPackagerExperiment,
269267
});
270268
}
271269
};

src/app/containers/Preferences/Experiments/Preferences.js

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import preferencesActionCreators from 'app/store/preferences/actions';
88
import {
99
Container,
1010
PreferenceContainer,
11-
PaddedPreference,
11+
// PaddedPreference,
1212
Description,
1313
} from '../styles';
1414

@@ -23,25 +23,22 @@ const mapDispatchToProps = dispatch => ({
2323
const mapStateToProps = state => ({
2424
preferences: preferencesSelector(state),
2525
});
26+
// eslint-disable-next-line no-unused-vars arrow-body-style
2627
const Preferences = ({ preferences, preferencesActions }: Props) => {
27-
const bindValue = name => ({
28-
value: preferences[name],
29-
setValue: value =>
30-
preferencesActions.setPreference({
31-
[name]: value,
32-
}),
33-
});
28+
// const bindValue = name => ({
29+
// value: preferences[name],
30+
// setValue: value =>
31+
// preferencesActions.setPreference({
32+
// [name]: value,
33+
// }),
34+
// });
35+
3436
return (
3537
<Container>
3638
<PreferenceContainer>
37-
<PaddedPreference
38-
title="New dependency bundler"
39-
type="boolean"
40-
{...bindValue('newPackagerExperiment')}
41-
/>
4239
<Description>
43-
Use the new, faster, client side dependency bundler. Reload the
44-
browser for changes to take effect.
40+
We have no experiments running currently! Tune in later to find some
41+
new goodies to test.
4542
</Description>
4643
</PreferenceContainer>
4744
</Container>

src/sandbox/compile.js

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import _debug from 'app/utils/debug';
77
import initializeErrorTransformers from './errors/transformers';
88
import getPreset from './eval';
99
import Manager from './eval/manager';
10-
import resolveDependency from './eval/loaders/dependency-resolver';
1110

1211
import { resetScreen } from './status-screen';
1312

@@ -53,16 +52,9 @@ function getIndexHtml(modules) {
5352
return '<div id="root"></div>';
5453
}
5554

56-
async function updateManager(
57-
sandboxId,
58-
template,
59-
managerModules,
60-
experimentalPackager = false
61-
) {
55+
async function updateManager(sandboxId, template, managerModules) {
6256
if (!manager || manager.id !== sandboxId) {
63-
manager = new Manager(sandboxId, managerModules, getPreset(template), {
64-
experimentalPackager,
65-
});
57+
manager = new Manager(sandboxId, managerModules, getPreset(template));
6658
} else {
6759
await manager.updateData(managerModules);
6860
}
@@ -95,7 +87,6 @@ async function compile({
9587
hasActions,
9688
isModuleView = false,
9789
template,
98-
experimentalPackager = false,
9990
}) {
10091
try {
10192
clearErrorTransformers();
@@ -116,21 +107,18 @@ async function compile({
116107
}));
117108

118109
const [{ manifest, isNewCombination }] = await Promise.all([
119-
loadDependencies(dependencies, experimentalPackager),
120-
updateManager(sandboxId, template, managerModules, experimentalPackager),
110+
loadDependencies(dependencies),
111+
updateManager(sandboxId, template, managerModules),
121112
]);
122113

123-
const { externals = {} } = manifest || {};
124-
if (experimentalPackager) {
125-
manager.setManifest(manifest);
126-
} else {
127-
manager.setExternals(externals);
128-
}
129-
114+
// Just reset the whole packager if it's a new combination
130115
if (isNewCombination) {
131-
manager.clearCompiledCache();
116+
manager = null;
117+
await updateManager(sandboxId, template, managerModules);
132118
}
133119

120+
manager.setManifest(manifest);
121+
134122
const managerModulePathToTranspile = getModulePath(
135123
modules,
136124
directories,
@@ -149,9 +137,12 @@ async function compile({
149137
try {
150138
const children = document.body.children;
151139
// Do unmounting for react
152-
if (externals['react-dom']) {
153-
const reactDOM = resolveDependency('react-dom', externals);
140+
if (manifest.dependencies.find(n => n.name === 'react-dom')) {
141+
const reactDOMModule = manager.resolveModule('react-dom', '');
142+
const reactDOM = manager.evaluateModule(reactDOMModule);
143+
154144
reactDOM.unmountComponentAtNode(document.body);
145+
155146
for (let i = 0; i < children.length; i += 1) {
156147
if (children[i].tagName === 'DIV') {
157148
reactDOM.unmountComponentAtNode(children[i]);

src/sandbox/eval/manager.js

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -57,29 +57,33 @@ export default class Manager {
5757
modules: ModuleObject;
5858

5959
manifest: Manifest;
60-
experimentalPackager: boolean;
6160

62-
constructor(
63-
id: string,
64-
modules: Array<Module>,
65-
preset: Preset,
66-
options: Object = {}
67-
) {
61+
constructor(id: string, modules: Array<Module>, preset: Preset) {
6862
this.id = id;
6963
this.preset = preset;
7064
this.transpiledModules = {};
65+
this.cachedPaths = {};
7166
modules.forEach(m => this.addModule(m));
7267

73-
this.experimentalPackager = options.experimentalPackager || false;
74-
7568
if (process.env.NODE_ENV === 'development') {
7669
console.log(this);
7770
}
7871
}
7972

80-
setExternals(externals: Externals) {
81-
this.externals = externals;
82-
}
73+
// Hoist these 2 functions to the top, since they get executed A LOT
74+
isFile = (p: string) =>
75+
!!this.transpiledModules[p] || !!getCombinedMetas()[p];
76+
77+
readFileSync = (p: string) => {
78+
if (this.transpiledModules[p]) {
79+
return this.transpiledModules[p].module.code;
80+
}
81+
82+
const err = new Error('Could not find ' + p);
83+
err.code = 'ENOENT';
84+
85+
throw err;
86+
};
8387

8488
setManifest(manifest: ?Manifest) {
8589
this.manifest = manifest || {
@@ -194,6 +198,7 @@ export default class Manager {
194198
* @param {*} entry
195199
*/
196200
transpileModules(entry: Module) {
201+
this.cachedPaths = {};
197202
const transpiledModule = this.getTranspiledModule(entry);
198203

199204
transpiledModule.setIsEntry(true);
@@ -208,6 +213,20 @@ export default class Manager {
208213
return values(this.transpiledModules).map(t => t.module);
209214
}
210215

216+
/**
217+
* The packager returns a list of dependencies that require a different path
218+
* of their subdependencies.
219+
*
220+
* An example:
221+
* if react requires lodash v3, and react-dom requires lodash v4. We add them
222+
* both to the bundle, and rewrite paths for lodash v3 to `lodash/3.0.0/`. Then
223+
* we specify that when react resolves `lodash` it should resolve `lodash/3.0.0`.
224+
*
225+
* @param {string} path
226+
* @param {string} currentPath
227+
* @returns
228+
* @memberof Manager
229+
*/
211230
getAliasedDependencyPath(path: string, currentPath: string) {
212231
const isDependency = /^(\w|@\w)/.test(path);
213232

@@ -237,29 +256,37 @@ export default class Manager {
237256
return path;
238257
}
239258

259+
// All paths are resolved at least twice: during transpilation and evaluation.
260+
// We can improve performance by almost 2x in this scenario if we cache the lookups
261+
cachedPaths: {
262+
[path: string]: string,
263+
} = {};
264+
240265
resolveModule(
241266
path: string,
242267
currentPath: string,
243268
defaultExtensions: Array<string> = ['js', 'jsx', 'json']
244269
): Module {
245270
const aliasedPath = this.getAliasedDependencyPath(path, currentPath);
246271
const shimmedPath = coreLibraries[aliasedPath] || aliasedPath;
272+
273+
const pathId = path + currentPath;
274+
const cachedPath = this.cachedPaths[pathId];
247275
try {
248-
const resolvedPath = resolve.sync(shimmedPath, {
249-
filename: currentPath,
250-
extensions: defaultExtensions.map(ext => '.' + ext),
251-
isFile: p => !!this.transpiledModules[p] || !!getCombinedMetas()[p],
252-
readFileSync: p => {
253-
if (this.transpiledModules[p]) {
254-
return this.transpiledModules[p].module.code;
255-
}
256-
257-
const err = new Error('Could not find ' + p);
258-
err.code = 'ENOENT';
259-
260-
throw err;
261-
},
262-
});
276+
let resolvedPath;
277+
278+
if (cachedPath) {
279+
resolvedPath = cachedPath;
280+
} else {
281+
resolvedPath = resolve.sync(shimmedPath, {
282+
filename: currentPath,
283+
extensions: defaultExtensions.map(ext => '.' + ext),
284+
isFile: this.isFile,
285+
readFileSync: this.readFileSync,
286+
});
287+
288+
this.cachedPaths[pathId] = resolvedPath;
289+
}
263290

264291
if (NODE_LIBS.includes(resolvedPath)) {
265292
return {

src/sandbox/eval/transpiled-module.js

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,6 @@ export default class TranspiledModule {
237237
// that include the source of another file by themselves, we need to
238238
// force transpilation to rebuild the file
239239
addTranspilationDependency: (depPath: string, options) => {
240-
if (
241-
/^(\w|@\w)/.test(depPath) &&
242-
!depPath.includes('!') &&
243-
!manager.experimentalPackager
244-
) {
245-
return;
246-
}
247-
248240
const tModule = manager.resolveTranspiledModule(
249241
depPath,
250242
options && options.isAbsolute ? '/' : this.module.path
@@ -257,9 +249,6 @@ export default class TranspiledModule {
257249
},
258250
addDependency: (depPath: string, options) => {
259251
if (
260-
(/^(\w|@\w)/.test(depPath) &&
261-
!depPath.includes('!') &&
262-
!manager.experimentalPackager) ||
263252
depPath.startsWith('babel-runtime') ||
264253
depPath.startsWith('codesandbox-api')
265254
) {
@@ -288,14 +277,6 @@ export default class TranspiledModule {
288277
}
289278
},
290279
addDependenciesInDirectory: (folderPath: string, options) => {
291-
if (
292-
/^(\w|@\w)/.test(folderPath) &&
293-
!folderPath.includes('!') &&
294-
!manager.experimentalPackager
295-
) {
296-
return;
297-
}
298-
299280
const tModules = manager.resolveTranspiledModulesInDirectory(
300281
folderPath,
301282
options && options.isAbsolute ? '/' : this.module.path
@@ -472,17 +453,10 @@ export default class TranspiledModule {
472453
if (/^(\w|@\w)/.test(aliasedPath) && !aliasedPath.includes('!')) {
473454
// So it must be a dependency
474455
if (
475-
!manager.experimentalPackager ||
476456
aliasedPath.startsWith('babel-runtime') ||
477457
aliasedPath.startsWith('codesandbox-api')
478458
)
479-
// TODO remove this hack for not-experimental packager
480-
return resolveDependency(
481-
path === 'vue' && !manager.experimentalPackager
482-
? path
483-
: aliasedPath,
484-
manager.externals
485-
);
459+
return resolveDependency(aliasedPath, manager.externals);
486460
}
487461

488462
const requiredTranspiledModule = manager.resolveTranspiledModule(

0 commit comments

Comments
 (0)