@jsenv/core 27.0.0-alpha.30 → 27.0.0-alpha.33
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/package.json +1 -1
- package/src/build/build.js +287 -220
- package/src/build/build_urls_generator.js +12 -3
- package/src/build/start_build_server.js +1 -1
- package/src/plugins/bundling/js_module/bundle_js_module.js +13 -2
- package/src/plugins/transpilation/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +5 -6
package/package.json
CHANGED
package/src/build/build.js
CHANGED
|
@@ -46,19 +46,44 @@ import { injectGlobalVersionMapping } from "./inject_global_version_mappings.js"
|
|
|
46
46
|
import { injectServiceWorkerUrls } from "./inject_service_worker_urls.js"
|
|
47
47
|
import { resyncRessourceHints } from "./resync_ressource_hints.js"
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Generate an optimized version of source files into a directory
|
|
51
|
+
* @param {Object} buildParameters
|
|
52
|
+
* @param {string|url} buildParameters.rootDirectoryUrl
|
|
53
|
+
* Directory containing source files
|
|
54
|
+
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
55
|
+
* Directory where optimized files will be written
|
|
56
|
+
* @param {object} buildParameters.entryPoints
|
|
57
|
+
* Describe entry point paths and control their names in the build directory
|
|
58
|
+
* @param {object} buildParameters.runtimeCompat
|
|
59
|
+
* Code generated will be compatible with these runtimes
|
|
60
|
+
* @param {string="/"} buildParameters.baseUrl
|
|
61
|
+
* All urls in build file contents are prefixed with this url
|
|
62
|
+
* @param {boolean|object} [buildParameters.minification=true]
|
|
63
|
+
* Minify build file contents
|
|
64
|
+
* @param {boolean} [buildParameters.versioning=true]
|
|
65
|
+
* Controls if url in build file contents are versioned
|
|
66
|
+
* @param {('search_param'|'filename')} [buildParameters.versioningMethod="search_param"]
|
|
67
|
+
* Controls how url are versioned
|
|
68
|
+
* @param {boolean|string} [buildParameters.sourcemaps=false]
|
|
69
|
+
* Generate sourcemaps in the build directory
|
|
70
|
+
* @return {Object} buildReturnValue
|
|
71
|
+
* @return {Object} buildReturnValue.buildFileContents
|
|
72
|
+
* Contains all build file paths relative to the build directory and their content
|
|
73
|
+
* @return {Object} buildReturnValue.buildInlineContents
|
|
74
|
+
* Contains content that is inline into build files
|
|
75
|
+
* @return {Object} buildReturnValue.buildManifest
|
|
76
|
+
* Map build file paths without versioning to versioned file paths
|
|
77
|
+
*/
|
|
49
78
|
export const build = async ({
|
|
50
79
|
signal = new AbortController().signal,
|
|
51
80
|
logLevel = "info",
|
|
52
81
|
rootDirectoryUrl,
|
|
53
82
|
buildDirectoryUrl,
|
|
54
83
|
entryPoints = {},
|
|
55
|
-
// for now it's here but I think preview will become an other script
|
|
56
|
-
// that will just pass different options to build project
|
|
57
|
-
// and this function will be agnostic about "preview" concept
|
|
58
|
-
isPreview = false,
|
|
59
84
|
|
|
60
85
|
plugins = [],
|
|
61
|
-
sourcemaps =
|
|
86
|
+
sourcemaps = false,
|
|
62
87
|
nodeEsmResolution,
|
|
63
88
|
fileSystemMagicResolution,
|
|
64
89
|
injectedGlobals,
|
|
@@ -142,6 +167,7 @@ build ${entryPointKeys.length} entry points`)
|
|
|
142
167
|
specifier: key,
|
|
143
168
|
})
|
|
144
169
|
entryUrls.push(entryUrlInfo.url)
|
|
170
|
+
entryUrlInfo.filename = entryPoints[key]
|
|
145
171
|
})
|
|
146
172
|
},
|
|
147
173
|
})
|
|
@@ -234,6 +260,7 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
234
260
|
})
|
|
235
261
|
}
|
|
236
262
|
})
|
|
263
|
+
const bundleUrlRedirections = {}
|
|
237
264
|
await Object.keys(bundlers).reduce(async (previous, type) => {
|
|
238
265
|
await previous
|
|
239
266
|
const bundler = bundlers[type]
|
|
@@ -276,6 +303,13 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
276
303
|
rawUrlRedirections[url] = buildUrl
|
|
277
304
|
rawUrls[buildUrl] = url
|
|
278
305
|
bundleUrlInfos[buildUrl] = bundleUrlInfo
|
|
306
|
+
if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
|
|
307
|
+
const urlForBundler = new URL(
|
|
308
|
+
bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
|
|
309
|
+
buildDirectoryUrl,
|
|
310
|
+
).href
|
|
311
|
+
bundleUrlRedirections[urlForBundler] = buildUrl
|
|
312
|
+
}
|
|
279
313
|
})
|
|
280
314
|
} catch (e) {
|
|
281
315
|
bundleTask.fail()
|
|
@@ -313,6 +347,10 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
313
347
|
reference.specifier[0] === "/"
|
|
314
348
|
? new URL(reference.specifier.slice(1), buildDirectoryUrl).href
|
|
315
349
|
: new URL(reference.specifier, reference.parentUrl).href
|
|
350
|
+
const urlRedirectedByBundle = bundleUrlRedirections[url]
|
|
351
|
+
if (urlRedirectedByBundle) {
|
|
352
|
+
return urlRedirectedByBundle
|
|
353
|
+
}
|
|
316
354
|
const parentIsFromBundle = Boolean(
|
|
317
355
|
bundleUrlInfos[reference.parentUrl],
|
|
318
356
|
)
|
|
@@ -579,220 +617,22 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
579
617
|
${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
580
618
|
)
|
|
581
619
|
if (versioning) {
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
// we don't know their content
|
|
598
|
-
// - unused files without reference
|
|
599
|
-
// File updated such as style.css -> style.css.js or file.js->file.es5.js
|
|
600
|
-
// Are used at some point just to be discarded later because they need to be converted
|
|
601
|
-
// There is no need to version them and we could not because the file have been ignored
|
|
602
|
-
// so their content is unknown
|
|
603
|
-
if (urlInfo.isInline) {
|
|
604
|
-
return
|
|
605
|
-
}
|
|
606
|
-
if (urlInfo.external) {
|
|
607
|
-
return
|
|
608
|
-
}
|
|
609
|
-
if (!urlInfo.data.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
610
|
-
return
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
const urlContent =
|
|
614
|
-
urlInfo.type === "html"
|
|
615
|
-
? stringifyHtmlAst(
|
|
616
|
-
parseHtmlString(urlInfo.content, {
|
|
617
|
-
storeOriginalPositions: false,
|
|
618
|
-
}),
|
|
619
|
-
{ removeOriginalPositionAttributes: true },
|
|
620
|
-
)
|
|
621
|
-
: urlInfo.content
|
|
622
|
-
const versionGenerator = createVersionGenerator()
|
|
623
|
-
versionGenerator.augmentWithContent({
|
|
624
|
-
content: urlContent,
|
|
625
|
-
contentType: urlInfo.contentType,
|
|
626
|
-
lineBreakNormalization,
|
|
627
|
-
})
|
|
628
|
-
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
629
|
-
// this dependency is inline (data:) or remote (http://, https://)
|
|
630
|
-
if (!dependencyUrl.startsWith("file:")) {
|
|
631
|
-
return
|
|
632
|
-
}
|
|
633
|
-
const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
|
|
634
|
-
if (
|
|
635
|
-
// this content is part of the file, no need to take into account twice
|
|
636
|
-
dependencyUrlInfo.isInline ||
|
|
637
|
-
// this dependency content is not known
|
|
638
|
-
dependencyUrlInfo.external
|
|
639
|
-
) {
|
|
640
|
-
return
|
|
641
|
-
}
|
|
642
|
-
if (dependencyUrlInfo.data.version) {
|
|
643
|
-
versionGenerator.augmentWithDependencyVersion(
|
|
644
|
-
dependencyUrlInfo.data.version,
|
|
645
|
-
)
|
|
646
|
-
} else {
|
|
647
|
-
// because all dependencies are know, if the dependency has no version
|
|
648
|
-
// it means there is a circular dependency between this file
|
|
649
|
-
// and it's dependency
|
|
650
|
-
// in that case we'll use the dependency content
|
|
651
|
-
versionGenerator.augmentWithContent({
|
|
652
|
-
content: dependencyUrlInfo.content,
|
|
653
|
-
contentType: dependencyUrlInfo.contentType,
|
|
654
|
-
lineBreakNormalization,
|
|
655
|
-
})
|
|
656
|
-
}
|
|
657
|
-
})
|
|
658
|
-
urlInfo.data.version = versionGenerator.generate()
|
|
659
|
-
|
|
660
|
-
urlInfo.data.versionedUrl = injectVersionIntoBuildUrl({
|
|
661
|
-
buildUrl: urlInfo.url,
|
|
662
|
-
version: urlInfo.data.version,
|
|
663
|
-
versioningMethod,
|
|
664
|
-
})
|
|
665
|
-
})
|
|
666
|
-
const versionMappings = {}
|
|
667
|
-
const usedVersionMappings = []
|
|
668
|
-
const versioningKitchen = createKitchen({
|
|
669
|
-
logger,
|
|
670
|
-
rootDirectoryUrl: buildDirectoryUrl,
|
|
671
|
-
urlGraph: finalGraph,
|
|
672
|
-
scenario: "build",
|
|
673
|
-
sourcemaps,
|
|
674
|
-
runtimeCompat,
|
|
675
|
-
plugins: [
|
|
676
|
-
jsenvPluginInline({
|
|
677
|
-
fetchInlineUrls: false,
|
|
678
|
-
analyzeConvertedScripts: true, // to be able to version their urls
|
|
679
|
-
allowEscapeForVersioning: true,
|
|
680
|
-
}),
|
|
681
|
-
{
|
|
682
|
-
name: "jsenv:versioning",
|
|
683
|
-
appliesDuring: { build: true },
|
|
684
|
-
resolveUrl: (reference) => {
|
|
685
|
-
if (reference.specifier[0] === "#") {
|
|
686
|
-
reference.external = true
|
|
687
|
-
}
|
|
688
|
-
const buildUrl = buildUrls[reference.specifier]
|
|
689
|
-
if (buildUrl) {
|
|
690
|
-
return buildUrl
|
|
691
|
-
}
|
|
692
|
-
const url = new URL(reference.specifier, reference.parentUrl).href
|
|
693
|
-
return url
|
|
694
|
-
},
|
|
695
|
-
formatUrl: (reference) => {
|
|
696
|
-
if (reference.isInline) {
|
|
697
|
-
return null
|
|
698
|
-
}
|
|
699
|
-
// specifier comes from "normalize" hook done a bit earlier in this file
|
|
700
|
-
// we want to get back their build url to access their infos
|
|
701
|
-
const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
|
|
702
|
-
if (!canUseVersionedUrl(referencedUrlInfo)) {
|
|
703
|
-
return reference.specifier
|
|
704
|
-
}
|
|
705
|
-
// data:* urls and so on
|
|
706
|
-
if (!referencedUrlInfo.url.startsWith("file:")) {
|
|
707
|
-
return null
|
|
708
|
-
}
|
|
709
|
-
const versionedUrl = referencedUrlInfo.data.versionedUrl
|
|
710
|
-
if (!versionedUrl) {
|
|
711
|
-
// happens for sourcemap
|
|
712
|
-
return `${baseUrl}${urlToRelativeUrl(
|
|
713
|
-
referencedUrlInfo.url,
|
|
714
|
-
buildDirectoryUrl,
|
|
715
|
-
)}`
|
|
716
|
-
}
|
|
717
|
-
const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
|
|
718
|
-
versionedUrl,
|
|
719
|
-
buildDirectoryUrl,
|
|
720
|
-
)}`
|
|
721
|
-
versionMappings[reference.specifier] = versionedSpecifier
|
|
722
|
-
buildUrls[versionedSpecifier] = versionedUrl
|
|
723
|
-
|
|
724
|
-
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
725
|
-
if (parentUrlInfo.jsQuote) {
|
|
726
|
-
// the url is inline inside js quotes
|
|
727
|
-
usedVersionMappings.push(reference.specifier)
|
|
728
|
-
return () =>
|
|
729
|
-
`${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
|
|
730
|
-
reference.specifier,
|
|
731
|
-
)})+${parentUrlInfo.jsQuote}`
|
|
732
|
-
}
|
|
733
|
-
if (
|
|
734
|
-
reference.type === "js_url_specifier" ||
|
|
735
|
-
reference.subtype === "import_dynamic"
|
|
736
|
-
) {
|
|
737
|
-
usedVersionMappings.push(reference.specifier)
|
|
738
|
-
return () => `__v__(${JSON.stringify(reference.specifier)})`
|
|
739
|
-
}
|
|
740
|
-
return versionedSpecifier
|
|
741
|
-
},
|
|
742
|
-
fetchUrlContent: (versionedUrlInfo) => {
|
|
743
|
-
if (!versionedUrlInfo.url.startsWith("file:")) {
|
|
744
|
-
return { external: true }
|
|
745
|
-
}
|
|
746
|
-
if (versionedUrlInfo.isInline) {
|
|
747
|
-
const rawUrlInfo = rawGraph.getUrlInfo(
|
|
748
|
-
rawUrls[versionedUrlInfo.url],
|
|
749
|
-
)
|
|
750
|
-
const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
|
|
751
|
-
return {
|
|
752
|
-
originalContent: rawUrlInfo
|
|
753
|
-
? rawUrlInfo.originalContent
|
|
754
|
-
: undefined,
|
|
755
|
-
sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
|
|
756
|
-
contentType: versionedUrlInfo.contentType,
|
|
757
|
-
content: versionedUrlInfo.content,
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
return versionedUrlInfo
|
|
761
|
-
},
|
|
762
|
-
},
|
|
763
|
-
],
|
|
764
|
-
})
|
|
765
|
-
await loadUrlGraph({
|
|
766
|
-
urlGraph: finalGraph,
|
|
767
|
-
kitchen: versioningKitchen,
|
|
768
|
-
startLoading: (cookEntryFile) => {
|
|
769
|
-
postBuildEntryUrls.forEach((postBuildEntryUrl) => {
|
|
770
|
-
cookEntryFile({
|
|
771
|
-
trace: `entryPoint`,
|
|
772
|
-
type: "entry_point",
|
|
773
|
-
specifier: postBuildEntryUrl,
|
|
774
|
-
})
|
|
775
|
-
})
|
|
776
|
-
},
|
|
777
|
-
})
|
|
778
|
-
if (usedVersionMappings.length) {
|
|
779
|
-
const versionMappingsNeeded = {}
|
|
780
|
-
usedVersionMappings.forEach((specifier) => {
|
|
781
|
-
versionMappingsNeeded[specifier] = versionMappings[specifier]
|
|
782
|
-
})
|
|
783
|
-
await injectGlobalVersionMapping({
|
|
784
|
-
finalGraphKitchen,
|
|
785
|
-
finalGraph,
|
|
786
|
-
versionMappings: versionMappingsNeeded,
|
|
787
|
-
})
|
|
788
|
-
}
|
|
789
|
-
} catch (e) {
|
|
790
|
-
versioningTask.fail()
|
|
791
|
-
throw e
|
|
792
|
-
}
|
|
793
|
-
versioningTask.done()
|
|
620
|
+
await applyUrlVersioning({
|
|
621
|
+
logger,
|
|
622
|
+
buildDirectoryUrl,
|
|
623
|
+
rawUrls,
|
|
624
|
+
buildUrls,
|
|
625
|
+
baseUrl,
|
|
626
|
+
postBuildEntryUrls,
|
|
627
|
+
sourcemaps,
|
|
628
|
+
runtimeCompat,
|
|
629
|
+
rawGraph,
|
|
630
|
+
finalGraph,
|
|
631
|
+
finalGraphKitchen,
|
|
632
|
+
lineBreakNormalization,
|
|
633
|
+
versioningMethod,
|
|
634
|
+
})
|
|
794
635
|
}
|
|
795
|
-
|
|
796
636
|
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
797
637
|
if (!urlInfo.url.startsWith("file:")) {
|
|
798
638
|
return
|
|
@@ -818,7 +658,6 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
818
658
|
urlInfo.data.buildUrlIsVersioned = useVersionedUrl
|
|
819
659
|
urlInfo.data.buildUrlSpecifier = buildUrlSpecifier
|
|
820
660
|
})
|
|
821
|
-
|
|
822
661
|
await resyncRessourceHints({
|
|
823
662
|
finalGraphKitchen,
|
|
824
663
|
finalGraph,
|
|
@@ -846,7 +685,6 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
846
685
|
finalGraph,
|
|
847
686
|
lineBreakNormalization,
|
|
848
687
|
})
|
|
849
|
-
|
|
850
688
|
logger.debug(
|
|
851
689
|
`graph urls post-versioning:
|
|
852
690
|
${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
@@ -905,6 +743,235 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
905
743
|
}
|
|
906
744
|
}
|
|
907
745
|
|
|
746
|
+
const applyUrlVersioning = async ({
|
|
747
|
+
logger,
|
|
748
|
+
buildDirectoryUrl,
|
|
749
|
+
rawUrls,
|
|
750
|
+
buildUrls,
|
|
751
|
+
baseUrl,
|
|
752
|
+
postBuildEntryUrls,
|
|
753
|
+
sourcemaps,
|
|
754
|
+
runtimeCompat,
|
|
755
|
+
rawGraph,
|
|
756
|
+
finalGraph,
|
|
757
|
+
finalGraphKitchen,
|
|
758
|
+
lineBreakNormalization,
|
|
759
|
+
versioningMethod,
|
|
760
|
+
}) => {
|
|
761
|
+
const versioningTask = createTaskLog(logger, "inject version in urls")
|
|
762
|
+
try {
|
|
763
|
+
const urlsSorted = sortUrlGraphByDependencies(finalGraph)
|
|
764
|
+
urlsSorted.forEach((url) => {
|
|
765
|
+
if (url.startsWith("data:")) {
|
|
766
|
+
return
|
|
767
|
+
}
|
|
768
|
+
const urlInfo = finalGraph.getUrlInfo(url)
|
|
769
|
+
if (urlInfo.type === "sourcemap") {
|
|
770
|
+
return
|
|
771
|
+
}
|
|
772
|
+
// ignore:
|
|
773
|
+
// - inline files:
|
|
774
|
+
// they are already taken into account in the file where they appear
|
|
775
|
+
// - external files
|
|
776
|
+
// we don't know their content
|
|
777
|
+
// - unused files without reference
|
|
778
|
+
// File updated such as style.css -> style.css.js or file.js->file.es5.js
|
|
779
|
+
// Are used at some point just to be discarded later because they need to be converted
|
|
780
|
+
// There is no need to version them and we could not because the file have been ignored
|
|
781
|
+
// so their content is unknown
|
|
782
|
+
if (urlInfo.isInline) {
|
|
783
|
+
return
|
|
784
|
+
}
|
|
785
|
+
if (urlInfo.external) {
|
|
786
|
+
return
|
|
787
|
+
}
|
|
788
|
+
if (!urlInfo.data.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
789
|
+
return
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
const urlContent =
|
|
793
|
+
urlInfo.type === "html"
|
|
794
|
+
? stringifyHtmlAst(
|
|
795
|
+
parseHtmlString(urlInfo.content, {
|
|
796
|
+
storeOriginalPositions: false,
|
|
797
|
+
}),
|
|
798
|
+
{ removeOriginalPositionAttributes: true },
|
|
799
|
+
)
|
|
800
|
+
: urlInfo.content
|
|
801
|
+
const versionGenerator = createVersionGenerator()
|
|
802
|
+
versionGenerator.augmentWithContent({
|
|
803
|
+
content: urlContent,
|
|
804
|
+
contentType: urlInfo.contentType,
|
|
805
|
+
lineBreakNormalization,
|
|
806
|
+
})
|
|
807
|
+
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
808
|
+
// this dependency is inline (data:) or remote (http://, https://)
|
|
809
|
+
if (!dependencyUrl.startsWith("file:")) {
|
|
810
|
+
return
|
|
811
|
+
}
|
|
812
|
+
const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
|
|
813
|
+
if (
|
|
814
|
+
// this content is part of the file, no need to take into account twice
|
|
815
|
+
dependencyUrlInfo.isInline ||
|
|
816
|
+
// this dependency content is not known
|
|
817
|
+
dependencyUrlInfo.external
|
|
818
|
+
) {
|
|
819
|
+
return
|
|
820
|
+
}
|
|
821
|
+
if (dependencyUrlInfo.data.version) {
|
|
822
|
+
versionGenerator.augmentWithDependencyVersion(
|
|
823
|
+
dependencyUrlInfo.data.version,
|
|
824
|
+
)
|
|
825
|
+
} else {
|
|
826
|
+
// because all dependencies are know, if the dependency has no version
|
|
827
|
+
// it means there is a circular dependency between this file
|
|
828
|
+
// and it's dependency
|
|
829
|
+
// in that case we'll use the dependency content
|
|
830
|
+
versionGenerator.augmentWithContent({
|
|
831
|
+
content: dependencyUrlInfo.content,
|
|
832
|
+
contentType: dependencyUrlInfo.contentType,
|
|
833
|
+
lineBreakNormalization,
|
|
834
|
+
})
|
|
835
|
+
}
|
|
836
|
+
})
|
|
837
|
+
urlInfo.data.version = versionGenerator.generate()
|
|
838
|
+
|
|
839
|
+
urlInfo.data.versionedUrl = injectVersionIntoBuildUrl({
|
|
840
|
+
buildUrl: urlInfo.url,
|
|
841
|
+
version: urlInfo.data.version,
|
|
842
|
+
versioningMethod,
|
|
843
|
+
})
|
|
844
|
+
})
|
|
845
|
+
const versionMappings = {}
|
|
846
|
+
const usedVersionMappings = []
|
|
847
|
+
const versioningKitchen = createKitchen({
|
|
848
|
+
logger,
|
|
849
|
+
rootDirectoryUrl: buildDirectoryUrl,
|
|
850
|
+
urlGraph: finalGraph,
|
|
851
|
+
scenario: "build",
|
|
852
|
+
sourcemaps,
|
|
853
|
+
runtimeCompat,
|
|
854
|
+
plugins: [
|
|
855
|
+
jsenvPluginInline({
|
|
856
|
+
fetchInlineUrls: false,
|
|
857
|
+
analyzeConvertedScripts: true, // to be able to version their urls
|
|
858
|
+
allowEscapeForVersioning: true,
|
|
859
|
+
}),
|
|
860
|
+
{
|
|
861
|
+
name: "jsenv:versioning",
|
|
862
|
+
appliesDuring: { build: true },
|
|
863
|
+
resolveUrl: (reference) => {
|
|
864
|
+
if (reference.specifier[0] === "#") {
|
|
865
|
+
reference.external = true
|
|
866
|
+
}
|
|
867
|
+
const buildUrl = buildUrls[reference.specifier]
|
|
868
|
+
if (buildUrl) {
|
|
869
|
+
return buildUrl
|
|
870
|
+
}
|
|
871
|
+
const url = new URL(reference.specifier, reference.parentUrl).href
|
|
872
|
+
return url
|
|
873
|
+
},
|
|
874
|
+
formatUrl: (reference) => {
|
|
875
|
+
if (reference.isInline) {
|
|
876
|
+
return null
|
|
877
|
+
}
|
|
878
|
+
// specifier comes from "normalize" hook done a bit earlier in this file
|
|
879
|
+
// we want to get back their build url to access their infos
|
|
880
|
+
const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
|
|
881
|
+
if (!canUseVersionedUrl(referencedUrlInfo)) {
|
|
882
|
+
return reference.specifier
|
|
883
|
+
}
|
|
884
|
+
// data:* urls and so on
|
|
885
|
+
if (!referencedUrlInfo.url.startsWith("file:")) {
|
|
886
|
+
return null
|
|
887
|
+
}
|
|
888
|
+
const versionedUrl = referencedUrlInfo.data.versionedUrl
|
|
889
|
+
if (!versionedUrl) {
|
|
890
|
+
// happens for sourcemap
|
|
891
|
+
return `${baseUrl}${urlToRelativeUrl(
|
|
892
|
+
referencedUrlInfo.url,
|
|
893
|
+
buildDirectoryUrl,
|
|
894
|
+
)}`
|
|
895
|
+
}
|
|
896
|
+
const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
|
|
897
|
+
versionedUrl,
|
|
898
|
+
buildDirectoryUrl,
|
|
899
|
+
)}`
|
|
900
|
+
versionMappings[reference.specifier] = versionedSpecifier
|
|
901
|
+
buildUrls[versionedSpecifier] = versionedUrl
|
|
902
|
+
|
|
903
|
+
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
904
|
+
if (parentUrlInfo.jsQuote) {
|
|
905
|
+
// the url is inline inside js quotes
|
|
906
|
+
usedVersionMappings.push(reference.specifier)
|
|
907
|
+
return () =>
|
|
908
|
+
`${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
|
|
909
|
+
reference.specifier,
|
|
910
|
+
)})+${parentUrlInfo.jsQuote}`
|
|
911
|
+
}
|
|
912
|
+
if (
|
|
913
|
+
reference.type === "js_url_specifier" ||
|
|
914
|
+
reference.subtype === "import_dynamic"
|
|
915
|
+
) {
|
|
916
|
+
usedVersionMappings.push(reference.specifier)
|
|
917
|
+
return () => `__v__(${JSON.stringify(reference.specifier)})`
|
|
918
|
+
}
|
|
919
|
+
return versionedSpecifier
|
|
920
|
+
},
|
|
921
|
+
fetchUrlContent: (versionedUrlInfo) => {
|
|
922
|
+
if (!versionedUrlInfo.url.startsWith("file:")) {
|
|
923
|
+
return { external: true }
|
|
924
|
+
}
|
|
925
|
+
if (versionedUrlInfo.isInline) {
|
|
926
|
+
const rawUrlInfo = rawGraph.getUrlInfo(
|
|
927
|
+
rawUrls[versionedUrlInfo.url],
|
|
928
|
+
)
|
|
929
|
+
const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
|
|
930
|
+
return {
|
|
931
|
+
originalContent: rawUrlInfo
|
|
932
|
+
? rawUrlInfo.originalContent
|
|
933
|
+
: undefined,
|
|
934
|
+
sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
|
|
935
|
+
contentType: versionedUrlInfo.contentType,
|
|
936
|
+
content: versionedUrlInfo.content,
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return versionedUrlInfo
|
|
940
|
+
},
|
|
941
|
+
},
|
|
942
|
+
],
|
|
943
|
+
})
|
|
944
|
+
await loadUrlGraph({
|
|
945
|
+
urlGraph: finalGraph,
|
|
946
|
+
kitchen: versioningKitchen,
|
|
947
|
+
startLoading: (cookEntryFile) => {
|
|
948
|
+
postBuildEntryUrls.forEach((postBuildEntryUrl) => {
|
|
949
|
+
cookEntryFile({
|
|
950
|
+
trace: `entryPoint`,
|
|
951
|
+
type: "entry_point",
|
|
952
|
+
specifier: postBuildEntryUrl,
|
|
953
|
+
})
|
|
954
|
+
})
|
|
955
|
+
},
|
|
956
|
+
})
|
|
957
|
+
if (usedVersionMappings.length) {
|
|
958
|
+
const versionMappingsNeeded = {}
|
|
959
|
+
usedVersionMappings.forEach((specifier) => {
|
|
960
|
+
versionMappingsNeeded[specifier] = versionMappings[specifier]
|
|
961
|
+
})
|
|
962
|
+
await injectGlobalVersionMapping({
|
|
963
|
+
finalGraphKitchen,
|
|
964
|
+
finalGraph,
|
|
965
|
+
versionMappings: versionMappingsNeeded,
|
|
966
|
+
})
|
|
967
|
+
}
|
|
968
|
+
} catch (e) {
|
|
969
|
+
versioningTask.fail()
|
|
970
|
+
throw e
|
|
971
|
+
}
|
|
972
|
+
versioningTask.done()
|
|
973
|
+
}
|
|
974
|
+
|
|
908
975
|
const injectVersionIntoBuildUrl = ({ buildUrl, version, versioningMethod }) => {
|
|
909
976
|
if (versioningMethod === "search_param") {
|
|
910
977
|
return injectQueryParams(buildUrl, {
|
|
@@ -4,6 +4,17 @@ import { memoizeByUrl } from "@jsenv/utils/memoize/memoize_by_url.js"
|
|
|
4
4
|
|
|
5
5
|
export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
6
6
|
const cache = {}
|
|
7
|
+
|
|
8
|
+
const getUrlName = (url, urlInfo) => {
|
|
9
|
+
if (!urlInfo) {
|
|
10
|
+
return urlToFilename(url)
|
|
11
|
+
}
|
|
12
|
+
if (urlInfo.filename) {
|
|
13
|
+
return urlInfo.filename
|
|
14
|
+
}
|
|
15
|
+
return urlToFilename(url)
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
const generate = memoizeByUrl((url, { urlInfo, parentUrlInfo }) => {
|
|
8
19
|
const directoryPath = determineDirectoryPath({
|
|
9
20
|
urlInfo,
|
|
@@ -16,9 +27,7 @@ export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
|
16
27
|
}
|
|
17
28
|
const urlObject = new URL(url)
|
|
18
29
|
let { search, hash } = urlObject
|
|
19
|
-
let name = urlInfo
|
|
20
|
-
? urlInfo.filename || urlToFilename(url)
|
|
21
|
-
: urlToFilename(url)
|
|
30
|
+
let name = getUrlName(url, urlInfo)
|
|
22
31
|
const [basename, extension] = splitFileExtension(name)
|
|
23
32
|
let nameCandidate = name
|
|
24
33
|
let integer = 1
|
|
@@ -132,9 +132,9 @@ const rollupPluginJsenv = ({
|
|
|
132
132
|
// there is 3 types of file: "placeholder", "asset", "chunk"
|
|
133
133
|
if (rollupFileInfo.type === "chunk") {
|
|
134
134
|
const jsModuleBundleUrlInfo = {
|
|
135
|
-
// buildRelativeUrl: rollupFileInfo.fileName,
|
|
136
135
|
data: {
|
|
137
136
|
generatedBy: "rollup",
|
|
137
|
+
bundleRelativeUrl: rollupFileInfo.fileName,
|
|
138
138
|
usesImport:
|
|
139
139
|
rollupFileInfo.imports.length > 0 ||
|
|
140
140
|
rollupFileInfo.dynamicImports.length > 0,
|
|
@@ -176,7 +176,18 @@ const rollupPluginJsenv = ({
|
|
|
176
176
|
fileUrlConverter,
|
|
177
177
|
jsModuleUrlInfos,
|
|
178
178
|
})
|
|
179
|
-
|
|
179
|
+
let nameFromUrlInfo
|
|
180
|
+
if (chunkInfo.facadeModuleId) {
|
|
181
|
+
const url = fileUrlConverter.asFileUrl(chunkInfo.facadeModuleId)
|
|
182
|
+
const urlInfo = jsModuleUrlInfos.find(
|
|
183
|
+
(jsModuleUrlInfo) => jsModuleUrlInfo.url === url,
|
|
184
|
+
)
|
|
185
|
+
if (urlInfo) {
|
|
186
|
+
nameFromUrlInfo = urlInfo.filename
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const name = nameFromUrlInfo || `${chunkInfo.name}.js`
|
|
190
|
+
return insideJs ? `js/${name}` : `${name}`
|
|
180
191
|
},
|
|
181
192
|
// https://rollupjs.org/guide/en/#outputpaths
|
|
182
193
|
// paths: (id) => {
|
|
@@ -105,13 +105,12 @@ const isNewCssStyleSheetCall = (node) => {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
const isDocumentAdoptedStyleSheets = (node) => {
|
|
108
|
-
const callee = node.callee
|
|
109
108
|
return (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
node.type === "MemberExpression" &&
|
|
110
|
+
node.object.type === "Identifier" &&
|
|
111
|
+
node.object.name === "document" &&
|
|
112
|
+
node.property.type === "Identifier" &&
|
|
113
|
+
node.property.name === "adoptedStyleSheets"
|
|
115
114
|
)
|
|
116
115
|
}
|
|
117
116
|
|