Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrapped islands #9941

Draft
wants to merge 30 commits into
base: v2
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions packages/core/core/src/BundleGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
} from '@parcel/types';
import type {
ContentGraphOpts,
ContentKey,
NodeId,
SerializedContentGraph,
} from '@parcel/graph';
Expand Down Expand Up @@ -1385,9 +1386,13 @@ export default class BundleGraph {
getSymbolResolution(
asset: Asset,
symbol: Symbol,
boundary: ?Bundle,
boundaryBundle: ?Bundle,
boundaryAssets: ?Set<ContentKey>,
): InternalSymbolResolution {
let assetOutside = boundary && !this.bundleHasAsset(boundary, asset);
let isAssetOutside = a =>
(boundaryBundle && !this.bundleHasAsset(boundaryBundle, a)) ||
(boundaryAssets && !boundaryAssets.has(a.id));
let assetOutside = isAssetOutside(asset);

let identifier = asset.symbols?.get(symbol)?.local;
if (symbol === '*') {
Expand Down Expand Up @@ -1444,7 +1449,12 @@ export default class BundleGraph {
symbol: resolvedSymbol,
exportSymbol,
loc,
} = this.getSymbolResolution(resolved, depSymbol, boundary);
} = this.getSymbolResolution(
resolved,
depSymbol,
boundaryBundle,
boundaryAssets,
);

if (!loc) {
// Remember how we got there
Expand All @@ -1470,7 +1480,12 @@ export default class BundleGraph {
if (!resolved) {
continue;
}
let result = this.getSymbolResolution(resolved, symbol, boundary);
let result = this.getSymbolResolution(
resolved,
symbol,
boundaryBundle,
boundaryAssets,
);

// We found the symbol
if (result.symbol != undefined) {
Expand All @@ -1494,15 +1509,15 @@ export default class BundleGraph {
}
if (result.symbol === null) {
found = true;
if (boundary && !this.bundleHasAsset(boundary, result.asset)) {
if (isAssetOutside(result.asset)) {
// If the returned asset is outside (and it's the first asset that is outside), return it.
if (!assetOutside) {
return {
potentialResults.push({
asset: result.asset,
symbol: result.symbol,
exportSymbol: result.exportSymbol,
loc: resolved.symbols?.get(symbol)?.loc,
};
});
} else {
// Otherwise the original asset will be returned at the end.
break;
Expand Down
170 changes: 126 additions & 44 deletions packages/core/core/src/PackagerRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
loadPluginConfig,
getConfigHash,
getConfigRequests,
type PluginWithLoadConfig,
type PluginWithLoadConfigGlobalInfo,
} from './requests/ConfigRequest';
import {
createDevDependency,
Expand Down Expand Up @@ -143,12 +143,20 @@ export default class PackagerRunner {
): Promise<PackageRequestResult> {
invalidateDevDeps(invalidDevDeps, this.options, this.config);

let configs = await this.loadConfigs(bundleGraph, bundle);
let {configs, globalInfos} = await this.loadConfigs(bundleGraph, bundle);
let bundleInfo =
(await this.getBundleInfoFromCache(bundleGraph, bundle, configs)) ??
(await this.getBundleInfo(bundle, bundleGraph, configs));

let configRequests = getConfigRequests([...configs.values()]);
(await this.getBundleInfoFromCache(
bundleGraph,
bundle,
configs,
globalInfos,
)) ??
(await this.getBundleInfo(bundle, bundleGraph, configs, globalInfos));

let configRequests = getConfigRequests([
...configs.values(),
...globalInfos.values(),
]);
let devDepRequests = getWorkerDevDepRequests([
...this.devDepRequests.values(),
]);
Expand All @@ -164,86 +172,130 @@ export default class PackagerRunner {
async loadConfigs(
bundleGraph: InternalBundleGraph,
bundle: InternalBundle,
): Promise<Map<string, Config>> {
): Promise<{|
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
|}> {
let configs = new Map();
let globalInfos = new Map();

await this.loadConfig(bundle, configs);
await this.loadConfig(bundleGraph, bundle, configs, globalInfos);
for (let inlineBundle of bundleGraph.getInlineBundles(bundle)) {
await this.loadConfig(inlineBundle, configs);
await this.loadConfig(bundleGraph, inlineBundle, configs, globalInfos);
}

return configs;
return {configs, globalInfos};
}

async loadConfig(
bundleGraph: InternalBundleGraph,
bundle: InternalBundle,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Promise<void> {
let name = nullthrows(bundle.name);
let plugin = await this.config.getPackager(name);
await this.loadPluginConfig(plugin, configs);
await this.loadPluginConfig(
bundleGraph,
bundle,
plugin,
configs,
globalInfos,
);

let optimizers = await this.config.getOptimizers(name, bundle.pipeline);

for (let optimizer of optimizers) {
await this.loadPluginConfig(optimizer, configs);
await this.loadPluginConfig(
bundleGraph,
bundle,
optimizer,
configs,
globalInfos,
);
}
}

async loadPluginConfig<T: PluginWithLoadConfig>(
async loadPluginConfig<T: PluginWithLoadConfigGlobalInfo>(
bundleGraph: InternalBundleGraph,
bundle: InternalBundle,
plugin: LoadedPlugin<T>,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Promise<void> {
if (configs.has(plugin.name)) {
return;
}
if (!configs.has(plugin.name)) {
// Only load config for a plugin once per build.
let existing = pluginConfigs.get(plugin.name);
if (existing != null) {
configs.set(plugin.name, existing);
} else {
if (plugin.plugin.loadConfig != null) {
let config = createConfig({
plugin: plugin.name,
searchPath: toProjectPathUnsafe('index'),
});

await loadPluginConfig(plugin, config, this.options);

for (let devDep of config.devDeps) {
let devDepRequest = await createDevDependency(
devDep,
this.previousDevDeps,
this.options,
);
let key = `${devDep.specifier}:${fromProjectPath(
this.options.projectRoot,
devDep.resolveFrom,
)}`;
this.devDepRequests.set(key, devDepRequest);
}

// Only load config for a plugin once per build.
let existing = pluginConfigs.get(plugin.name);
if (existing != null) {
configs.set(plugin.name, existing);
return;
pluginConfigs.set(plugin.name, config);
configs.set(plugin.name, config);
}
}
}

if (plugin.plugin.loadConfig != null) {
let loadGlobalInfo = plugin.plugin.loadGlobalInfo;
if (!globalInfos.has(plugin.name) && loadGlobalInfo != null) {
let config = createConfig({
plugin: plugin.name,
searchPath: toProjectPathUnsafe('index'),
});

await loadPluginConfig(plugin, config, this.options);

for (let devDep of config.devDeps) {
let devDepRequest = await createDevDependency(
devDep,
this.previousDevDeps,
config.result = await loadGlobalInfo({
bundle: NamedBundle.get(bundle, bundleGraph, this.options),
bundleGraph: new BundleGraph<NamedBundleType>(
bundleGraph,
NamedBundle.get.bind(NamedBundle),
this.options,
);
let key = `${devDep.specifier}:${fromProjectPath(
this.options.projectRoot,
devDep.resolveFrom,
)}`;
this.devDepRequests.set(key, devDepRequest);
}

pluginConfigs.set(plugin.name, config);
configs.set(plugin.name, config);
),
options: new PluginOptions(this.options),
logger: new PluginLogger({origin: plugin.name}),
});
// TODO expose config and let plugin set key?
config.cacheKey = hashString(JSON.stringify(config.result) ?? '');
globalInfos.set(plugin.name, config);
}
}

async getBundleInfoFromCache(
bundleGraph: InternalBundleGraph,
bundle: InternalBundle,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Async<?BundleInfo> {
if (this.options.shouldDisableCache) {
return;
}

if (bundle.name === process.env.PARCEL_FORCE_PACKAGE) {
return;
}

let cacheKey = await this.getCacheKey(
bundle,
bundleGraph,
configs,
globalInfos,
this.previousInvalidations,
);
let infoKey = PackagerRunner.getInfoKey(cacheKey);
Expand All @@ -254,17 +306,23 @@ export default class PackagerRunner {
bundle: InternalBundle,
bundleGraph: InternalBundleGraph,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Promise<BundleInfo> {
let {type, contents, map} = await this.getBundleResult(
bundle,
bundleGraph,
configs,
globalInfos,
);

// Recompute cache keys as they may have changed due to dev dependencies.
let cacheKey = await this.getCacheKey(bundle, bundleGraph, configs, [
...this.invalidations.values(),
]);
let cacheKey = await this.getCacheKey(
bundle,
bundleGraph,
configs,
globalInfos,
[...this.invalidations.values()],
);
let cacheKeys = {
content: PackagerRunner.getContentKey(cacheKey),
map: PackagerRunner.getMapKey(cacheKey),
Expand All @@ -278,12 +336,18 @@ export default class PackagerRunner {
bundle: InternalBundle,
bundleGraph: InternalBundleGraph,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Promise<{|
type: string,
contents: Blob,
map: ?string,
|}> {
let packaged = await this.package(bundle, bundleGraph, configs);
let packaged = await this.package(
bundle,
bundleGraph,
configs,
globalInfos,
);
let type = packaged.type ?? bundle.type;
let res = await this.optimize(
bundle,
Expand All @@ -292,6 +356,7 @@ export default class PackagerRunner {
packaged.contents,
packaged.map,
configs,
globalInfos,
);

let map =
Expand Down Expand Up @@ -319,6 +384,7 @@ export default class PackagerRunner {
internalBundle: InternalBundle,
bundleGraph: InternalBundleGraph,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Promise<BundleResult> {
let bundle = NamedBundle.get(internalBundle, bundleGraph, this.options);
this.report({
Expand All @@ -332,6 +398,7 @@ export default class PackagerRunner {
try {
return await plugin.package({
config: configs.get(name)?.result,
globalInfo: globalInfos.get(name)?.result,
bundle,
bundleGraph: new BundleGraph<NamedBundleType>(
bundleGraph,
Expand All @@ -358,6 +425,7 @@ export default class PackagerRunner {
// $FlowFixMe
bundleGraphToInternalBundleGraph(bundleGraph),
configs,
globalInfos,
);

return {contents: res.contents};
Expand Down Expand Up @@ -395,6 +463,7 @@ export default class PackagerRunner {
contents: Blob,
map?: ?SourceMap,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
): Promise<BundleResult> {
let bundle = NamedBundle.get(
internalBundle,
Expand Down Expand Up @@ -430,6 +499,7 @@ export default class PackagerRunner {
try {
let next = await optimizer.plugin.optimize({
config: configs.get(optimizer.name)?.result,
globalInfo: globalInfos.get(optimizer.name)?.result,
bundle,
bundleGraph,
contents: optimized.contents,
Expand Down Expand Up @@ -535,6 +605,7 @@ export default class PackagerRunner {
bundle: InternalBundle,
bundleGraph: InternalBundleGraph,
configs: Map<string, Config>,
globalInfos: Map<string, Config>,
invalidations: Array<RequestInvalidation>,
): Promise<string> {
let configResults = {};
Expand All @@ -547,6 +618,16 @@ export default class PackagerRunner {
);
}
}
let globalInfoResults = {};
for (let [pluginName, config] of globalInfos) {
if (config) {
globalInfoResults[pluginName] = await getConfigHash(
config,
pluginName,
this.options,
);
}
}

let devDepHashes = await this.getDevDepHashes(bundle);
for (let inlineBundle of bundleGraph.getInlineBundles(bundle)) {
Expand All @@ -565,6 +646,7 @@ export default class PackagerRunner {
bundle.target.publicUrl +
bundleGraph.getHash(bundle) +
JSON.stringify(configResults) +
JSON.stringify(globalInfoResults) +
this.options.mode,
);
}
Expand Down
Loading