@atlaspack/packager-js 2.12.1-dev.3401 → 2.12.1-dev.3450
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ScopeHoistingPackager.js +39 -9
- package/lib/index.js +12 -4
- package/package.json +10 -9
- package/src/ScopeHoistingPackager.js +137 -83
- package/src/index.js +12 -0
|
@@ -53,6 +53,13 @@ function _path() {
|
|
|
53
53
|
};
|
|
54
54
|
return data;
|
|
55
55
|
}
|
|
56
|
+
function _featureFlags() {
|
|
57
|
+
const data = require("@atlaspack/feature-flags");
|
|
58
|
+
_featureFlags = function () {
|
|
59
|
+
return data;
|
|
60
|
+
};
|
|
61
|
+
return data;
|
|
62
|
+
}
|
|
56
63
|
var _ESMOutputFormat = require("./ESMOutputFormat");
|
|
57
64
|
var _CJSOutputFormat = require("./CJSOutputFormat");
|
|
58
65
|
var _GlobalOutputFormat = require("./GlobalOutputFormat");
|
|
@@ -63,7 +70,10 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
63
70
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
64
71
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
65
72
|
// and count the number of newlines in the file for source maps.
|
|
66
|
-
|
|
73
|
+
//
|
|
74
|
+
// For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
|
|
75
|
+
const REPLACEMENT_RE_CONDITIONAL = /\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require|importCond)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
76
|
+
const REPLACEMENT_RE = /\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
67
77
|
const BUILTINS = Object.keys(_globals().default.builtin);
|
|
68
78
|
const GLOBALS_BY_CONTEXT = {
|
|
69
79
|
browser: new Set([...BUILTINS, ...Object.keys(_globals().default.browser)]),
|
|
@@ -89,12 +99,15 @@ class ScopeHoistingPackager {
|
|
|
89
99
|
needsPrelude = false;
|
|
90
100
|
usedHelpers = new Set();
|
|
91
101
|
externalAssets = new Set();
|
|
92
|
-
|
|
102
|
+
forceSkipWrapAssets = [];
|
|
103
|
+
constructor(options, bundleGraph, bundle, parcelRequireName, useAsyncBundleRuntime, forceSkipWrapAssets, logger) {
|
|
93
104
|
this.options = options;
|
|
94
105
|
this.bundleGraph = bundleGraph;
|
|
95
106
|
this.bundle = bundle;
|
|
96
107
|
this.parcelRequireName = parcelRequireName;
|
|
97
108
|
this.useAsyncBundleRuntime = useAsyncBundleRuntime;
|
|
109
|
+
this.forceSkipWrapAssets = forceSkipWrapAssets ?? [];
|
|
110
|
+
this.logger = logger;
|
|
98
111
|
let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
|
|
99
112
|
this.outputFormat = new OutputFormat(this);
|
|
100
113
|
this.isAsyncBundle = this.bundleGraph.hasParentBundleOfType(this.bundle, 'js') && !this.bundle.env.isIsolated() && this.bundle.bundleBehavior !== 'isolated';
|
|
@@ -257,6 +270,18 @@ class ScopeHoistingPackager {
|
|
|
257
270
|
actions.skipChildren();
|
|
258
271
|
return;
|
|
259
272
|
}
|
|
273
|
+
// This prevents children of a wrapped asset also being wrapped - it's an "unsafe" optimisation
|
|
274
|
+
// that should only be used when you know (or think you know) what you're doing.
|
|
275
|
+
//
|
|
276
|
+
// In particular this can force an async bundle to be scope hoisted where it previously would not be
|
|
277
|
+
// due to the entry asset being wrapped.
|
|
278
|
+
if (this.forceSkipWrapAssets.length > 0 && this.forceSkipWrapAssets.some(p => p === _path().default.relative(this.options.projectRoot, asset.filePath))) {
|
|
279
|
+
this.logger.verbose({
|
|
280
|
+
message: `Force skipping wrapping of ${_path().default.relative(this.options.projectRoot, asset.filePath)}`
|
|
281
|
+
});
|
|
282
|
+
actions.skipChildren();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
260
285
|
if (!asset.meta.isConstantModule) {
|
|
261
286
|
this.wrappedAssets.add(asset.id);
|
|
262
287
|
wrapped.push(asset);
|
|
@@ -412,7 +437,7 @@ class ScopeHoistingPackager {
|
|
|
412
437
|
// in a single regex so that we only do one pass over the whole code.
|
|
413
438
|
let offset = 0;
|
|
414
439
|
let columnStartIndex = 0;
|
|
415
|
-
code = code.replace(REPLACEMENT_RE, (m, d, i) => {
|
|
440
|
+
code = code.replace((0, _featureFlags().getFeatureFlag)('conditionalBundlingApi') ? REPLACEMENT_RE_CONDITIONAL : REPLACEMENT_RE, (m, d, i) => {
|
|
416
441
|
if (m === '\n') {
|
|
417
442
|
columnStartIndex = i + offset + 1;
|
|
418
443
|
lineCount++;
|
|
@@ -559,7 +584,7 @@ ${code}
|
|
|
559
584
|
// Async dependencies need a namespace object even if all used symbols were statically analyzed.
|
|
560
585
|
// This is recorded in the promiseSymbol meta property set by the transformer rather than in
|
|
561
586
|
// symbols so that we don't mark all symbols as used.
|
|
562
|
-
if (dep.priority === 'lazy' && dep.meta.promiseSymbol) {
|
|
587
|
+
if ((dep.priority === 'lazy' || dep.priority === 'conditional') && dep.meta.promiseSymbol) {
|
|
563
588
|
let promiseSymbol = dep.meta.promiseSymbol;
|
|
564
589
|
(0, _assert().default)(typeof promiseSymbol === 'string');
|
|
565
590
|
let symbol = this.getSymbolResolution(asset, resolved, '*', dep);
|
|
@@ -993,7 +1018,9 @@ ${code}
|
|
|
993
1018
|
// Add the prelude if this is potentially the first JS bundle to load in a
|
|
994
1019
|
// particular context (e.g. entry scripts in HTML, workers, etc.).
|
|
995
1020
|
let parentBundles = this.bundleGraph.getParentBundles(this.bundle);
|
|
996
|
-
let mightBeFirstJS = parentBundles.length === 0 || parentBundles.some(b => b.type !== 'js') || this.bundleGraph.getBundleGroupsContainingBundle(this.bundle).some(g => this.bundleGraph.isEntryBundleGroup(g)) || this.bundle.env.isIsolated() || this.bundle.bundleBehavior === 'isolated'
|
|
1021
|
+
let mightBeFirstJS = parentBundles.length === 0 || parentBundles.some(b => b.type !== 'js') || this.bundleGraph.getBundleGroupsContainingBundle(this.bundle).some(g => this.bundleGraph.isEntryBundleGroup(g)) || this.bundle.env.isIsolated() || this.bundle.bundleBehavior === 'isolated' ||
|
|
1022
|
+
// Conditional deps may be loaded before entrypoints on the server
|
|
1023
|
+
this.hasConditionalDependency();
|
|
997
1024
|
if (mightBeFirstJS) {
|
|
998
1025
|
let preludeCode = (0, _helpers.prelude)(this.parcelRequireName);
|
|
999
1026
|
res += preludeCode;
|
|
@@ -1036,10 +1063,7 @@ ${code}
|
|
|
1036
1063
|
}
|
|
1037
1064
|
needsDefaultInterop(asset) {
|
|
1038
1065
|
if (asset.symbols.hasExportSymbol('*') && !asset.symbols.hasExportSymbol('default')) {
|
|
1039
|
-
|
|
1040
|
-
return deps.some(dep => this.bundle.hasDependency(dep) &&
|
|
1041
|
-
// dep.meta.isES6Module &&
|
|
1042
|
-
dep.symbols.hasExportSymbol('default'));
|
|
1066
|
+
return true;
|
|
1043
1067
|
}
|
|
1044
1068
|
return false;
|
|
1045
1069
|
}
|
|
@@ -1055,5 +1079,11 @@ ${code}
|
|
|
1055
1079
|
buildFunctionExpression(args, expr) {
|
|
1056
1080
|
return this.bundle.env.supports('arrow-functions', true) ? `(${args.join(', ')}) => ${expr}` : `function (${args.join(', ')}) { return ${expr}; }`;
|
|
1057
1081
|
}
|
|
1082
|
+
hasConditionalDependency() {
|
|
1083
|
+
if (!(0, _featureFlags().getFeatureFlag)('conditionalBundlingApi')) {
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1086
|
+
return this.bundle.getEntryAssets().some(entry => this.bundleGraph.getIncomingDependencies(entry).some(dep => dep.priority === 'conditional'));
|
|
1087
|
+
}
|
|
1058
1088
|
}
|
|
1059
1089
|
exports.ScopeHoistingPackager = ScopeHoistingPackager;
|
package/lib/index.js
CHANGED
|
@@ -47,6 +47,12 @@ const CONFIG_SCHEMA = {
|
|
|
47
47
|
properties: {
|
|
48
48
|
unstable_asyncBundleRuntime: {
|
|
49
49
|
type: 'boolean'
|
|
50
|
+
},
|
|
51
|
+
unstable_forceSkipWrapAssets: {
|
|
52
|
+
type: 'array',
|
|
53
|
+
items: {
|
|
54
|
+
type: 'string'
|
|
55
|
+
}
|
|
50
56
|
}
|
|
51
57
|
},
|
|
52
58
|
additionalProperties: false
|
|
@@ -56,7 +62,7 @@ var _default = exports.default = new (_plugin().Packager)({
|
|
|
56
62
|
config,
|
|
57
63
|
options
|
|
58
64
|
}) {
|
|
59
|
-
var _packageName$contents, _conf$contents;
|
|
65
|
+
var _packageName$contents, _conf$contents, _conf$contents2;
|
|
60
66
|
let packageKey = '@atlaspack/packager-js';
|
|
61
67
|
let conf = await config.getConfigFrom(options.projectRoot + '/index', [], {
|
|
62
68
|
packageKey
|
|
@@ -78,7 +84,8 @@ var _default = exports.default = new (_plugin().Packager)({
|
|
|
78
84
|
let name = (packageName === null || packageName === void 0 || (_packageName$contents = packageName.contents) === null || _packageName$contents === void 0 ? void 0 : _packageName$contents.name) ?? '';
|
|
79
85
|
return {
|
|
80
86
|
parcelRequireName: 'parcelRequire' + (0, _rust().hashString)(name).slice(-4),
|
|
81
|
-
unstable_asyncBundleRuntime: Boolean(conf === null || conf === void 0 || (_conf$contents = conf.contents) === null || _conf$contents === void 0 ? void 0 : _conf$contents.unstable_asyncBundleRuntime)
|
|
87
|
+
unstable_asyncBundleRuntime: Boolean(conf === null || conf === void 0 || (_conf$contents = conf.contents) === null || _conf$contents === void 0 ? void 0 : _conf$contents.unstable_asyncBundleRuntime),
|
|
88
|
+
unstable_forceSkipWrapAssets: (conf === null || conf === void 0 || (_conf$contents2 = conf.contents) === null || _conf$contents2 === void 0 ? void 0 : _conf$contents2.unstable_forceSkipWrapAssets) ?? []
|
|
82
89
|
};
|
|
83
90
|
},
|
|
84
91
|
async package({
|
|
@@ -87,7 +94,8 @@ var _default = exports.default = new (_plugin().Packager)({
|
|
|
87
94
|
getInlineBundleContents,
|
|
88
95
|
getSourceMapReference,
|
|
89
96
|
config,
|
|
90
|
-
options
|
|
97
|
+
options,
|
|
98
|
+
logger
|
|
91
99
|
}) {
|
|
92
100
|
// If this is a non-module script, and there is only one asset with no dependencies,
|
|
93
101
|
// then we don't need to package at all and can pass through the original code un-wrapped.
|
|
@@ -100,7 +108,7 @@ var _default = exports.default = new (_plugin().Packager)({
|
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
110
|
if (contents == null) {
|
|
103
|
-
let packager = bundle.env.shouldScopeHoist ? new _ScopeHoistingPackager.ScopeHoistingPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName, (0, _nullthrows().default)(config).unstable_asyncBundleRuntime) : new _DevPackager.DevPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName);
|
|
111
|
+
let packager = bundle.env.shouldScopeHoist ? new _ScopeHoistingPackager.ScopeHoistingPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName, (0, _nullthrows().default)(config).unstable_asyncBundleRuntime, (0, _nullthrows().default)(config).unstable_forceSkipWrapAssets, logger) : new _DevPackager.DevPackager(options, bundleGraph, bundle, (0, _nullthrows().default)(config).parcelRequireName);
|
|
104
112
|
({
|
|
105
113
|
contents,
|
|
106
114
|
map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaspack/packager-js",
|
|
3
|
-
"version": "2.12.1-dev.
|
|
4
|
-
"license": "MIT",
|
|
3
|
+
"version": "2.12.1-dev.3450+58845ef87",
|
|
4
|
+
"license": "(MIT OR Apache-2.0)",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -13,17 +13,18 @@
|
|
|
13
13
|
"source": "src/index.js",
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">= 16.0.0",
|
|
16
|
-
"parcel": "^2.12.1-dev.
|
|
16
|
+
"parcel": "^2.12.1-dev.3450+58845ef87"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@atlaspack/diagnostic": "2.12.1-dev.
|
|
20
|
-
"@atlaspack/
|
|
21
|
-
"@atlaspack/
|
|
22
|
-
"@atlaspack/
|
|
23
|
-
"@atlaspack/
|
|
19
|
+
"@atlaspack/diagnostic": "2.12.1-dev.3450+58845ef87",
|
|
20
|
+
"@atlaspack/feature-flags": "2.12.1-dev.3450+58845ef87",
|
|
21
|
+
"@atlaspack/plugin": "2.12.1-dev.3450+58845ef87",
|
|
22
|
+
"@atlaspack/rust": "2.12.1-dev.3450+58845ef87",
|
|
23
|
+
"@atlaspack/types": "2.12.1-dev.3450+58845ef87",
|
|
24
|
+
"@atlaspack/utils": "2.12.1-dev.3450+58845ef87",
|
|
24
25
|
"@parcel/source-map": "^2.1.1",
|
|
25
26
|
"globals": "^13.2.0",
|
|
26
27
|
"nullthrows": "^1.1.1"
|
|
27
28
|
},
|
|
28
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "58845ef87446fcedb7d7d8876440c64184645cbb"
|
|
29
30
|
}
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
Dependency,
|
|
7
7
|
PluginOptions,
|
|
8
8
|
NamedBundle,
|
|
9
|
+
PluginLogger,
|
|
9
10
|
} from '@atlaspack/types';
|
|
10
11
|
|
|
11
12
|
import {
|
|
@@ -23,6 +24,7 @@ import ThrowableDiagnostic, {
|
|
|
23
24
|
} from '@atlaspack/diagnostic';
|
|
24
25
|
import globals from 'globals';
|
|
25
26
|
import path from 'path';
|
|
27
|
+
import {getFeatureFlag} from '@atlaspack/feature-flags';
|
|
26
28
|
|
|
27
29
|
import {ESMOutputFormat} from './ESMOutputFormat';
|
|
28
30
|
import {CJSOutputFormat} from './CJSOutputFormat';
|
|
@@ -34,10 +36,15 @@ import {
|
|
|
34
36
|
isValidIdentifier,
|
|
35
37
|
makeValidIdentifier,
|
|
36
38
|
} from './utils';
|
|
39
|
+
|
|
37
40
|
// General regex used to replace imports with the resolved code, references with resolutions,
|
|
38
41
|
// and count the number of newlines in the file for source maps.
|
|
42
|
+
//
|
|
43
|
+
// For conditional bundling the only difference in this regex is adding `importCond` where we have `importAsync` etc..
|
|
44
|
+
const REPLACEMENT_RE_CONDITIONAL =
|
|
45
|
+
/\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require|importCond)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
39
46
|
const REPLACEMENT_RE =
|
|
40
|
-
/\n|import\s+"([0-9a-f]{16}:.+?)";|(?:\$[0-9a-f]{16}\$exports)|(?:\$[0-9a-f]{16}\$(?:import|importAsync|require)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
47
|
+
/\n|import\s+"([0-9a-f]{16,20}:.+?)";|(?:\$[0-9a-f]{16,20}\$exports)|(?:\$[0-9a-f]{16,20}\$(?:import|importAsync|require)\$[0-9a-f]+(?:\$[0-9a-f]+)?)/g;
|
|
41
48
|
|
|
42
49
|
const BUILTINS = Object.keys(globals.builtin);
|
|
43
50
|
const GLOBALS_BY_CONTEXT = {
|
|
@@ -95,6 +102,8 @@ export class ScopeHoistingPackager {
|
|
|
95
102
|
needsPrelude: boolean = false;
|
|
96
103
|
usedHelpers: Set<string> = new Set();
|
|
97
104
|
externalAssets: Set<Asset> = new Set();
|
|
105
|
+
forceSkipWrapAssets: Array<string> = [];
|
|
106
|
+
logger: PluginLogger;
|
|
98
107
|
|
|
99
108
|
constructor(
|
|
100
109
|
options: PluginOptions,
|
|
@@ -102,12 +111,16 @@ export class ScopeHoistingPackager {
|
|
|
102
111
|
bundle: NamedBundle,
|
|
103
112
|
parcelRequireName: string,
|
|
104
113
|
useAsyncBundleRuntime: boolean,
|
|
114
|
+
forceSkipWrapAssets: Array<string>,
|
|
115
|
+
logger: PluginLogger,
|
|
105
116
|
) {
|
|
106
117
|
this.options = options;
|
|
107
118
|
this.bundleGraph = bundleGraph;
|
|
108
119
|
this.bundle = bundle;
|
|
109
120
|
this.parcelRequireName = parcelRequireName;
|
|
110
121
|
this.useAsyncBundleRuntime = useAsyncBundleRuntime;
|
|
122
|
+
this.forceSkipWrapAssets = forceSkipWrapAssets ?? [];
|
|
123
|
+
this.logger = logger;
|
|
111
124
|
|
|
112
125
|
let OutputFormat = OUTPUT_FORMATS[this.bundle.env.outputFormat];
|
|
113
126
|
this.outputFormat = new OutputFormat(this);
|
|
@@ -340,6 +353,26 @@ export class ScopeHoistingPackager {
|
|
|
340
353
|
actions.skipChildren();
|
|
341
354
|
return;
|
|
342
355
|
}
|
|
356
|
+
// This prevents children of a wrapped asset also being wrapped - it's an "unsafe" optimisation
|
|
357
|
+
// that should only be used when you know (or think you know) what you're doing.
|
|
358
|
+
//
|
|
359
|
+
// In particular this can force an async bundle to be scope hoisted where it previously would not be
|
|
360
|
+
// due to the entry asset being wrapped.
|
|
361
|
+
if (
|
|
362
|
+
this.forceSkipWrapAssets.length > 0 &&
|
|
363
|
+
this.forceSkipWrapAssets.some(
|
|
364
|
+
p => p === path.relative(this.options.projectRoot, asset.filePath),
|
|
365
|
+
)
|
|
366
|
+
) {
|
|
367
|
+
this.logger.verbose({
|
|
368
|
+
message: `Force skipping wrapping of ${path.relative(
|
|
369
|
+
this.options.projectRoot,
|
|
370
|
+
asset.filePath,
|
|
371
|
+
)}`,
|
|
372
|
+
});
|
|
373
|
+
actions.skipChildren();
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
343
376
|
if (!asset.meta.isConstantModule) {
|
|
344
377
|
this.wrappedAssets.add(asset.id);
|
|
345
378
|
wrapped.push(asset);
|
|
@@ -536,92 +569,100 @@ export class ScopeHoistingPackager {
|
|
|
536
569
|
// in a single regex so that we only do one pass over the whole code.
|
|
537
570
|
let offset = 0;
|
|
538
571
|
let columnStartIndex = 0;
|
|
539
|
-
code = code.replace(
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
let deps = depMap.get(d);
|
|
549
|
-
if (!deps) {
|
|
550
|
-
return m;
|
|
572
|
+
code = code.replace(
|
|
573
|
+
getFeatureFlag('conditionalBundlingApi')
|
|
574
|
+
? REPLACEMENT_RE_CONDITIONAL
|
|
575
|
+
: REPLACEMENT_RE,
|
|
576
|
+
(m, d, i) => {
|
|
577
|
+
if (m === '\n') {
|
|
578
|
+
columnStartIndex = i + offset + 1;
|
|
579
|
+
lineCount++;
|
|
580
|
+
return '\n';
|
|
551
581
|
}
|
|
552
582
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
let
|
|
566
|
-
asset,
|
|
583
|
+
// If we matched an import, replace with the source code for the dependency.
|
|
584
|
+
if (d != null) {
|
|
585
|
+
let deps = depMap.get(d);
|
|
586
|
+
if (!deps) {
|
|
587
|
+
return m;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
let replacement = '';
|
|
591
|
+
|
|
592
|
+
// A single `${id}:${specifier}:esm` might have been resolved to multiple assets due to
|
|
593
|
+
// reexports.
|
|
594
|
+
for (let dep of deps) {
|
|
595
|
+
let resolved = this.bundleGraph.getResolvedAsset(
|
|
567
596
|
dep,
|
|
568
|
-
|
|
597
|
+
this.bundle,
|
|
569
598
|
);
|
|
570
|
-
let
|
|
571
|
-
if (
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
//
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
599
|
+
let skipped = this.bundleGraph.isDependencySkipped(dep);
|
|
600
|
+
if (resolved && !skipped) {
|
|
601
|
+
// Hoist variable declarations for the referenced parcelRequire dependencies
|
|
602
|
+
// after the dependency is declared. This handles the case where the resulting asset
|
|
603
|
+
// is wrapped, but the dependency in this asset is not marked as wrapped. This means
|
|
604
|
+
// that it was imported/required at the top-level, so its side effects should run immediately.
|
|
605
|
+
let [res, lines] = this.getHoistedParcelRequires(
|
|
606
|
+
asset,
|
|
607
|
+
dep,
|
|
608
|
+
resolved,
|
|
609
|
+
);
|
|
610
|
+
let map;
|
|
611
|
+
if (
|
|
612
|
+
this.bundle.hasAsset(resolved) &&
|
|
613
|
+
!this.seenAssets.has(resolved.id)
|
|
614
|
+
) {
|
|
615
|
+
// If this asset is wrapped, we need to hoist the code for the dependency
|
|
616
|
+
// outside our parcelRequire.register wrapper. This is safe because all
|
|
617
|
+
// assets referenced by this asset will also be wrapped. Otherwise, inline the
|
|
618
|
+
// asset content where the import statement was.
|
|
619
|
+
if (shouldWrap) {
|
|
620
|
+
depContent.push(this.visitAsset(resolved));
|
|
621
|
+
} else {
|
|
622
|
+
let [depCode, depMap, depLines] = this.visitAsset(resolved);
|
|
623
|
+
res = depCode + '\n' + res;
|
|
624
|
+
lines += 1 + depLines;
|
|
625
|
+
map = depMap;
|
|
626
|
+
}
|
|
586
627
|
}
|
|
587
|
-
}
|
|
588
628
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
629
|
+
// Push this asset's source mappings down by the number of lines in the dependency
|
|
630
|
+
// plus the number of hoisted parcelRequires. Then insert the source map for the dependency.
|
|
631
|
+
if (sourceMap) {
|
|
632
|
+
if (lines > 0) {
|
|
633
|
+
sourceMap.offsetLines(lineCount + 1, lines);
|
|
634
|
+
}
|
|
595
635
|
|
|
596
|
-
|
|
597
|
-
|
|
636
|
+
if (map) {
|
|
637
|
+
sourceMap.addSourceMap(map, lineCount);
|
|
638
|
+
}
|
|
598
639
|
}
|
|
599
|
-
}
|
|
600
640
|
|
|
601
|
-
|
|
602
|
-
|
|
641
|
+
replacement += res;
|
|
642
|
+
lineCount += lines;
|
|
643
|
+
}
|
|
603
644
|
}
|
|
645
|
+
return replacement;
|
|
604
646
|
}
|
|
605
|
-
return replacement;
|
|
606
|
-
}
|
|
607
647
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
648
|
+
// If it wasn't a dependency, then it was an inline replacement (e.g. $id$import$foo -> $id$export$foo).
|
|
649
|
+
let replacement = replacements.get(m) ?? m;
|
|
650
|
+
if (sourceMap) {
|
|
651
|
+
// Offset the source map columns for this line if the replacement was a different length.
|
|
652
|
+
// This assumes that the match and replacement both do not contain any newlines.
|
|
653
|
+
let lengthDifference = replacement.length - m.length;
|
|
654
|
+
if (lengthDifference !== 0) {
|
|
655
|
+
sourceMap.offsetColumns(
|
|
656
|
+
lineCount + 1,
|
|
657
|
+
i + offset - columnStartIndex + m.length,
|
|
658
|
+
lengthDifference,
|
|
659
|
+
);
|
|
660
|
+
offset += lengthDifference;
|
|
661
|
+
}
|
|
621
662
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
663
|
+
return replacement;
|
|
664
|
+
},
|
|
665
|
+
);
|
|
625
666
|
}
|
|
626
667
|
|
|
627
668
|
// If the asset is wrapped, we need to insert the dependency code outside the parcelRequire.register
|
|
@@ -743,7 +784,10 @@ ${code}
|
|
|
743
784
|
// Async dependencies need a namespace object even if all used symbols were statically analyzed.
|
|
744
785
|
// This is recorded in the promiseSymbol meta property set by the transformer rather than in
|
|
745
786
|
// symbols so that we don't mark all symbols as used.
|
|
746
|
-
if (
|
|
787
|
+
if (
|
|
788
|
+
(dep.priority === 'lazy' || dep.priority === 'conditional') &&
|
|
789
|
+
dep.meta.promiseSymbol
|
|
790
|
+
) {
|
|
747
791
|
let promiseSymbol = dep.meta.promiseSymbol;
|
|
748
792
|
invariant(typeof promiseSymbol === 'string');
|
|
749
793
|
let symbol = this.getSymbolResolution(asset, resolved, '*', dep);
|
|
@@ -1376,7 +1420,9 @@ ${code}
|
|
|
1376
1420
|
.getBundleGroupsContainingBundle(this.bundle)
|
|
1377
1421
|
.some(g => this.bundleGraph.isEntryBundleGroup(g)) ||
|
|
1378
1422
|
this.bundle.env.isIsolated() ||
|
|
1379
|
-
this.bundle.bundleBehavior === 'isolated'
|
|
1423
|
+
this.bundle.bundleBehavior === 'isolated' ||
|
|
1424
|
+
// Conditional deps may be loaded before entrypoints on the server
|
|
1425
|
+
this.hasConditionalDependency();
|
|
1380
1426
|
|
|
1381
1427
|
if (mightBeFirstJS) {
|
|
1382
1428
|
let preludeCode = prelude(this.parcelRequireName);
|
|
@@ -1430,13 +1476,7 @@ ${code}
|
|
|
1430
1476
|
asset.symbols.hasExportSymbol('*') &&
|
|
1431
1477
|
!asset.symbols.hasExportSymbol('default')
|
|
1432
1478
|
) {
|
|
1433
|
-
|
|
1434
|
-
return deps.some(
|
|
1435
|
-
dep =>
|
|
1436
|
-
this.bundle.hasDependency(dep) &&
|
|
1437
|
-
// dep.meta.isES6Module &&
|
|
1438
|
-
dep.symbols.hasExportSymbol('default'),
|
|
1439
|
-
);
|
|
1479
|
+
return true;
|
|
1440
1480
|
}
|
|
1441
1481
|
|
|
1442
1482
|
return false;
|
|
@@ -1467,4 +1507,18 @@ ${code}
|
|
|
1467
1507
|
? `(${args.join(', ')}) => ${expr}`
|
|
1468
1508
|
: `function (${args.join(', ')}) { return ${expr}; }`;
|
|
1469
1509
|
}
|
|
1510
|
+
|
|
1511
|
+
hasConditionalDependency(): boolean {
|
|
1512
|
+
if (!getFeatureFlag('conditionalBundlingApi')) {
|
|
1513
|
+
return false;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
return this.bundle
|
|
1517
|
+
.getEntryAssets()
|
|
1518
|
+
.some(entry =>
|
|
1519
|
+
this.bundleGraph
|
|
1520
|
+
.getIncomingDependencies(entry)
|
|
1521
|
+
.some(dep => dep.priority === 'conditional'),
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1470
1524
|
}
|
package/src/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import {ScopeHoistingPackager} from './ScopeHoistingPackager';
|
|
|
17
17
|
type JSPackagerConfig = {|
|
|
18
18
|
parcelRequireName: string,
|
|
19
19
|
unstable_asyncBundleRuntime: boolean,
|
|
20
|
+
unstable_forceSkipWrapAssets: Array<string>,
|
|
20
21
|
|};
|
|
21
22
|
|
|
22
23
|
const CONFIG_SCHEMA: SchemaEntity = {
|
|
@@ -25,6 +26,12 @@ const CONFIG_SCHEMA: SchemaEntity = {
|
|
|
25
26
|
unstable_asyncBundleRuntime: {
|
|
26
27
|
type: 'boolean',
|
|
27
28
|
},
|
|
29
|
+
unstable_forceSkipWrapAssets: {
|
|
30
|
+
type: 'array',
|
|
31
|
+
items: {
|
|
32
|
+
type: 'string',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
28
35
|
},
|
|
29
36
|
additionalProperties: false,
|
|
30
37
|
};
|
|
@@ -66,6 +73,8 @@ export default (new Packager({
|
|
|
66
73
|
unstable_asyncBundleRuntime: Boolean(
|
|
67
74
|
conf?.contents?.unstable_asyncBundleRuntime,
|
|
68
75
|
),
|
|
76
|
+
unstable_forceSkipWrapAssets:
|
|
77
|
+
conf?.contents?.unstable_forceSkipWrapAssets ?? [],
|
|
69
78
|
};
|
|
70
79
|
},
|
|
71
80
|
async package({
|
|
@@ -75,6 +84,7 @@ export default (new Packager({
|
|
|
75
84
|
getSourceMapReference,
|
|
76
85
|
config,
|
|
77
86
|
options,
|
|
87
|
+
logger,
|
|
78
88
|
}) {
|
|
79
89
|
// If this is a non-module script, and there is only one asset with no dependencies,
|
|
80
90
|
// then we don't need to package at all and can pass through the original code un-wrapped.
|
|
@@ -98,6 +108,8 @@ export default (new Packager({
|
|
|
98
108
|
bundle,
|
|
99
109
|
nullthrows(config).parcelRequireName,
|
|
100
110
|
nullthrows(config).unstable_asyncBundleRuntime,
|
|
111
|
+
nullthrows(config).unstable_forceSkipWrapAssets,
|
|
112
|
+
logger,
|
|
101
113
|
)
|
|
102
114
|
: new DevPackager(
|
|
103
115
|
options,
|