@jsenv/core 27.0.0-alpha.56 → 27.0.0-alpha.59
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/src/build/build.js
CHANGED
|
@@ -14,7 +14,9 @@ import {
|
|
|
14
14
|
urlToExtension,
|
|
15
15
|
urlToRelativeUrl,
|
|
16
16
|
writeFile,
|
|
17
|
+
registerDirectoryLifecycle,
|
|
17
18
|
} from "@jsenv/filesystem"
|
|
19
|
+
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
|
|
18
20
|
import { createLogger } from "@jsenv/logger"
|
|
19
21
|
|
|
20
22
|
import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
|
|
@@ -79,6 +81,7 @@ import { resyncRessourceHints } from "./resync_ressource_hints.js"
|
|
|
79
81
|
*/
|
|
80
82
|
export const build = async ({
|
|
81
83
|
signal = new AbortController().signal,
|
|
84
|
+
handleSIGINT = true,
|
|
82
85
|
logLevel = "info",
|
|
83
86
|
rootDirectoryUrl,
|
|
84
87
|
buildDirectoryUrl,
|
|
@@ -97,13 +100,34 @@ export const build = async ({
|
|
|
97
100
|
versioningMethod = "search_param", // "filename", "search_param"
|
|
98
101
|
lineBreakNormalization = process.platform === "win32",
|
|
99
102
|
|
|
103
|
+
clientFiles = {
|
|
104
|
+
"./**": true,
|
|
105
|
+
"./**/.*/": false, // any folder starting with a dot is ignored (includes .git,.jsenv for instance)
|
|
106
|
+
"./dist/": false,
|
|
107
|
+
"./**/node_modules/": false,
|
|
108
|
+
},
|
|
109
|
+
cooldownBetweenFileEvents,
|
|
110
|
+
watch = false,
|
|
111
|
+
|
|
100
112
|
writeOnFileSystem = true,
|
|
101
113
|
buildDirectoryClean = true,
|
|
102
114
|
baseUrl = "/",
|
|
103
115
|
assetManifest = true,
|
|
104
116
|
assetManifestFileRelativeUrl = "asset-manifest.json",
|
|
105
117
|
}) => {
|
|
106
|
-
const
|
|
118
|
+
const operation = Abort.startOperation()
|
|
119
|
+
operation.addAbortSignal(signal)
|
|
120
|
+
if (handleSIGINT) {
|
|
121
|
+
operation.addAbortSource((abort) => {
|
|
122
|
+
return raceProcessTeardownEvents(
|
|
123
|
+
{
|
|
124
|
+
SIGINT: true,
|
|
125
|
+
},
|
|
126
|
+
abort,
|
|
127
|
+
)
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
107
131
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
108
132
|
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl)
|
|
109
133
|
assertEntryPoints({ entryPoints })
|
|
@@ -113,659 +137,739 @@ export const build = async ({
|
|
|
113
137
|
)
|
|
114
138
|
}
|
|
115
139
|
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
140
|
+
const runBuild = async ({ signal, logLevel }) => {
|
|
141
|
+
const logger = createLogger({ logLevel })
|
|
142
|
+
const buildOperation = Abort.startOperation()
|
|
143
|
+
buildOperation.addAbortSignal(signal)
|
|
144
|
+
const entryPointKeys = Object.keys(entryPoints)
|
|
145
|
+
if (entryPointKeys.length === 1) {
|
|
146
|
+
logger.info(`
|
|
119
147
|
build "${entryPointKeys[0]}"`)
|
|
120
|
-
|
|
121
|
-
|
|
148
|
+
} else {
|
|
149
|
+
logger.info(`
|
|
122
150
|
build ${entryPointKeys.length} entry points`)
|
|
123
|
-
|
|
124
|
-
const rawGraph = createUrlGraph()
|
|
125
|
-
const prebuildTask = createTaskLog(logger, "prebuild")
|
|
126
|
-
let urlCount = 0
|
|
127
|
-
const rawGraphKitchen = createKitchen({
|
|
128
|
-
signal,
|
|
129
|
-
logger,
|
|
130
|
-
rootDirectoryUrl,
|
|
131
|
-
urlGraph: rawGraph,
|
|
132
|
-
scenario: "build",
|
|
133
|
-
sourcemaps,
|
|
134
|
-
runtimeCompat,
|
|
135
|
-
plugins: [
|
|
136
|
-
...plugins,
|
|
137
|
-
{
|
|
138
|
-
name: "jsenv:build_log",
|
|
139
|
-
appliesDuring: { build: true },
|
|
140
|
-
cooked: () => {
|
|
141
|
-
urlCount++
|
|
142
|
-
prebuildTask.setRightText(urlCount)
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
...getCorePlugins({
|
|
146
|
-
rootDirectoryUrl,
|
|
147
|
-
urlGraph: rawGraph,
|
|
148
|
-
scenario: "build",
|
|
151
|
+
}
|
|
149
152
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
minification,
|
|
158
|
-
bundling,
|
|
159
|
-
}),
|
|
160
|
-
],
|
|
161
|
-
})
|
|
162
|
-
const entryUrls = []
|
|
163
|
-
try {
|
|
164
|
-
await loadUrlGraph({
|
|
153
|
+
const rawGraph = createUrlGraph()
|
|
154
|
+
const prebuildTask = createTaskLog(logger, "prebuild")
|
|
155
|
+
let urlCount = 0
|
|
156
|
+
const rawGraphKitchen = createKitchen({
|
|
157
|
+
signal,
|
|
158
|
+
logger,
|
|
159
|
+
rootDirectoryUrl,
|
|
165
160
|
urlGraph: rawGraph,
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
// here we can perform many checks such as ensuring ressource hints are used
|
|
185
|
-
prebuildTask.done()
|
|
186
|
-
logger.debug(
|
|
187
|
-
`raw graph urls:
|
|
188
|
-
${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
189
|
-
)
|
|
161
|
+
scenario: "build",
|
|
162
|
+
sourcemaps,
|
|
163
|
+
runtimeCompat,
|
|
164
|
+
plugins: [
|
|
165
|
+
...plugins,
|
|
166
|
+
{
|
|
167
|
+
name: "jsenv:build_log",
|
|
168
|
+
appliesDuring: { build: true },
|
|
169
|
+
cooked: () => {
|
|
170
|
+
urlCount++
|
|
171
|
+
prebuildTask.setRightText(urlCount)
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
...getCorePlugins({
|
|
175
|
+
rootDirectoryUrl,
|
|
176
|
+
urlGraph: rawGraph,
|
|
177
|
+
scenario: "build",
|
|
190
178
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
179
|
+
nodeEsmResolution,
|
|
180
|
+
fileSystemMagicResolution,
|
|
181
|
+
injectedGlobals,
|
|
182
|
+
transpilation: {
|
|
183
|
+
...transpilation,
|
|
184
|
+
jsModuleAsJsClassic: false,
|
|
185
|
+
},
|
|
186
|
+
minification,
|
|
187
|
+
bundling,
|
|
188
|
+
}),
|
|
189
|
+
],
|
|
190
|
+
})
|
|
191
|
+
const entryUrls = []
|
|
192
|
+
try {
|
|
193
|
+
await loadUrlGraph({
|
|
194
|
+
operation: buildOperation,
|
|
195
|
+
urlGraph: rawGraph,
|
|
196
|
+
kitchen: rawGraphKitchen,
|
|
197
|
+
outDirectoryUrl: new URL(`.jsenv/build/`, rootDirectoryUrl),
|
|
198
|
+
startLoading: (cookEntryFile) => {
|
|
199
|
+
Object.keys(entryPoints).forEach((key) => {
|
|
200
|
+
const [, entryUrlInfo] = cookEntryFile({
|
|
201
|
+
trace: `"${key}" in entryPoints parameter`,
|
|
202
|
+
type: "entry_point",
|
|
203
|
+
specifier: key,
|
|
204
|
+
})
|
|
205
|
+
entryUrls.push(entryUrlInfo.url)
|
|
206
|
+
entryUrlInfo.filename = entryPoints[key]
|
|
207
|
+
})
|
|
208
|
+
},
|
|
209
|
+
})
|
|
210
|
+
} catch (e) {
|
|
211
|
+
prebuildTask.fail()
|
|
212
|
+
throw e
|
|
208
213
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
prebuildTask.done()
|
|
215
|
+
|
|
216
|
+
const buildUrlsGenerator = createBuilUrlsGenerator({
|
|
217
|
+
buildDirectoryUrl,
|
|
218
|
+
})
|
|
219
|
+
const rawUrls = {}
|
|
220
|
+
const buildUrls = {}
|
|
221
|
+
const rawUrlRedirections = {}
|
|
222
|
+
const bundleUrlInfos = {}
|
|
223
|
+
const bundlers = {}
|
|
224
|
+
rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
|
|
225
|
+
const bundle = plugin.bundle
|
|
226
|
+
if (!bundle) {
|
|
217
227
|
return
|
|
218
228
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
229
|
+
if (typeof bundle !== "object") {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`bundle must be an object, found "${bundle}" on plugin named "${plugin.name}"`,
|
|
232
|
+
)
|
|
223
233
|
}
|
|
234
|
+
Object.keys(bundle).forEach((type) => {
|
|
235
|
+
const bundleFunction = bundle[type]
|
|
236
|
+
if (!bundleFunction) {
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
const bundlerForThatType = bundlers[type]
|
|
240
|
+
if (bundlerForThatType) {
|
|
241
|
+
// first plugin to define a bundle hook wins
|
|
242
|
+
return
|
|
243
|
+
}
|
|
244
|
+
bundlers[type] = {
|
|
245
|
+
plugin,
|
|
246
|
+
bundleFunction: bundle[type],
|
|
247
|
+
urlInfos: [],
|
|
248
|
+
}
|
|
249
|
+
})
|
|
224
250
|
})
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
251
|
+
const addToBundlerIfAny = (rawUrlInfo) => {
|
|
252
|
+
const bundler = bundlers[rawUrlInfo.type]
|
|
253
|
+
if (bundler) {
|
|
254
|
+
bundler.urlInfos.push(rawUrlInfo)
|
|
255
|
+
return
|
|
256
|
+
}
|
|
231
257
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
258
|
+
GRAPH.forEach(rawGraph, (rawUrlInfo) => {
|
|
259
|
+
if (rawUrlInfo.data.isEntryPoint) {
|
|
260
|
+
addToBundlerIfAny(rawUrlInfo)
|
|
261
|
+
if (rawUrlInfo.type === "html") {
|
|
262
|
+
rawUrlInfo.dependencies.forEach((dependencyUrl) => {
|
|
263
|
+
const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl)
|
|
264
|
+
if (dependencyUrlInfo.isInline) {
|
|
265
|
+
if (dependencyUrlInfo.type === "js_module") {
|
|
266
|
+
// bundle inline script type module deps
|
|
267
|
+
dependencyUrlInfo.references.forEach((inlineScriptRef) => {
|
|
268
|
+
if (inlineScriptRef.type === "js_import_export") {
|
|
269
|
+
const inlineUrlInfo = rawGraph.getUrlInfo(
|
|
270
|
+
inlineScriptRef.url,
|
|
271
|
+
)
|
|
272
|
+
addToBundlerIfAny(inlineUrlInfo)
|
|
273
|
+
}
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
// inline content cannot be bundled
|
|
277
|
+
return
|
|
248
278
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
addToBundlerIfAny(dependencyUrlInfo)
|
|
253
|
-
})
|
|
254
|
-
rawUrlInfo.references.forEach((reference) => {
|
|
255
|
-
if (
|
|
256
|
-
reference.isRessourceHint &&
|
|
257
|
-
reference.expectedType === "js_module"
|
|
258
|
-
) {
|
|
259
|
-
const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
279
|
+
addToBundlerIfAny(dependencyUrlInfo)
|
|
280
|
+
})
|
|
281
|
+
rawUrlInfo.references.forEach((reference) => {
|
|
260
282
|
if (
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
referencedUrlInfo.dependents.size > 0
|
|
283
|
+
reference.isRessourceHint &&
|
|
284
|
+
reference.expectedType === "js_module"
|
|
264
285
|
) {
|
|
265
|
-
|
|
286
|
+
const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
287
|
+
if (
|
|
288
|
+
referencedUrlInfo &&
|
|
289
|
+
// something else than the ressource hint is using this url
|
|
290
|
+
referencedUrlInfo.dependents.size > 0
|
|
291
|
+
) {
|
|
292
|
+
addToBundlerIfAny(referencedUrlInfo)
|
|
293
|
+
}
|
|
266
294
|
}
|
|
295
|
+
})
|
|
296
|
+
return
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// File referenced with new URL('./file.js', import.meta.url)
|
|
300
|
+
// are entry points that can be bundled
|
|
301
|
+
// For instance we will bundle service worker/workers detected like this
|
|
302
|
+
if (rawUrlInfo.type === "js_module") {
|
|
303
|
+
rawUrlInfo.references.forEach((reference) => {
|
|
304
|
+
if (reference.type === "js_url_specifier") {
|
|
305
|
+
const urlInfo = rawGraph.getUrlInfo(reference.url)
|
|
306
|
+
addToBundlerIfAny(urlInfo)
|
|
267
307
|
}
|
|
268
308
|
})
|
|
309
|
+
}
|
|
310
|
+
})
|
|
311
|
+
const bundleUrlRedirections = {}
|
|
312
|
+
await Object.keys(bundlers).reduce(async (previous, type) => {
|
|
313
|
+
await previous
|
|
314
|
+
const bundler = bundlers[type]
|
|
315
|
+
const urlInfosToBundle = bundler.urlInfos
|
|
316
|
+
if (urlInfosToBundle.length === 0) {
|
|
269
317
|
return
|
|
270
318
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
value: bundler.bundleFunction,
|
|
300
|
-
},
|
|
301
|
-
urlInfosToBundle,
|
|
302
|
-
{
|
|
303
|
-
...rawGraphKitchen.baseContext,
|
|
304
|
-
buildDirectoryUrl,
|
|
305
|
-
},
|
|
306
|
-
)
|
|
307
|
-
Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
|
|
308
|
-
const rawUrlInfo = rawGraph.getUrlInfo(url)
|
|
309
|
-
const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url]
|
|
310
|
-
const bundleUrlInfo = {
|
|
311
|
-
type,
|
|
312
|
-
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
313
|
-
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
314
|
-
...bundlerGeneratedUrlInfo,
|
|
315
|
-
data: {
|
|
316
|
-
...(rawUrlInfo ? rawUrlInfo.data : {}),
|
|
317
|
-
...bundlerGeneratedUrlInfo.data,
|
|
318
|
-
fromBundle: true,
|
|
319
|
-
},
|
|
320
|
-
}
|
|
321
|
-
const buildUrl = buildUrlsGenerator.generate(url, {
|
|
322
|
-
urlInfo: bundleUrlInfo,
|
|
323
|
-
})
|
|
324
|
-
rawUrlRedirections[url] = buildUrl
|
|
325
|
-
rawUrls[buildUrl] = url
|
|
326
|
-
bundleUrlInfos[buildUrl] = bundleUrlInfo
|
|
327
|
-
if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
|
|
328
|
-
const urlForBundler = new URL(
|
|
329
|
-
bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
|
|
330
|
-
buildDirectoryUrl,
|
|
331
|
-
).href
|
|
332
|
-
bundleUrlRedirections[urlForBundler] = buildUrl
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
} catch (e) {
|
|
336
|
-
bundleTask.fail()
|
|
337
|
-
throw e
|
|
338
|
-
}
|
|
339
|
-
bundleTask.done()
|
|
340
|
-
}, Promise.resolve())
|
|
341
|
-
|
|
342
|
-
const buildUrlRedirections = {}
|
|
343
|
-
const finalGraph = createUrlGraph()
|
|
344
|
-
const optimizeUrlContentHooks =
|
|
345
|
-
rawGraphKitchen.pluginController.addHook("optimizeUrlContent")
|
|
346
|
-
const finalGraphKitchen = createKitchen({
|
|
347
|
-
logger,
|
|
348
|
-
rootDirectoryUrl,
|
|
349
|
-
urlGraph: finalGraph,
|
|
350
|
-
scenario: "build",
|
|
351
|
-
sourcemaps,
|
|
352
|
-
sourcemapsRelativeSources: !versioning,
|
|
353
|
-
runtimeCompat,
|
|
354
|
-
plugins: [
|
|
355
|
-
jsenvPluginUrlAnalysis(),
|
|
356
|
-
jsenvPluginAsJsClassic({
|
|
357
|
-
systemJsInjection: true,
|
|
358
|
-
}),
|
|
359
|
-
jsenvPluginInline({
|
|
360
|
-
fetchInlineUrls: false,
|
|
361
|
-
}),
|
|
362
|
-
{
|
|
363
|
-
name: "jsenv:postbuild",
|
|
364
|
-
appliesDuring: { build: true },
|
|
365
|
-
resolveUrl: (reference) => {
|
|
366
|
-
if (reference.specifier[0] === "#") {
|
|
367
|
-
reference.external = true
|
|
368
|
-
}
|
|
369
|
-
let url =
|
|
370
|
-
reference.specifier[0] === "/"
|
|
371
|
-
? new URL(reference.specifier.slice(1), buildDirectoryUrl).href
|
|
372
|
-
: new URL(reference.specifier, reference.parentUrl).href
|
|
373
|
-
const urlRedirectedByBundle = bundleUrlRedirections[url]
|
|
374
|
-
if (urlRedirectedByBundle) {
|
|
375
|
-
return urlRedirectedByBundle
|
|
376
|
-
}
|
|
377
|
-
const urlRedirected = rawUrlRedirections[url]
|
|
378
|
-
return urlRedirected || url
|
|
379
|
-
},
|
|
380
|
-
redirectUrl: (reference) => {
|
|
381
|
-
if (!reference.url.startsWith("file:")) {
|
|
382
|
-
return null
|
|
383
|
-
}
|
|
384
|
-
// already a build url
|
|
385
|
-
const rawUrl = rawUrls[reference.url]
|
|
386
|
-
if (rawUrl) {
|
|
387
|
-
return reference.url
|
|
319
|
+
const bundleTask = createTaskLog(logger, `bundle "${type}"`)
|
|
320
|
+
try {
|
|
321
|
+
const bundlerGeneratedUrlInfos =
|
|
322
|
+
await rawGraphKitchen.pluginController.callAsyncHook(
|
|
323
|
+
{
|
|
324
|
+
plugin: bundler.plugin,
|
|
325
|
+
hookName: "bundle",
|
|
326
|
+
value: bundler.bundleFunction,
|
|
327
|
+
},
|
|
328
|
+
urlInfosToBundle,
|
|
329
|
+
{
|
|
330
|
+
...rawGraphKitchen.baseContext,
|
|
331
|
+
buildDirectoryUrl,
|
|
332
|
+
},
|
|
333
|
+
)
|
|
334
|
+
Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
|
|
335
|
+
const rawUrlInfo = rawGraph.getUrlInfo(url)
|
|
336
|
+
const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url]
|
|
337
|
+
const bundleUrlInfo = {
|
|
338
|
+
type,
|
|
339
|
+
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
340
|
+
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
341
|
+
...bundlerGeneratedUrlInfo,
|
|
342
|
+
data: {
|
|
343
|
+
...(rawUrlInfo ? rawUrlInfo.data : {}),
|
|
344
|
+
...bundlerGeneratedUrlInfo.data,
|
|
345
|
+
fromBundle: true,
|
|
346
|
+
},
|
|
388
347
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
348
|
+
const buildUrl = buildUrlsGenerator.generate(url, {
|
|
349
|
+
urlInfo: bundleUrlInfo,
|
|
350
|
+
})
|
|
351
|
+
rawUrlRedirections[url] = buildUrl
|
|
352
|
+
rawUrls[buildUrl] = url
|
|
353
|
+
bundleUrlInfos[buildUrl] = bundleUrlInfo
|
|
354
|
+
if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
|
|
355
|
+
const urlForBundler = new URL(
|
|
356
|
+
bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
|
|
357
|
+
buildDirectoryUrl,
|
|
358
|
+
).href
|
|
359
|
+
bundleUrlRedirections[urlForBundler] = buildUrl
|
|
393
360
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
361
|
+
})
|
|
362
|
+
} catch (e) {
|
|
363
|
+
bundleTask.fail()
|
|
364
|
+
throw e
|
|
365
|
+
}
|
|
366
|
+
bundleTask.done()
|
|
367
|
+
}, Promise.resolve())
|
|
368
|
+
|
|
369
|
+
const buildUrlRedirections = {}
|
|
370
|
+
const finalGraph = createUrlGraph()
|
|
371
|
+
const optimizeUrlContentHooks =
|
|
372
|
+
rawGraphKitchen.pluginController.addHook("optimizeUrlContent")
|
|
373
|
+
const finalGraphKitchen = createKitchen({
|
|
374
|
+
logger,
|
|
375
|
+
rootDirectoryUrl,
|
|
376
|
+
urlGraph: finalGraph,
|
|
377
|
+
scenario: "build",
|
|
378
|
+
sourcemaps,
|
|
379
|
+
sourcemapsRelativeSources: !versioning,
|
|
380
|
+
runtimeCompat,
|
|
381
|
+
plugins: [
|
|
382
|
+
jsenvPluginUrlAnalysis(),
|
|
383
|
+
jsenvPluginAsJsClassic({
|
|
384
|
+
systemJsInjection: true,
|
|
385
|
+
}),
|
|
386
|
+
jsenvPluginInline({
|
|
387
|
+
fetchInlineUrls: false,
|
|
388
|
+
}),
|
|
389
|
+
{
|
|
390
|
+
name: "jsenv:postbuild",
|
|
391
|
+
appliesDuring: { build: true },
|
|
392
|
+
resolveUrl: (reference) => {
|
|
393
|
+
if (reference.specifier[0] === "#") {
|
|
394
|
+
reference.external = true
|
|
406
395
|
}
|
|
407
|
-
let
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
: reference.url
|
|
415
|
-
} else {
|
|
416
|
-
rawUrl = reference.url
|
|
396
|
+
let url =
|
|
397
|
+
reference.specifier[0] === "/"
|
|
398
|
+
? new URL(reference.specifier.slice(1), buildDirectoryUrl).href
|
|
399
|
+
: new URL(reference.specifier, reference.parentUrl).href
|
|
400
|
+
const urlRedirectedByBundle = bundleUrlRedirections[url]
|
|
401
|
+
if (urlRedirectedByBundle) {
|
|
402
|
+
return urlRedirectedByBundle
|
|
417
403
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
404
|
+
const urlRedirected = rawUrlRedirections[url]
|
|
405
|
+
return urlRedirected || url
|
|
406
|
+
},
|
|
407
|
+
redirectUrl: (reference) => {
|
|
408
|
+
if (!reference.url.startsWith("file:")) {
|
|
409
|
+
return null
|
|
410
|
+
}
|
|
411
|
+
// already a build url
|
|
412
|
+
const rawUrl = rawUrls[reference.url]
|
|
413
|
+
if (rawUrl) {
|
|
414
|
+
return reference.url
|
|
415
|
+
}
|
|
416
|
+
// from rollup or postcss
|
|
417
|
+
const bundleUrlInfo = bundleUrlInfos[reference.url]
|
|
418
|
+
if (bundleUrlInfo) {
|
|
419
|
+
return reference.url
|
|
420
|
+
}
|
|
421
|
+
// from "js_module_as_js_classic":
|
|
422
|
+
// - injecting "?as_js_classic" for the first time
|
|
423
|
+
// - injecting "?as_js_classic" because the parentUrl has it
|
|
424
|
+
if (reference.original) {
|
|
425
|
+
const referenceOriginalUrl = reference.original.url
|
|
426
|
+
let originalBuildUrl
|
|
427
|
+
if (urlIsInsideOf(referenceOriginalUrl, buildDirectoryUrl)) {
|
|
428
|
+
originalBuildUrl = referenceOriginalUrl
|
|
429
|
+
} else {
|
|
430
|
+
originalBuildUrl = Object.keys(rawUrls).find(
|
|
431
|
+
(key) => rawUrls[key] === referenceOriginalUrl,
|
|
432
|
+
)
|
|
441
433
|
}
|
|
442
|
-
|
|
443
|
-
|
|
434
|
+
let rawUrl
|
|
435
|
+
if (urlIsInsideOf(reference.url, buildDirectoryUrl)) {
|
|
436
|
+
// rawUrl = rawUrls[reference.url] || reference.url
|
|
437
|
+
const originalBuildUrl =
|
|
438
|
+
buildUrlRedirections[referenceOriginalUrl]
|
|
439
|
+
rawUrl = originalBuildUrl
|
|
440
|
+
? rawUrls[originalBuildUrl]
|
|
441
|
+
: reference.url
|
|
442
|
+
} else {
|
|
443
|
+
rawUrl = reference.url
|
|
444
444
|
}
|
|
445
|
-
|
|
446
|
-
|
|
445
|
+
// the url info do not exists yet (it will be created after this "normalize" hook)
|
|
446
|
+
// And the content will be generated when url is cooked by url graph loader.
|
|
447
|
+
// Here we just want to reserve an url for that file
|
|
448
|
+
const buildUrl = buildUrlsGenerator.generate(rawUrl, {
|
|
449
|
+
urlInfo: {
|
|
450
|
+
data: {
|
|
451
|
+
...reference.data,
|
|
452
|
+
isWebWorkerEntryPoint:
|
|
453
|
+
isWebWorkerEntryPointReference(reference),
|
|
454
|
+
},
|
|
455
|
+
type: reference.expectedType,
|
|
456
|
+
subtype: reference.expectedSubtype,
|
|
457
|
+
filename: reference.filename,
|
|
458
|
+
},
|
|
459
|
+
})
|
|
460
|
+
buildUrlRedirections[originalBuildUrl] = buildUrl
|
|
461
|
+
rawUrls[buildUrl] = rawUrl
|
|
462
|
+
return buildUrl
|
|
463
|
+
}
|
|
464
|
+
if (reference.isInline) {
|
|
465
|
+
const rawUrlInfo = GRAPH.find(rawGraph, (rawUrlInfo) => {
|
|
466
|
+
if (!rawUrlInfo.isInline) {
|
|
467
|
+
return false
|
|
468
|
+
}
|
|
469
|
+
if (rawUrlInfo.content === reference.content) {
|
|
470
|
+
return true
|
|
471
|
+
}
|
|
472
|
+
if (rawUrlInfo.originalContent === reference.content) {
|
|
473
|
+
return true
|
|
474
|
+
}
|
|
475
|
+
return false
|
|
476
|
+
})
|
|
477
|
+
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
478
|
+
if (!rawUrlInfo) {
|
|
479
|
+
// generated during final graph
|
|
480
|
+
// (happens for JSON.parse injected for import assertions for instance)
|
|
481
|
+
// throw new Error(`cannot find raw url for "${reference.url}"`)
|
|
482
|
+
return reference.url
|
|
447
483
|
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
// throw new Error(`cannot find raw url for "${reference.url}"`)
|
|
455
|
-
return reference.url
|
|
484
|
+
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
485
|
+
urlInfo: rawUrlInfo,
|
|
486
|
+
parentUrlInfo,
|
|
487
|
+
})
|
|
488
|
+
rawUrls[buildUrl] = rawUrlInfo.url
|
|
489
|
+
return buildUrl
|
|
456
490
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
491
|
+
// from "js_module_as_js_classic":
|
|
492
|
+
// - to inject "s.js"
|
|
493
|
+
if (reference.injected) {
|
|
494
|
+
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
495
|
+
urlInfo: {
|
|
496
|
+
data: {},
|
|
497
|
+
type: "js_classic",
|
|
498
|
+
},
|
|
499
|
+
})
|
|
500
|
+
rawUrls[buildUrl] = reference.url
|
|
501
|
+
return buildUrl
|
|
502
|
+
}
|
|
503
|
+
const rawUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
504
|
+
// files from root directory but not given to rollup nor postcss
|
|
505
|
+
if (rawUrlInfo) {
|
|
506
|
+
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
507
|
+
urlInfo: rawUrlInfo,
|
|
508
|
+
})
|
|
509
|
+
rawUrls[buildUrl] = rawUrlInfo.url
|
|
510
|
+
return buildUrl
|
|
511
|
+
}
|
|
512
|
+
if (reference.type === "sourcemap_comment") {
|
|
513
|
+
// inherit parent build url
|
|
514
|
+
return generateSourcemapUrl(reference.parentUrl)
|
|
515
|
+
}
|
|
516
|
+
// files generated during the final graph:
|
|
517
|
+
// - sourcemaps
|
|
518
|
+
// const finalUrlInfo = finalGraph.getUrlInfo(url)
|
|
467
519
|
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
468
520
|
urlInfo: {
|
|
469
521
|
data: {},
|
|
470
|
-
type: "
|
|
522
|
+
type: "asset",
|
|
471
523
|
},
|
|
472
524
|
})
|
|
473
|
-
rawUrls[buildUrl] = reference.url
|
|
474
|
-
return buildUrl
|
|
475
|
-
}
|
|
476
|
-
const rawUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
477
|
-
// files from root directory but not given to rollup nor postcss
|
|
478
|
-
if (rawUrlInfo) {
|
|
479
|
-
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
480
|
-
urlInfo: rawUrlInfo,
|
|
481
|
-
})
|
|
482
|
-
rawUrls[buildUrl] = rawUrlInfo.url
|
|
483
525
|
return buildUrl
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
urlInfo: {
|
|
494
|
-
data: {},
|
|
495
|
-
type: "asset",
|
|
496
|
-
},
|
|
497
|
-
})
|
|
498
|
-
return buildUrl
|
|
499
|
-
},
|
|
500
|
-
formatUrl: (reference) => {
|
|
501
|
-
if (!reference.generatedUrl.startsWith("file:")) {
|
|
502
|
-
return null
|
|
503
|
-
}
|
|
504
|
-
if (!urlIsInsideOf(reference.generatedUrl, buildDirectoryUrl)) {
|
|
505
|
-
throw new Error(
|
|
506
|
-
`urls should be inside build directory at this stage, found "${reference.url}"`,
|
|
507
|
-
)
|
|
508
|
-
}
|
|
509
|
-
// remove eventual search params and hash
|
|
510
|
-
const urlUntilPathname = asUrlUntilPathname(reference.generatedUrl)
|
|
511
|
-
let specifier
|
|
512
|
-
if (baseUrl === "./") {
|
|
513
|
-
const relativeUrl = urlToRelativeUrl(
|
|
514
|
-
urlUntilPathname,
|
|
515
|
-
reference.parentUrl === rootDirectoryUrl
|
|
516
|
-
? buildDirectoryUrl
|
|
517
|
-
: reference.parentUrl,
|
|
518
|
-
)
|
|
519
|
-
// ensure "./" on relative url (otherwise it could be a "bare specifier")
|
|
520
|
-
specifier =
|
|
521
|
-
relativeUrl[0] === "." ? relativeUrl : `./${relativeUrl}`
|
|
522
|
-
} else {
|
|
523
|
-
// if a file is in the same directory we could prefer the relative notation
|
|
524
|
-
// but to keep things simple let's keep the "absolutely relative" to baseUrl for now
|
|
525
|
-
specifier = `${baseUrl}${urlToRelativeUrl(
|
|
526
|
-
urlUntilPathname,
|
|
527
|
-
buildDirectoryUrl,
|
|
528
|
-
)}`
|
|
529
|
-
}
|
|
530
|
-
buildUrls[specifier] = reference.generatedUrl
|
|
531
|
-
return specifier
|
|
532
|
-
},
|
|
533
|
-
fetchUrlContent: async (finalUrlInfo, context) => {
|
|
534
|
-
if (!finalUrlInfo.url.startsWith("file:")) {
|
|
535
|
-
return { external: true }
|
|
536
|
-
}
|
|
537
|
-
const fromBundleOrRawGraph = (url) => {
|
|
538
|
-
const bundleUrlInfo = bundleUrlInfos[url]
|
|
539
|
-
if (bundleUrlInfo) {
|
|
540
|
-
return bundleUrlInfo
|
|
526
|
+
},
|
|
527
|
+
formatUrl: (reference) => {
|
|
528
|
+
if (!reference.generatedUrl.startsWith("file:")) {
|
|
529
|
+
return null
|
|
530
|
+
}
|
|
531
|
+
if (!urlIsInsideOf(reference.generatedUrl, buildDirectoryUrl)) {
|
|
532
|
+
throw new Error(
|
|
533
|
+
`urls should be inside build directory at this stage, found "${reference.url}"`,
|
|
534
|
+
)
|
|
541
535
|
}
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
536
|
+
// remove eventual search params and hash
|
|
537
|
+
const urlUntilPathname = asUrlUntilPathname(reference.generatedUrl)
|
|
538
|
+
let specifier
|
|
539
|
+
if (baseUrl === "./") {
|
|
540
|
+
const relativeUrl = urlToRelativeUrl(
|
|
541
|
+
urlUntilPathname,
|
|
542
|
+
reference.parentUrl === rootDirectoryUrl
|
|
543
|
+
? buildDirectoryUrl
|
|
544
|
+
: reference.parentUrl,
|
|
545
|
+
)
|
|
546
|
+
// ensure "./" on relative url (otherwise it could be a "bare specifier")
|
|
547
|
+
specifier =
|
|
548
|
+
relativeUrl[0] === "." ? relativeUrl : `./${relativeUrl}`
|
|
549
|
+
} else {
|
|
550
|
+
// if a file is in the same directory we could prefer the relative notation
|
|
551
|
+
// but to keep things simple let's keep the "absolutely relative" to baseUrl for now
|
|
552
|
+
specifier = `${baseUrl}${urlToRelativeUrl(
|
|
553
|
+
urlUntilPathname,
|
|
554
|
+
buildDirectoryUrl,
|
|
555
|
+
)}`
|
|
556
|
+
}
|
|
557
|
+
buildUrls[specifier] = reference.generatedUrl
|
|
558
|
+
return specifier
|
|
559
|
+
},
|
|
560
|
+
fetchUrlContent: async (finalUrlInfo, context) => {
|
|
561
|
+
if (!finalUrlInfo.url.startsWith("file:")) {
|
|
562
|
+
return { external: true }
|
|
563
|
+
}
|
|
564
|
+
const fromBundleOrRawGraph = (url) => {
|
|
565
|
+
const bundleUrlInfo = bundleUrlInfos[url]
|
|
566
|
+
if (bundleUrlInfo) {
|
|
567
|
+
return bundleUrlInfo
|
|
568
|
+
}
|
|
569
|
+
const rawUrl = rawUrls[url] || url
|
|
570
|
+
const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
|
|
571
|
+
if (!rawUrlInfo) {
|
|
572
|
+
const originalBuildUrl = buildUrlRedirections[url]
|
|
573
|
+
if (originalBuildUrl) {
|
|
574
|
+
return fromBundleOrRawGraph(originalBuildUrl)
|
|
575
|
+
}
|
|
576
|
+
throw new Error(`Cannot find url`)
|
|
548
577
|
}
|
|
549
|
-
|
|
578
|
+
if (rawUrlInfo.isInline) {
|
|
579
|
+
// Inline content, such as <script> inside html, is transformed during the previous phase.
|
|
580
|
+
// If we read the inline content it would be considered as the original content.
|
|
581
|
+
// - It could be "fixed" by taking into account sourcemap and consider sourcemap sources
|
|
582
|
+
// as the original content.
|
|
583
|
+
// - But it would not work when sourcemap are not generated
|
|
584
|
+
// - would be a bit slower
|
|
585
|
+
// - So instead of reading the inline content directly, we search into raw graph
|
|
586
|
+
// to get "originalContent" and "sourcemap"
|
|
587
|
+
finalUrlInfo.type = rawUrlInfo.type
|
|
588
|
+
finalUrlInfo.subtype = rawUrlInfo.subtype
|
|
589
|
+
return rawUrlInfo
|
|
590
|
+
}
|
|
591
|
+
return rawUrlInfo
|
|
550
592
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
593
|
+
// reference injected during "postbuild":
|
|
594
|
+
// - happens for "as_js_classic" injecting "s.js"
|
|
595
|
+
if (context.reference.injected) {
|
|
596
|
+
const [ref, rawUrlInfo] = rawGraphKitchen.injectReference({
|
|
597
|
+
type: context.reference.type,
|
|
598
|
+
expectedType: context.reference.expectedType,
|
|
599
|
+
expectedSubtype: context.reference.expectedSubtype,
|
|
600
|
+
parentUrl: rawUrls[context.reference.parentUrl],
|
|
601
|
+
specifier: context.reference.specifier,
|
|
602
|
+
injected: true,
|
|
603
|
+
})
|
|
604
|
+
await rawGraphKitchen.cook({
|
|
605
|
+
reference: ref,
|
|
606
|
+
urlInfo: rawUrlInfo,
|
|
607
|
+
})
|
|
562
608
|
return rawUrlInfo
|
|
563
609
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
expectedType: context.reference.expectedType,
|
|
572
|
-
expectedSubtype: context.reference.expectedSubtype,
|
|
573
|
-
parentUrl: rawUrls[context.reference.parentUrl],
|
|
574
|
-
specifier: context.reference.specifier,
|
|
575
|
-
injected: true,
|
|
576
|
-
})
|
|
577
|
-
await rawGraphKitchen.cook({
|
|
578
|
-
reference: ref,
|
|
579
|
-
urlInfo: rawUrlInfo,
|
|
580
|
-
})
|
|
581
|
-
return rawUrlInfo
|
|
582
|
-
}
|
|
583
|
-
// reference updated during "postbuild":
|
|
584
|
-
// - happens for "as_js_classic"
|
|
585
|
-
if (context.reference.original) {
|
|
586
|
-
return fromBundleOrRawGraph(context.reference.original.url)
|
|
587
|
-
}
|
|
588
|
-
return fromBundleOrRawGraph(finalUrlInfo.url)
|
|
610
|
+
// reference updated during "postbuild":
|
|
611
|
+
// - happens for "as_js_classic"
|
|
612
|
+
if (context.reference.original) {
|
|
613
|
+
return fromBundleOrRawGraph(context.reference.original.url)
|
|
614
|
+
}
|
|
615
|
+
return fromBundleOrRawGraph(finalUrlInfo.url)
|
|
616
|
+
},
|
|
589
617
|
},
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
}
|
|
618
|
+
{
|
|
619
|
+
name: "jsenv:optimize",
|
|
620
|
+
appliesDuring: { build: true },
|
|
621
|
+
finalizeUrlContent: async (urlInfo, context) => {
|
|
622
|
+
if (optimizeUrlContentHooks.length) {
|
|
623
|
+
await rawGraphKitchen.pluginController.callAsyncHooks(
|
|
624
|
+
"optimizeUrlContent",
|
|
625
|
+
urlInfo,
|
|
626
|
+
context,
|
|
627
|
+
async (optimizeReturnValue) => {
|
|
628
|
+
await finalGraphKitchen.urlInfoTransformer.applyFinalTransformations(
|
|
629
|
+
urlInfo,
|
|
630
|
+
optimizeReturnValue,
|
|
631
|
+
)
|
|
632
|
+
},
|
|
633
|
+
)
|
|
634
|
+
}
|
|
635
|
+
},
|
|
608
636
|
},
|
|
609
|
-
|
|
610
|
-
],
|
|
611
|
-
})
|
|
612
|
-
const buildTask = createTaskLog(logger, "build")
|
|
613
|
-
const postBuildEntryUrls = []
|
|
614
|
-
try {
|
|
615
|
-
await loadUrlGraph({
|
|
616
|
-
urlGraph: finalGraph,
|
|
617
|
-
kitchen: finalGraphKitchen,
|
|
618
|
-
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
619
|
-
skipRessourceHint: true,
|
|
620
|
-
startLoading: (cookEntryFile) => {
|
|
621
|
-
entryUrls.forEach((entryUrl) => {
|
|
622
|
-
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
623
|
-
trace: `entryPoint`,
|
|
624
|
-
type: "entry_point",
|
|
625
|
-
specifier: entryUrl,
|
|
626
|
-
})
|
|
627
|
-
postBuildEntryUrls.push(postBuildEntryUrlInfo.url)
|
|
628
|
-
})
|
|
629
|
-
},
|
|
637
|
+
],
|
|
630
638
|
})
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
639
|
+
const buildTask = createTaskLog(logger, "build")
|
|
640
|
+
const postBuildEntryUrls = []
|
|
641
|
+
try {
|
|
642
|
+
await loadUrlGraph({
|
|
643
|
+
operation: buildOperation,
|
|
644
|
+
urlGraph: finalGraph,
|
|
645
|
+
kitchen: finalGraphKitchen,
|
|
646
|
+
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
647
|
+
skipRessourceHint: true,
|
|
648
|
+
startLoading: (cookEntryFile) => {
|
|
649
|
+
entryUrls.forEach((entryUrl) => {
|
|
650
|
+
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
651
|
+
trace: `entryPoint`,
|
|
652
|
+
type: "entry_point",
|
|
653
|
+
specifier: entryUrl,
|
|
654
|
+
})
|
|
655
|
+
postBuildEntryUrls.push(postBuildEntryUrlInfo.url)
|
|
656
|
+
})
|
|
657
|
+
},
|
|
658
|
+
})
|
|
659
|
+
} catch (e) {
|
|
660
|
+
buildTask.fail()
|
|
661
|
+
throw e
|
|
662
|
+
}
|
|
663
|
+
buildTask.done()
|
|
636
664
|
|
|
637
|
-
|
|
638
|
-
|
|
665
|
+
logger.debug(
|
|
666
|
+
`graph urls pre-versioning:
|
|
639
667
|
${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
668
|
+
)
|
|
669
|
+
if (versioning) {
|
|
670
|
+
await applyUrlVersioning({
|
|
671
|
+
buildOperation,
|
|
672
|
+
logger,
|
|
673
|
+
buildDirectoryUrl,
|
|
674
|
+
rawUrls,
|
|
675
|
+
buildUrls,
|
|
676
|
+
baseUrl,
|
|
677
|
+
postBuildEntryUrls,
|
|
678
|
+
sourcemaps,
|
|
679
|
+
runtimeCompat,
|
|
680
|
+
rawGraph,
|
|
681
|
+
finalGraph,
|
|
682
|
+
finalGraphKitchen,
|
|
683
|
+
lineBreakNormalization,
|
|
684
|
+
versioningMethod,
|
|
685
|
+
})
|
|
686
|
+
}
|
|
687
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
688
|
+
if (!urlInfo.url.startsWith("file:")) {
|
|
689
|
+
return
|
|
690
|
+
}
|
|
691
|
+
if (urlInfo.external) {
|
|
692
|
+
return
|
|
693
|
+
}
|
|
694
|
+
if (urlInfo.type === "html") {
|
|
695
|
+
const htmlAst = parseHtmlString(urlInfo.content, {
|
|
696
|
+
storeOriginalPositions: false,
|
|
697
|
+
})
|
|
698
|
+
urlInfo.content = stringifyHtmlAst(htmlAst, {
|
|
699
|
+
removeOriginalPositionAttributes: true,
|
|
700
|
+
})
|
|
701
|
+
}
|
|
702
|
+
const version = urlInfo.data.version
|
|
703
|
+
const useVersionedUrl = version && canUseVersionedUrl(urlInfo, finalGraph)
|
|
704
|
+
const buildUrl = useVersionedUrl ? urlInfo.data.versionedUrl : urlInfo.url
|
|
705
|
+
const buildUrlSpecifier = Object.keys(buildUrls).find(
|
|
706
|
+
(key) => buildUrls[key] === buildUrl,
|
|
707
|
+
)
|
|
708
|
+
urlInfo.data.buildUrl = buildUrl
|
|
709
|
+
urlInfo.data.buildUrlIsVersioned = useVersionedUrl
|
|
710
|
+
urlInfo.data.buildUrlSpecifier = buildUrlSpecifier
|
|
711
|
+
})
|
|
712
|
+
await resyncRessourceHints({
|
|
713
|
+
finalGraphKitchen,
|
|
714
|
+
finalGraph,
|
|
645
715
|
rawUrls,
|
|
646
716
|
buildUrls,
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
717
|
+
})
|
|
718
|
+
buildOperation.throwIfAborted()
|
|
719
|
+
const cleanupActions = []
|
|
720
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
721
|
+
// nothing uses this url anymore
|
|
722
|
+
// - versioning update inline content
|
|
723
|
+
// - file converted for import assertion of js_classic conversion
|
|
724
|
+
if (
|
|
725
|
+
!urlInfo.data.isEntryPoint &&
|
|
726
|
+
urlInfo.type !== "sourcemap" &&
|
|
727
|
+
urlInfo.dependents.size === 0
|
|
728
|
+
) {
|
|
729
|
+
cleanupActions.push(() => {
|
|
730
|
+
finalGraph.deleteUrlInfo(urlInfo.url)
|
|
731
|
+
})
|
|
732
|
+
}
|
|
733
|
+
})
|
|
734
|
+
cleanupActions.forEach((cleanupAction) => cleanupAction())
|
|
735
|
+
await injectServiceWorkerUrls({
|
|
653
736
|
finalGraphKitchen,
|
|
737
|
+
finalGraph,
|
|
654
738
|
lineBreakNormalization,
|
|
655
|
-
versioningMethod,
|
|
656
739
|
})
|
|
657
|
-
|
|
658
|
-
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
659
|
-
if (!urlInfo.url.startsWith("file:")) {
|
|
660
|
-
return
|
|
661
|
-
}
|
|
662
|
-
if (urlInfo.external) {
|
|
663
|
-
return
|
|
664
|
-
}
|
|
665
|
-
if (urlInfo.type === "html") {
|
|
666
|
-
const htmlAst = parseHtmlString(urlInfo.content, {
|
|
667
|
-
storeOriginalPositions: false,
|
|
668
|
-
})
|
|
669
|
-
urlInfo.content = stringifyHtmlAst(htmlAst, {
|
|
670
|
-
removeOriginalPositionAttributes: true,
|
|
671
|
-
})
|
|
672
|
-
}
|
|
673
|
-
const version = urlInfo.data.version
|
|
674
|
-
const useVersionedUrl = version && canUseVersionedUrl(urlInfo, finalGraph)
|
|
675
|
-
const buildUrl = useVersionedUrl ? urlInfo.data.versionedUrl : urlInfo.url
|
|
676
|
-
const buildUrlSpecifier = Object.keys(buildUrls).find(
|
|
677
|
-
(key) => buildUrls[key] === buildUrl,
|
|
678
|
-
)
|
|
679
|
-
urlInfo.data.buildUrl = buildUrl
|
|
680
|
-
urlInfo.data.buildUrlIsVersioned = useVersionedUrl
|
|
681
|
-
urlInfo.data.buildUrlSpecifier = buildUrlSpecifier
|
|
682
|
-
})
|
|
683
|
-
await resyncRessourceHints({
|
|
684
|
-
finalGraphKitchen,
|
|
685
|
-
finalGraph,
|
|
686
|
-
rawUrls,
|
|
687
|
-
buildUrls,
|
|
688
|
-
})
|
|
689
|
-
const cleanupActions = []
|
|
690
|
-
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
691
|
-
// nothing uses this url anymore
|
|
692
|
-
// - versioning update inline content
|
|
693
|
-
// - file converted for import assertion of js_classic conversion
|
|
694
|
-
if (
|
|
695
|
-
!urlInfo.data.isEntryPoint &&
|
|
696
|
-
urlInfo.type !== "sourcemap" &&
|
|
697
|
-
urlInfo.dependents.size === 0
|
|
698
|
-
) {
|
|
699
|
-
cleanupActions.push(() => {
|
|
700
|
-
finalGraph.deleteUrlInfo(urlInfo.url)
|
|
701
|
-
})
|
|
702
|
-
}
|
|
703
|
-
})
|
|
704
|
-
cleanupActions.forEach((cleanupAction) => cleanupAction())
|
|
705
|
-
await injectServiceWorkerUrls({
|
|
706
|
-
finalGraphKitchen,
|
|
707
|
-
finalGraph,
|
|
708
|
-
lineBreakNormalization,
|
|
709
|
-
})
|
|
710
|
-
logger.debug(
|
|
711
|
-
`graph urls post-versioning:
|
|
712
|
-
${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
713
|
-
)
|
|
740
|
+
buildOperation.throwIfAborted()
|
|
714
741
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
buildDirectoryUrl,
|
|
728
|
-
)
|
|
729
|
-
if (urlInfo.isInline) {
|
|
730
|
-
buildInlineContents[buildRelativeUrl] = urlInfo.content
|
|
731
|
-
} else {
|
|
732
|
-
buildFileContents[buildRelativeUrl] = urlInfo.content
|
|
733
|
-
const buildRelativeUrlWithoutVersioning = urlToRelativeUrl(
|
|
734
|
-
urlInfo.url,
|
|
742
|
+
const buildManifest = {}
|
|
743
|
+
const buildFileContents = {}
|
|
744
|
+
const buildInlineContents = {}
|
|
745
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
746
|
+
if (urlInfo.external) {
|
|
747
|
+
return
|
|
748
|
+
}
|
|
749
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
750
|
+
return
|
|
751
|
+
}
|
|
752
|
+
const buildRelativeUrl = urlToRelativeUrl(
|
|
753
|
+
urlInfo.data.buildUrl,
|
|
735
754
|
buildDirectoryUrl,
|
|
736
755
|
)
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
const buildRelativeUrls = Object.keys(buildFileContents)
|
|
745
|
-
await Promise.all(
|
|
746
|
-
buildRelativeUrls.map(async (buildRelativeUrl) => {
|
|
747
|
-
await writeFile(
|
|
748
|
-
new URL(buildRelativeUrl, buildDirectoryUrl),
|
|
749
|
-
buildFileContents[buildRelativeUrl],
|
|
756
|
+
if (urlInfo.isInline) {
|
|
757
|
+
buildInlineContents[buildRelativeUrl] = urlInfo.content
|
|
758
|
+
} else {
|
|
759
|
+
buildFileContents[buildRelativeUrl] = urlInfo.content
|
|
760
|
+
const buildRelativeUrlWithoutVersioning = urlToRelativeUrl(
|
|
761
|
+
urlInfo.url,
|
|
762
|
+
buildDirectoryUrl,
|
|
750
763
|
)
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
764
|
+
buildManifest[buildRelativeUrlWithoutVersioning] = buildRelativeUrl
|
|
765
|
+
}
|
|
766
|
+
})
|
|
767
|
+
if (writeOnFileSystem) {
|
|
768
|
+
if (buildDirectoryClean) {
|
|
769
|
+
await ensureEmptyDirectory(buildDirectoryUrl)
|
|
770
|
+
}
|
|
771
|
+
const buildRelativeUrls = Object.keys(buildFileContents)
|
|
772
|
+
await Promise.all(
|
|
773
|
+
buildRelativeUrls.map(async (buildRelativeUrl) => {
|
|
774
|
+
await writeFile(
|
|
775
|
+
new URL(buildRelativeUrl, buildDirectoryUrl),
|
|
776
|
+
buildFileContents[buildRelativeUrl],
|
|
777
|
+
)
|
|
778
|
+
}),
|
|
757
779
|
)
|
|
780
|
+
if (versioning && assetManifest && Object.keys(buildManifest).length) {
|
|
781
|
+
await writeFile(
|
|
782
|
+
new URL(assetManifestFileRelativeUrl, buildDirectoryUrl),
|
|
783
|
+
JSON.stringify(buildManifest, null, " "),
|
|
784
|
+
)
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
logger.info(createUrlGraphSummary(finalGraph, { title: "build files" }))
|
|
788
|
+
return {
|
|
789
|
+
buildFileContents,
|
|
790
|
+
buildInlineContents,
|
|
791
|
+
buildManifest,
|
|
758
792
|
}
|
|
759
793
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
buildInlineContents,
|
|
764
|
-
buildManifest,
|
|
794
|
+
|
|
795
|
+
if (!watch) {
|
|
796
|
+
return runBuild({ signal: operation.signal, logLevel })
|
|
765
797
|
}
|
|
798
|
+
|
|
799
|
+
let resolveFirstBuild
|
|
800
|
+
let rejectFirstBuild
|
|
801
|
+
const firstBuildPromise = new Promise((resolve, reject) => {
|
|
802
|
+
resolveFirstBuild = resolve
|
|
803
|
+
rejectFirstBuild = reject
|
|
804
|
+
})
|
|
805
|
+
const watchLogger = createLogger({ logLevel: "info" })
|
|
806
|
+
let buildAbortController
|
|
807
|
+
let watchFilesTask
|
|
808
|
+
const startBuild = async () => {
|
|
809
|
+
const buildTask = createTaskLog(watchLogger, "build")
|
|
810
|
+
buildAbortController = new AbortController()
|
|
811
|
+
try {
|
|
812
|
+
const result = await runBuild({
|
|
813
|
+
signal: buildAbortController.signal,
|
|
814
|
+
logLevel: "warn",
|
|
815
|
+
})
|
|
816
|
+
buildTask.done()
|
|
817
|
+
resolveFirstBuild(result)
|
|
818
|
+
watchFilesTask = createTaskLog(watchLogger, "watch files")
|
|
819
|
+
} catch (e) {
|
|
820
|
+
if (Abort.isAbortError(e)) {
|
|
821
|
+
buildTask.fail(`build aborted`)
|
|
822
|
+
} else if (e.code === "PARSE_ERROR") {
|
|
823
|
+
buildTask.fail()
|
|
824
|
+
watchLogger.error(e.stack)
|
|
825
|
+
watchFilesTask = createTaskLog(watchLogger, "watch files")
|
|
826
|
+
} else {
|
|
827
|
+
buildTask.fail()
|
|
828
|
+
rejectFirstBuild(e)
|
|
829
|
+
throw e
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
startBuild()
|
|
835
|
+
let startTimeout
|
|
836
|
+
const clientFileChangeCallback = ({ relativeUrl, event }) => {
|
|
837
|
+
const url = new URL(relativeUrl, rootDirectoryUrl).href
|
|
838
|
+
if (watchFilesTask) {
|
|
839
|
+
watchFilesTask.happen(`${url.slice(rootDirectoryUrl.length)} ${event}`)
|
|
840
|
+
watchFilesTask = null
|
|
841
|
+
}
|
|
842
|
+
buildAbortController.abort()
|
|
843
|
+
// setTimeout is to ensure the abortController.abort() above
|
|
844
|
+
// is properly taken into account so that logs about abort comes first
|
|
845
|
+
// then logs about re-running the build happens
|
|
846
|
+
clearTimeout(startTimeout)
|
|
847
|
+
startTimeout = setTimeout(startBuild, 20)
|
|
848
|
+
}
|
|
849
|
+
const stopWatchingClientFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
850
|
+
watchPatterns: clientFiles,
|
|
851
|
+
cooldownBetweenFileEvents,
|
|
852
|
+
keepProcessAlive: true,
|
|
853
|
+
recursive: true,
|
|
854
|
+
added: ({ relativeUrl }) => {
|
|
855
|
+
clientFileChangeCallback({ relativeUrl, event: "added" })
|
|
856
|
+
},
|
|
857
|
+
updated: ({ relativeUrl }) => {
|
|
858
|
+
clientFileChangeCallback({ relativeUrl, event: "modified" })
|
|
859
|
+
},
|
|
860
|
+
removed: ({ relativeUrl }) => {
|
|
861
|
+
clientFileChangeCallback({ relativeUrl, event: "removed" })
|
|
862
|
+
},
|
|
863
|
+
})
|
|
864
|
+
operation.addAbortCallback(() => {
|
|
865
|
+
stopWatchingClientFiles()
|
|
866
|
+
})
|
|
867
|
+
await firstBuildPromise
|
|
868
|
+
return stopWatchingClientFiles
|
|
766
869
|
}
|
|
767
870
|
|
|
768
871
|
const applyUrlVersioning = async ({
|
|
872
|
+
buildOperation,
|
|
769
873
|
logger,
|
|
770
874
|
buildDirectoryUrl,
|
|
771
875
|
rawUrls,
|
|
@@ -968,6 +1072,7 @@ const applyUrlVersioning = async ({
|
|
|
968
1072
|
],
|
|
969
1073
|
})
|
|
970
1074
|
await loadUrlGraph({
|
|
1075
|
+
operation: buildOperation,
|
|
971
1076
|
urlGraph: finalGraph,
|
|
972
1077
|
kitchen: versioningKitchen,
|
|
973
1078
|
skipRessourceHint: true,
|