@jsenv/core 27.0.0-alpha.4 → 27.0.0-alpha.40
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/dist/event_source_client.js +549 -0
- package/dist/event_source_client.js.map +188 -0
- package/dist/html_supervisor_installer.js +1145 -0
- package/dist/html_supervisor_installer.js.map +322 -0
- package/dist/html_supervisor_setup.js +92 -0
- package/dist/html_supervisor_setup.js.map +57 -0
- package/main.js +8 -1
- package/package.json +22 -21
- package/readme.md +4 -12
- package/src/build/build.js +731 -433
- package/src/build/build_urls_generator.js +55 -21
- package/src/build/graph_utils.js +31 -0
- package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
- package/src/build/inject_service_worker_urls.js +79 -0
- package/src/build/resync_ressource_hints.js +68 -0
- package/src/build/start_build_server.js +205 -0
- package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
- package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
- package/src/dev/start_dev_server.js +58 -26
- package/src/execute/execute.js +30 -4
- package/src/execute/run.js +19 -56
- package/src/execute/runtimes/browsers/from_playwright.js +201 -147
- package/src/execute/runtimes/node/controllable_file.mjs +26 -10
- package/src/execute/runtimes/node/node_execution_performance.js +67 -0
- package/src/execute/runtimes/node/node_process.js +280 -39
- package/src/jsenv_root_directory_url.js +1 -0
- package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
- package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
- package/src/omega/compat/runtime_compat.js +50 -0
- package/src/omega/errors.js +51 -58
- package/src/omega/fetched_content_compliance.js +24 -0
- package/src/omega/file_url_converter.js +8 -50
- package/src/omega/kitchen.js +414 -285
- package/src/omega/server/file_service.js +21 -22
- package/src/omega/url_graph/url_graph_load.js +14 -7
- package/src/omega/url_graph/url_graph_report.js +17 -15
- package/src/omega/url_graph/url_info_transformations.js +17 -5
- package/src/omega/url_graph.js +33 -10
- package/src/omega/web_workers.js +42 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
- package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +46 -0
- package/src/{dev/plugins/autoreload/jsenv_plugin_autoreload.js → plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js} +31 -172
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +27 -0
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
- package/src/plugins/bundling/css/bundle_css.js +21 -0
- package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
- package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +120 -79
- package/src/plugins/bundling/jsenv_plugin_bundling.js +51 -0
- package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +54 -41
- package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
- package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +8 -5
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_installer.js +3 -2
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_setup.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
- package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +52 -55
- package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
- package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +101 -0
- package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +33 -8
- package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
- package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
- package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +37 -31
- package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +67 -0
- package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
- package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
- package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +61 -40
- package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
- package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
- package/src/plugins/inline/jsenv_plugin_js_inline_content.js +296 -0
- package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
- package/src/plugins/minification/css/minify_css.js +9 -0
- package/src/plugins/minification/html/minify_html.js +15 -0
- package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
- package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
- package/src/plugins/minification/json/minify_json.js +8 -0
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +146 -0
- package/src/{omega → plugins}/plugin_controller.js +39 -11
- package/src/plugins/plugins.js +89 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
- package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
- package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
- package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +93 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_babel_helpers_as_jsenv_imports.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugin_structure.js +4 -22
- package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +37 -21
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
- package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
- package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
- package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +200 -0
- package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +70 -0
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
- package/src/plugins/url_references/css/css_urls.js +49 -0
- package/src/plugins/url_references/html/html_urls.js +273 -0
- package/src/plugins/url_references/js/js_urls.js +43 -0
- package/src/plugins/url_references/jsenv_plugin_imports_analysis.js +46 -0
- package/src/plugins/url_references/jsenv_plugin_url_analysis.js +18 -0
- package/src/plugins/url_references/jsenv_plugin_url_references.js +6 -0
- package/src/plugins/url_references/webmanifest/webmanifest_urls.js +17 -0
- package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
- package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +12 -15
- package/src/test/execute_plan.js +28 -11
- package/src/test/execute_test_plan.js +23 -8
- package/src/test/logs_file_execution.js +8 -7
- package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
- package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
- package/src/dev/plugins/autoreload/sse_service.js +0 -149
- package/src/execute/runtimes/node/controlled_process.js +0 -316
- package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
- package/src/omega/core_plugins/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -98
- package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
- package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
- package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
- package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
- package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
- package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
- package/src/omega/core_plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +0 -77
- package/src/omega/core_plugins.js +0 -39
- package/src/omega/runtime_support/runtime_support.js +0 -20
- package/src/omega/url_mentions/css_url_mentions.js +0 -63
- package/src/omega/url_mentions/html_url_mentions.js +0 -185
- package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
- package/src/omega/url_mentions/parse_url_mentions.js +0 -37
- package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
package/src/build/build.js
CHANGED
|
@@ -21,70 +21,101 @@ import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
|
|
|
21
21
|
import {
|
|
22
22
|
injectQueryParams,
|
|
23
23
|
setUrlFilename,
|
|
24
|
+
asUrlUntilPathname,
|
|
24
25
|
} from "@jsenv/utils/urls/url_utils.js"
|
|
25
|
-
import {
|
|
26
|
+
import { createVersionGenerator } from "@jsenv/utils/versioning/version_generator.js"
|
|
26
27
|
import { generateSourcemapUrl } from "@jsenv/utils/sourcemap/sourcemap_utils.js"
|
|
27
28
|
import {
|
|
28
29
|
parseHtmlString,
|
|
29
30
|
stringifyHtmlAst,
|
|
30
31
|
} from "@jsenv/utils/html_ast/html_ast.js"
|
|
31
32
|
|
|
32
|
-
import {
|
|
33
|
-
import { jsenvPluginInline } from "../
|
|
33
|
+
import { jsenvPluginUrlReferences } from "../plugins/url_references/jsenv_plugin_url_references.js"
|
|
34
|
+
import { jsenvPluginInline } from "../plugins/inline/jsenv_plugin_inline.js"
|
|
35
|
+
import { jsenvPluginAsJsClassic } from "../plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js"
|
|
34
36
|
import { createUrlGraph } from "../omega/url_graph.js"
|
|
35
|
-
import { getCorePlugins } from "../
|
|
37
|
+
import { getCorePlugins } from "../plugins/plugins.js"
|
|
36
38
|
import { createKitchen } from "../omega/kitchen.js"
|
|
37
39
|
import { loadUrlGraph } from "../omega/url_graph/url_graph_load.js"
|
|
38
40
|
import { createUrlGraphSummary } from "../omega/url_graph/url_graph_report.js"
|
|
39
41
|
import { sortUrlGraphByDependencies } from "../omega/url_graph/url_graph_sort.js"
|
|
42
|
+
import { isWebWorkerEntryPointReference } from "../omega/web_workers.js"
|
|
40
43
|
|
|
44
|
+
import { GRAPH } from "./graph_utils.js"
|
|
41
45
|
import { createBuilUrlsGenerator } from "./build_urls_generator.js"
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
45
|
-
import { jsenvPluginMinifyHtml } from "./plugins/minify_html/jsenv_plugin_minify_html.js"
|
|
46
|
+
import { injectGlobalVersionMapping } from "./inject_global_version_mappings.js"
|
|
47
|
+
import { injectServiceWorkerUrls } from "./inject_service_worker_urls.js"
|
|
48
|
+
import { resyncRessourceHints } from "./resync_ressource_hints.js"
|
|
46
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Generate an optimized version of source files into a directory
|
|
52
|
+
* @param {Object} buildParameters
|
|
53
|
+
* @param {string|url} buildParameters.rootDirectoryUrl
|
|
54
|
+
* Directory containing source files
|
|
55
|
+
* @param {string|url} buildParameters.buildDirectoryUrl
|
|
56
|
+
* Directory where optimized files will be written
|
|
57
|
+
* @param {object} buildParameters.entryPoints
|
|
58
|
+
* Describe entry point paths and control their names in the build directory
|
|
59
|
+
* @param {object} buildParameters.runtimeCompat
|
|
60
|
+
* Code generated will be compatible with these runtimes
|
|
61
|
+
* @param {string="/"} buildParameters.baseUrl
|
|
62
|
+
* All urls in build file contents are prefixed with this url
|
|
63
|
+
* @param {boolean|object} [buildParameters.minification=true]
|
|
64
|
+
* Minify build file contents
|
|
65
|
+
* @param {boolean} [buildParameters.versioning=true]
|
|
66
|
+
* Controls if url in build file contents are versioned
|
|
67
|
+
* @param {('search_param'|'filename')} [buildParameters.versioningMethod="search_param"]
|
|
68
|
+
* Controls how url are versioned
|
|
69
|
+
* @param {boolean|string} [buildParameters.sourcemaps=false]
|
|
70
|
+
* Generate sourcemaps in the build directory
|
|
71
|
+
* @return {Object} buildReturnValue
|
|
72
|
+
* @return {Object} buildReturnValue.buildFileContents
|
|
73
|
+
* Contains all build file paths relative to the build directory and their content
|
|
74
|
+
* @return {Object} buildReturnValue.buildInlineContents
|
|
75
|
+
* Contains content that is inline into build files
|
|
76
|
+
* @return {Object} buildReturnValue.buildManifest
|
|
77
|
+
* Map build file paths without versioning to versioned file paths
|
|
78
|
+
*/
|
|
47
79
|
export const build = async ({
|
|
48
80
|
signal = new AbortController().signal,
|
|
49
81
|
logLevel = "info",
|
|
50
82
|
rootDirectoryUrl,
|
|
51
83
|
buildDirectoryUrl,
|
|
52
84
|
entryPoints = {},
|
|
53
|
-
|
|
54
|
-
// that will just pass different options to build project
|
|
55
|
-
// and this function will be agnostic about "preview" concept
|
|
56
|
-
isPreview = false,
|
|
85
|
+
|
|
57
86
|
plugins = [],
|
|
58
|
-
|
|
87
|
+
sourcemaps = false,
|
|
59
88
|
nodeEsmResolution,
|
|
60
89
|
fileSystemMagicResolution,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
injectedGlobals,
|
|
91
|
+
runtimeCompat,
|
|
92
|
+
transpilation = {},
|
|
65
93
|
bundling = true,
|
|
66
|
-
|
|
67
|
-
versioning =
|
|
94
|
+
minification = true,
|
|
95
|
+
versioning = true,
|
|
96
|
+
versioningMethod = "search_param", // "filename", "search_param"
|
|
68
97
|
lineBreakNormalization = process.platform === "win32",
|
|
69
98
|
|
|
70
99
|
writeOnFileSystem = true,
|
|
71
100
|
buildDirectoryClean = true,
|
|
72
101
|
baseUrl = "/",
|
|
102
|
+
assetManifest = true,
|
|
103
|
+
assetManifestFileRelativeUrl = "asset-manifest.json",
|
|
73
104
|
}) => {
|
|
74
105
|
const logger = createLogger({ logLevel })
|
|
75
106
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
76
107
|
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl)
|
|
77
108
|
assertEntryPoints({ entryPoints })
|
|
78
|
-
if (!["filename", "search_param"
|
|
109
|
+
if (!["filename", "search_param"].includes(versioningMethod)) {
|
|
79
110
|
throw new Error(
|
|
80
|
-
`Unexpected "
|
|
111
|
+
`Unexpected "versioningMethod": must be "filename", "search_param"; got ${versioning}`,
|
|
81
112
|
)
|
|
82
113
|
}
|
|
83
114
|
|
|
84
115
|
const entryPointKeys = Object.keys(entryPoints)
|
|
85
116
|
if (entryPointKeys.length === 1) {
|
|
86
117
|
logger.info(`
|
|
87
|
-
build ${entryPointKeys[0]}`)
|
|
118
|
+
build "${entryPointKeys[0]}"`)
|
|
88
119
|
} else {
|
|
89
120
|
logger.info(`
|
|
90
121
|
build ${entryPointKeys.length} entry points`)
|
|
@@ -97,6 +128,9 @@ build ${entryPointKeys.length} entry points`)
|
|
|
97
128
|
logger,
|
|
98
129
|
rootDirectoryUrl,
|
|
99
130
|
urlGraph: rawGraph,
|
|
131
|
+
scenario: "build",
|
|
132
|
+
sourcemaps,
|
|
133
|
+
runtimeCompat,
|
|
100
134
|
plugins: [
|
|
101
135
|
...plugins,
|
|
102
136
|
{
|
|
@@ -108,33 +142,39 @@ build ${entryPointKeys.length} entry points`)
|
|
|
108
142
|
},
|
|
109
143
|
},
|
|
110
144
|
...getCorePlugins({
|
|
111
|
-
|
|
145
|
+
rootDirectoryUrl,
|
|
146
|
+
urlGraph: rawGraph,
|
|
147
|
+
scenario: "build",
|
|
148
|
+
|
|
112
149
|
nodeEsmResolution,
|
|
113
150
|
fileSystemMagicResolution,
|
|
114
|
-
|
|
151
|
+
injectedGlobals,
|
|
152
|
+
transpilation: {
|
|
153
|
+
...transpilation,
|
|
154
|
+
jsModuleAsJsClassic: false,
|
|
155
|
+
},
|
|
156
|
+
minification,
|
|
157
|
+
bundling,
|
|
115
158
|
}),
|
|
116
|
-
jsenvPluginBundleJsModule(),
|
|
117
|
-
...(minify ? [jsenvPluginMinifyJs(), jsenvPluginMinifyHtml()] : []),
|
|
118
159
|
],
|
|
119
|
-
scenario: "build",
|
|
120
|
-
sourcemaps,
|
|
121
160
|
})
|
|
122
|
-
const
|
|
123
|
-
Object.keys(entryPoints).forEach((key) => {
|
|
124
|
-
cookEntryFile({
|
|
125
|
-
trace: `"${key}" in entryPoints parameter`,
|
|
126
|
-
type: "entry_point",
|
|
127
|
-
specifier: key,
|
|
128
|
-
})
|
|
129
|
-
})
|
|
130
|
-
}
|
|
161
|
+
const entryUrls = []
|
|
131
162
|
try {
|
|
132
163
|
await loadUrlGraph({
|
|
133
164
|
urlGraph: rawGraph,
|
|
134
165
|
kitchen: rawGraphKitchen,
|
|
135
166
|
outDirectoryUrl: new URL(`.jsenv/build/`, rootDirectoryUrl),
|
|
136
|
-
|
|
137
|
-
|
|
167
|
+
startLoading: (cookEntryFile) => {
|
|
168
|
+
Object.keys(entryPoints).forEach((key) => {
|
|
169
|
+
const [, entryUrlInfo] = cookEntryFile({
|
|
170
|
+
trace: `"${key}" in entryPoints parameter`,
|
|
171
|
+
type: "entry_point",
|
|
172
|
+
specifier: key,
|
|
173
|
+
})
|
|
174
|
+
entryUrls.push(entryUrlInfo.url)
|
|
175
|
+
entryUrlInfo.filename = entryPoints[key]
|
|
176
|
+
})
|
|
177
|
+
},
|
|
138
178
|
})
|
|
139
179
|
} catch (e) {
|
|
140
180
|
prebuildTask.fail()
|
|
@@ -147,44 +187,53 @@ build ${entryPointKeys.length} entry points`)
|
|
|
147
187
|
${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
148
188
|
)
|
|
149
189
|
|
|
190
|
+
const buildUrlsGenerator = createBuilUrlsGenerator({
|
|
191
|
+
buildDirectoryUrl,
|
|
192
|
+
})
|
|
193
|
+
const rawUrls = {}
|
|
194
|
+
const buildUrls = {}
|
|
195
|
+
const rawUrlRedirections = {}
|
|
150
196
|
const bundleUrlInfos = {}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
197
|
+
const bundlers = {}
|
|
198
|
+
rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
|
|
199
|
+
const bundle = plugin.bundle
|
|
200
|
+
if (!bundle) {
|
|
201
|
+
return
|
|
202
|
+
}
|
|
203
|
+
if (typeof bundle !== "object") {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`bundle must be an object, found "${bundle}" on plugin named "${plugin.name}"`,
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
Object.keys(bundle).forEach((type) => {
|
|
209
|
+
const bundleFunction = bundle[type]
|
|
210
|
+
if (!bundleFunction) {
|
|
156
211
|
return
|
|
157
212
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
Object.keys(bundle).forEach((type) => {
|
|
164
|
-
const bundlerForThatType = bundlers[type]
|
|
165
|
-
if (bundlerForThatType) {
|
|
166
|
-
// first plugin to define a bundle hook wins
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
bundlers[type] = {
|
|
170
|
-
plugin,
|
|
171
|
-
bundleFunction: bundle[type],
|
|
172
|
-
urlInfos: [],
|
|
173
|
-
}
|
|
174
|
-
})
|
|
175
|
-
})
|
|
176
|
-
const addToBundlerIfAny = (rawUrlInfo) => {
|
|
177
|
-
const bundler = bundlers[rawUrlInfo.type]
|
|
178
|
-
if (bundler) {
|
|
179
|
-
bundler.urlInfos.push(rawUrlInfo)
|
|
213
|
+
const bundlerForThatType = bundlers[type]
|
|
214
|
+
if (bundlerForThatType) {
|
|
215
|
+
// first plugin to define a bundle hook wins
|
|
180
216
|
return
|
|
181
217
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return
|
|
218
|
+
bundlers[type] = {
|
|
219
|
+
plugin,
|
|
220
|
+
bundleFunction: bundle[type],
|
|
221
|
+
urlInfos: [],
|
|
187
222
|
}
|
|
223
|
+
})
|
|
224
|
+
})
|
|
225
|
+
const addToBundlerIfAny = (rawUrlInfo) => {
|
|
226
|
+
// if (rawUrlInfo.dependencies.size === 0) {
|
|
227
|
+
// return
|
|
228
|
+
// }
|
|
229
|
+
const bundler = bundlers[rawUrlInfo.type]
|
|
230
|
+
if (bundler) {
|
|
231
|
+
bundler.urlInfos.push(rawUrlInfo)
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
GRAPH.forEach(rawGraph, (rawUrlInfo) => {
|
|
236
|
+
if (rawUrlInfo.data.isEntryPoint) {
|
|
188
237
|
addToBundlerIfAny(rawUrlInfo)
|
|
189
238
|
if (rawUrlInfo.type === "html") {
|
|
190
239
|
rawUrlInfo.dependencies.forEach((dependencyUrl) => {
|
|
@@ -194,7 +243,8 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
194
243
|
// bundle inline script type module deps
|
|
195
244
|
dependencyUrlInfo.references.forEach((inlineScriptRef) => {
|
|
196
245
|
if (inlineScriptRef.type === "js_import_export") {
|
|
197
|
-
|
|
246
|
+
const inlineUrlInfo = rawGraph.getUrlInfo(inlineScriptRef.url)
|
|
247
|
+
addToBundlerIfAny(inlineUrlInfo)
|
|
198
248
|
}
|
|
199
249
|
})
|
|
200
250
|
}
|
|
@@ -205,231 +255,335 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
205
255
|
})
|
|
206
256
|
return
|
|
207
257
|
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
258
|
+
}
|
|
259
|
+
// File referenced with new URL('./file.js', import.meta.url)
|
|
260
|
+
// are entry points that can be bundled
|
|
261
|
+
// For instance we will bundle service worker/workers detected like this
|
|
262
|
+
if (rawUrlInfo.type === "js_module") {
|
|
263
|
+
rawUrlInfo.references.forEach((reference) => {
|
|
264
|
+
if (reference.type === "js_url_specifier") {
|
|
265
|
+
const urlInfo = rawGraph.getUrlInfo(reference.url)
|
|
266
|
+
addToBundlerIfAny(urlInfo)
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
const bundleUrlRedirections = {}
|
|
272
|
+
await Object.keys(bundlers).reduce(async (previous, type) => {
|
|
273
|
+
await previous
|
|
274
|
+
const bundler = bundlers[type]
|
|
275
|
+
const urlInfosToBundle = bundler.urlInfos
|
|
276
|
+
if (urlInfosToBundle.length === 0) {
|
|
277
|
+
return
|
|
278
|
+
}
|
|
279
|
+
const bundleTask = createTaskLog(logger, `bundle "${type}"`)
|
|
280
|
+
try {
|
|
281
|
+
const bundlerGeneratedUrlInfos =
|
|
282
|
+
await rawGraphKitchen.pluginController.callAsyncHook(
|
|
283
|
+
{
|
|
284
|
+
plugin: bundler.plugin,
|
|
285
|
+
hookName: "bundle",
|
|
286
|
+
value: bundler.bundleFunction,
|
|
287
|
+
},
|
|
288
|
+
urlInfosToBundle,
|
|
289
|
+
{
|
|
290
|
+
...rawGraphKitchen.baseContext,
|
|
291
|
+
buildDirectoryUrl,
|
|
292
|
+
},
|
|
293
|
+
)
|
|
294
|
+
Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
|
|
295
|
+
const rawUrlInfo = rawGraph.getUrlInfo(url)
|
|
296
|
+
const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url]
|
|
297
|
+
const bundleUrlInfo = {
|
|
298
|
+
type,
|
|
299
|
+
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
300
|
+
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
301
|
+
...bundlerGeneratedUrlInfo,
|
|
302
|
+
data: {
|
|
303
|
+
...(rawUrlInfo ? rawUrlInfo.data : {}),
|
|
304
|
+
...bundlerGeneratedUrlInfo.data,
|
|
305
|
+
fromBundle: true,
|
|
306
|
+
},
|
|
307
|
+
}
|
|
308
|
+
const buildUrl = buildUrlsGenerator.generate(url, {
|
|
309
|
+
urlInfo: bundleUrlInfo,
|
|
248
310
|
})
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
311
|
+
rawUrlRedirections[url] = buildUrl
|
|
312
|
+
rawUrls[buildUrl] = url
|
|
313
|
+
bundleUrlInfos[buildUrl] = bundleUrlInfo
|
|
314
|
+
if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
|
|
315
|
+
const urlForBundler = new URL(
|
|
316
|
+
bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
|
|
317
|
+
buildDirectoryUrl,
|
|
318
|
+
).href
|
|
319
|
+
bundleUrlRedirections[urlForBundler] = buildUrl
|
|
320
|
+
}
|
|
321
|
+
})
|
|
322
|
+
} catch (e) {
|
|
323
|
+
bundleTask.fail()
|
|
324
|
+
throw e
|
|
325
|
+
}
|
|
326
|
+
bundleTask.done()
|
|
327
|
+
}, Promise.resolve())
|
|
256
328
|
|
|
257
|
-
const
|
|
258
|
-
buildDirectoryUrl,
|
|
259
|
-
})
|
|
260
|
-
const rawUrls = {}
|
|
261
|
-
const buildUrls = {}
|
|
329
|
+
const buildUrlRedirections = {}
|
|
262
330
|
const finalGraph = createUrlGraph()
|
|
263
|
-
const
|
|
331
|
+
const optimizeUrlContentHooks =
|
|
332
|
+
rawGraphKitchen.pluginController.addHook("optimizeUrlContent")
|
|
264
333
|
const finalGraphKitchen = createKitchen({
|
|
265
334
|
logger,
|
|
266
335
|
rootDirectoryUrl,
|
|
267
336
|
urlGraph: finalGraph,
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
// - But it would not work when sourcemap are not generated
|
|
273
|
-
// - would be a bit slower
|
|
274
|
-
// - So instead of reading the inline content directly, we search into raw graph
|
|
275
|
-
// to get "originalContent" and "sourcemap"
|
|
276
|
-
loadInlineUrlInfos: (finalUrlInfo) => {
|
|
277
|
-
const rawUrl = finalUrlInfo.data.rawUrl
|
|
278
|
-
const bundleUrlInfo = bundleUrlInfos[rawUrl]
|
|
279
|
-
const urlInfo = bundleUrlInfo || finalUrlInfo
|
|
280
|
-
const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
|
|
281
|
-
return {
|
|
282
|
-
originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
|
|
283
|
-
sourcemap: bundleUrlInfo
|
|
284
|
-
? bundleUrlInfo.sourcemap
|
|
285
|
-
: rawUrlInfo
|
|
286
|
-
? rawUrlInfo.sourcemap
|
|
287
|
-
: undefined,
|
|
288
|
-
contentType: urlInfo.contentType,
|
|
289
|
-
content: urlInfo.content,
|
|
290
|
-
}
|
|
291
|
-
},
|
|
337
|
+
scenario: "build",
|
|
338
|
+
sourcemaps,
|
|
339
|
+
sourcemapsRelativeSources: true,
|
|
340
|
+
runtimeCompat,
|
|
292
341
|
plugins: [
|
|
293
|
-
|
|
342
|
+
jsenvPluginUrlReferences(),
|
|
343
|
+
jsenvPluginAsJsClassic({
|
|
344
|
+
systemJsInjection: true,
|
|
345
|
+
}),
|
|
346
|
+
jsenvPluginInline({
|
|
347
|
+
fetchInlineUrls: false,
|
|
348
|
+
}),
|
|
294
349
|
{
|
|
295
350
|
name: "jsenv:postbuild",
|
|
296
351
|
appliesDuring: { build: true },
|
|
297
|
-
|
|
298
|
-
if (reference.specifier[0] === "
|
|
299
|
-
|
|
300
|
-
.href
|
|
301
|
-
return url
|
|
352
|
+
resolveUrl: (reference) => {
|
|
353
|
+
if (reference.specifier[0] === "#") {
|
|
354
|
+
reference.external = true
|
|
302
355
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return rawUrl
|
|
356
|
+
let url =
|
|
357
|
+
reference.specifier[0] === "/"
|
|
358
|
+
? new URL(reference.specifier.slice(1), buildDirectoryUrl).href
|
|
359
|
+
: new URL(reference.specifier, reference.parentUrl).href
|
|
360
|
+
const urlRedirectedByBundle = bundleUrlRedirections[url]
|
|
361
|
+
if (urlRedirectedByBundle) {
|
|
362
|
+
return urlRedirectedByBundle
|
|
311
363
|
}
|
|
312
|
-
|
|
364
|
+
const parentIsFromBundle = Boolean(
|
|
365
|
+
bundleUrlInfos[reference.parentUrl],
|
|
366
|
+
)
|
|
367
|
+
// urls inside css bundled by parcel
|
|
368
|
+
// contains url relative to the bundle file (which is considered inside build directory)
|
|
369
|
+
// if the file is not itself a bundle file it must be resolved against
|
|
370
|
+
// the original css url
|
|
371
|
+
if (
|
|
372
|
+
parentIsFromBundle &&
|
|
373
|
+
!bundleUrlInfos[url] &&
|
|
374
|
+
urlIsInsideOf(url, buildDirectoryUrl)
|
|
375
|
+
) {
|
|
376
|
+
const parentRawUrl = rawUrls[reference.parentUrl]
|
|
377
|
+
url = new URL(reference.specifier, parentRawUrl).href
|
|
378
|
+
}
|
|
379
|
+
const urlRedirected = rawUrlRedirections[url]
|
|
380
|
+
return urlRedirected || url
|
|
313
381
|
},
|
|
314
|
-
|
|
382
|
+
normalizeUrl: (reference) => {
|
|
315
383
|
if (!reference.url.startsWith("file:")) {
|
|
316
384
|
return null
|
|
317
385
|
}
|
|
318
386
|
// already a build url
|
|
319
387
|
const rawUrl = rawUrls[reference.url]
|
|
320
388
|
if (rawUrl) {
|
|
321
|
-
reference.data.rawUrl = rawUrl
|
|
322
389
|
return reference.url
|
|
323
390
|
}
|
|
324
|
-
const bundleUrlInfo = bundleUrlInfos[reference.url]
|
|
325
391
|
// from rollup or postcss
|
|
392
|
+
const bundleUrlInfo = bundleUrlInfos[reference.url]
|
|
326
393
|
if (bundleUrlInfo) {
|
|
327
|
-
|
|
328
|
-
reference.url,
|
|
329
|
-
bundleUrlInfo,
|
|
330
|
-
)
|
|
331
|
-
reference.data.rawUrl = reference.url
|
|
332
|
-
rawUrls[buildUrl] = reference.url
|
|
333
|
-
return buildUrl
|
|
394
|
+
return reference.url
|
|
334
395
|
}
|
|
335
|
-
|
|
336
|
-
//
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
)
|
|
342
|
-
|
|
343
|
-
|
|
396
|
+
// from "js_module_as_js_classic":
|
|
397
|
+
// - injecting "?as_js_classic" for the first time
|
|
398
|
+
// - injecting "?as_js_classic" because the parentUrl has it
|
|
399
|
+
if (reference.original) {
|
|
400
|
+
const referenceOriginalUrl = reference.original.url
|
|
401
|
+
let originalBuildUrl
|
|
402
|
+
if (urlIsInsideOf(referenceOriginalUrl, buildDirectoryUrl)) {
|
|
403
|
+
originalBuildUrl = referenceOriginalUrl
|
|
404
|
+
} else {
|
|
405
|
+
originalBuildUrl = Object.keys(rawUrls).find(
|
|
406
|
+
(key) => rawUrls[key] === referenceOriginalUrl,
|
|
407
|
+
)
|
|
408
|
+
}
|
|
409
|
+
let rawUrl
|
|
410
|
+
if (urlIsInsideOf(reference.url, buildDirectoryUrl)) {
|
|
411
|
+
// rawUrl = rawUrls[reference.url] || reference.url
|
|
412
|
+
const originalBuildUrl =
|
|
413
|
+
buildUrlRedirections[referenceOriginalUrl]
|
|
414
|
+
rawUrl = originalBuildUrl
|
|
415
|
+
? rawUrls[originalBuildUrl]
|
|
416
|
+
: reference.url
|
|
417
|
+
} else {
|
|
418
|
+
rawUrl = reference.url
|
|
419
|
+
}
|
|
420
|
+
// the url info do not exists yet (it will be created after this "normalize" hook)
|
|
421
|
+
// And the content will be generated when url is cooked by url graph loader.
|
|
422
|
+
// Here we just want to reserve an url for that file
|
|
423
|
+
const buildUrl = buildUrlsGenerator.generate(rawUrl, {
|
|
424
|
+
urlInfo: {
|
|
425
|
+
data: {
|
|
426
|
+
...reference.data,
|
|
427
|
+
isWebWorkerEntryPoint:
|
|
428
|
+
isWebWorkerEntryPointReference(reference),
|
|
429
|
+
},
|
|
430
|
+
type: reference.expectedType,
|
|
431
|
+
subtype: reference.expectedSubtype,
|
|
432
|
+
filename: reference.filename,
|
|
433
|
+
},
|
|
434
|
+
})
|
|
435
|
+
buildUrlRedirections[originalBuildUrl] = buildUrl
|
|
436
|
+
rawUrls[buildUrl] = rawUrl
|
|
344
437
|
return buildUrl
|
|
345
438
|
}
|
|
346
439
|
if (reference.isInline) {
|
|
347
|
-
const
|
|
348
|
-
const rawUrlInfo = rawGraph.urlInfos[url]
|
|
440
|
+
const rawUrlInfo = GRAPH.find(rawGraph, (rawUrlInfo) => {
|
|
349
441
|
if (!rawUrlInfo.isInline) {
|
|
350
442
|
return false
|
|
351
443
|
}
|
|
352
444
|
if (rawUrlInfo.content === reference.content) {
|
|
353
445
|
return true
|
|
354
446
|
}
|
|
447
|
+
if (rawUrlInfo.originalContent === reference.content) {
|
|
448
|
+
return true
|
|
449
|
+
}
|
|
355
450
|
return false
|
|
356
451
|
})
|
|
357
|
-
if (!rawUrl) {
|
|
358
|
-
throw new Error(`cannot find raw url`)
|
|
359
|
-
}
|
|
360
|
-
const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
|
|
361
452
|
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
453
|
+
if (!rawUrlInfo) {
|
|
454
|
+
// generated during final graph
|
|
455
|
+
// (happens for JSON.parse injected for import assertions for instance)
|
|
456
|
+
// throw new Error(`cannot find raw url for "${reference.url}"`)
|
|
457
|
+
return reference.url
|
|
458
|
+
}
|
|
459
|
+
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
460
|
+
urlInfo: rawUrlInfo,
|
|
365
461
|
parentUrlInfo,
|
|
366
|
-
)
|
|
462
|
+
})
|
|
463
|
+
rawUrls[buildUrl] = rawUrlInfo.url
|
|
464
|
+
return buildUrl
|
|
465
|
+
}
|
|
466
|
+
// from "js_module_as_js_classic":
|
|
467
|
+
// - to inject "s.js"
|
|
468
|
+
if (reference.injected) {
|
|
469
|
+
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
470
|
+
urlInfo: {
|
|
471
|
+
data: {},
|
|
472
|
+
type: "js_classic",
|
|
473
|
+
},
|
|
474
|
+
})
|
|
367
475
|
rawUrls[buildUrl] = reference.url
|
|
368
|
-
|
|
476
|
+
return buildUrl
|
|
477
|
+
}
|
|
478
|
+
const rawUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
479
|
+
// files from root directory but not given to rollup nor postcss
|
|
480
|
+
if (rawUrlInfo) {
|
|
481
|
+
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
482
|
+
urlInfo: rawUrlInfo,
|
|
483
|
+
})
|
|
484
|
+
rawUrls[buildUrl] = rawUrlInfo.url
|
|
369
485
|
return buildUrl
|
|
370
486
|
}
|
|
371
487
|
if (reference.type === "sourcemap_comment") {
|
|
372
488
|
// inherit parent build url
|
|
373
489
|
return generateSourcemapUrl(reference.parentUrl)
|
|
374
490
|
}
|
|
375
|
-
// files generated during the final graph
|
|
491
|
+
// files generated during the final graph:
|
|
492
|
+
// - sourcemaps
|
|
376
493
|
// const finalUrlInfo = finalGraph.getUrlInfo(url)
|
|
377
494
|
const buildUrl = buildUrlsGenerator.generate(reference.url, {
|
|
378
|
-
|
|
379
|
-
|
|
495
|
+
urlInfo: {
|
|
496
|
+
data: {},
|
|
497
|
+
type: "asset",
|
|
498
|
+
},
|
|
380
499
|
})
|
|
381
500
|
return buildUrl
|
|
382
501
|
},
|
|
383
|
-
|
|
384
|
-
if (!reference.
|
|
502
|
+
formatUrl: (reference) => {
|
|
503
|
+
if (!reference.generatedUrl.startsWith("file:")) {
|
|
385
504
|
return null
|
|
386
505
|
}
|
|
387
|
-
if (!urlIsInsideOf(reference.
|
|
506
|
+
if (!urlIsInsideOf(reference.generatedUrl, buildDirectoryUrl)) {
|
|
388
507
|
throw new Error(
|
|
389
508
|
`urls should be inside build directory at this stage, found "${reference.url}"`,
|
|
390
509
|
)
|
|
391
510
|
}
|
|
511
|
+
// remove eventual search params and hash
|
|
512
|
+
const urlUntilPathname = asUrlUntilPathname(reference.generatedUrl)
|
|
392
513
|
// if a file is in the same directory we could prefer the relative notation
|
|
393
|
-
// but to keep things simple let's keep the
|
|
514
|
+
// but to keep things simple let's keep the "absolutely relative" to baseUrl for now
|
|
394
515
|
const specifier = `${baseUrl}${urlToRelativeUrl(
|
|
395
|
-
|
|
516
|
+
urlUntilPathname,
|
|
396
517
|
buildDirectoryUrl,
|
|
397
518
|
)}`
|
|
398
|
-
buildUrls[specifier] = reference.
|
|
519
|
+
buildUrls[specifier] = reference.generatedUrl
|
|
399
520
|
return specifier
|
|
400
521
|
},
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
const urlInfo = bundleUrlInfo || rawGraph.getUrlInfo(rawUrl)
|
|
405
|
-
return {
|
|
406
|
-
data: bundleUrlInfo ? bundleUrlInfo.data : undefined,
|
|
407
|
-
originalContent: urlInfo.originalContent,
|
|
408
|
-
contentType: urlInfo.contentType,
|
|
409
|
-
content: urlInfo.content,
|
|
410
|
-
sourcemap: urlInfo.sourcemap,
|
|
522
|
+
fetchUrlContent: async (finalUrlInfo, context) => {
|
|
523
|
+
if (!finalUrlInfo.url.startsWith("file:")) {
|
|
524
|
+
return { external: true }
|
|
411
525
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
storeOriginalPositions: false,
|
|
417
|
-
})
|
|
418
|
-
return {
|
|
419
|
-
content: stringifyHtmlAst(htmlAst, {
|
|
420
|
-
removeOriginalPositionAttributes: true,
|
|
421
|
-
}),
|
|
526
|
+
const fromBundleOrRawGraph = (url) => {
|
|
527
|
+
const bundleUrlInfo = bundleUrlInfos[url]
|
|
528
|
+
if (bundleUrlInfo) {
|
|
529
|
+
return bundleUrlInfo
|
|
422
530
|
}
|
|
423
|
-
|
|
531
|
+
const rawUrl = rawUrls[url] || url
|
|
532
|
+
const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
|
|
533
|
+
if (!rawUrlInfo) {
|
|
534
|
+
const originalBuildUrl = buildUrlRedirections[url]
|
|
535
|
+
if (originalBuildUrl) {
|
|
536
|
+
return fromBundleOrRawGraph(originalBuildUrl)
|
|
537
|
+
}
|
|
538
|
+
throw new Error(`Cannot find url`)
|
|
539
|
+
}
|
|
540
|
+
if (rawUrlInfo.isInline) {
|
|
541
|
+
// Inline content, such as <script> inside html, is transformed during the previous phase.
|
|
542
|
+
// If we read the inline content it would be considered as the original content.
|
|
543
|
+
// - It could be "fixed" by taking into account sourcemap and consider sourcemap sources
|
|
544
|
+
// as the original content.
|
|
545
|
+
// - But it would not work when sourcemap are not generated
|
|
546
|
+
// - would be a bit slower
|
|
547
|
+
// - So instead of reading the inline content directly, we search into raw graph
|
|
548
|
+
// to get "originalContent" and "sourcemap"
|
|
549
|
+
finalUrlInfo.type = rawUrlInfo.type
|
|
550
|
+
finalUrlInfo.subtype = rawUrlInfo.subtype
|
|
551
|
+
return rawUrlInfo
|
|
552
|
+
}
|
|
553
|
+
return rawUrlInfo
|
|
554
|
+
}
|
|
555
|
+
// reference injected during "postbuild":
|
|
556
|
+
// - happens for "as_js_classic" injecting "s.js"
|
|
557
|
+
if (context.reference.injected) {
|
|
558
|
+
const [ref, rawUrlInfo] = rawGraphKitchen.injectReference({
|
|
559
|
+
type: context.reference.type,
|
|
560
|
+
expectedType: context.reference.expectedType,
|
|
561
|
+
expectedSubtype: context.reference.expectedSubtype,
|
|
562
|
+
parentUrl: rawUrls[context.reference.parentUrl],
|
|
563
|
+
specifier: context.reference.specifier,
|
|
564
|
+
injected: true,
|
|
565
|
+
})
|
|
566
|
+
await rawGraphKitchen.cook({
|
|
567
|
+
reference: ref,
|
|
568
|
+
urlInfo: rawUrlInfo,
|
|
569
|
+
})
|
|
570
|
+
return rawUrlInfo
|
|
571
|
+
}
|
|
572
|
+
// reference updated during "postbuild":
|
|
573
|
+
// - happens for "as_js_classic"
|
|
574
|
+
if (context.reference.original) {
|
|
575
|
+
return fromBundleOrRawGraph(context.reference.original.url)
|
|
576
|
+
}
|
|
577
|
+
return fromBundleOrRawGraph(finalUrlInfo.url)
|
|
424
578
|
},
|
|
425
579
|
},
|
|
426
580
|
{
|
|
427
581
|
name: "jsenv:optimize",
|
|
428
582
|
appliesDuring: { build: true },
|
|
429
|
-
|
|
430
|
-
if (
|
|
583
|
+
finalizeUrlContent: async (urlInfo, context) => {
|
|
584
|
+
if (optimizeUrlContentHooks.length) {
|
|
431
585
|
await rawGraphKitchen.pluginController.callAsyncHooks(
|
|
432
|
-
"
|
|
586
|
+
"optimizeUrlContent",
|
|
433
587
|
urlInfo,
|
|
434
588
|
context,
|
|
435
589
|
async (optimizeReturnValue) => {
|
|
@@ -443,17 +597,24 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
443
597
|
},
|
|
444
598
|
},
|
|
445
599
|
],
|
|
446
|
-
scenario: "build",
|
|
447
|
-
sourcemaps,
|
|
448
600
|
})
|
|
449
601
|
const buildTask = createTaskLog(logger, "build")
|
|
602
|
+
const postBuildEntryUrls = []
|
|
450
603
|
try {
|
|
451
604
|
await loadUrlGraph({
|
|
452
605
|
urlGraph: finalGraph,
|
|
453
606
|
kitchen: finalGraphKitchen,
|
|
454
607
|
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
455
|
-
|
|
456
|
-
|
|
608
|
+
startLoading: (cookEntryFile) => {
|
|
609
|
+
entryUrls.forEach((entryUrl) => {
|
|
610
|
+
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
611
|
+
trace: `entryPoint`,
|
|
612
|
+
type: "entry_point",
|
|
613
|
+
specifier: entryUrl,
|
|
614
|
+
})
|
|
615
|
+
postBuildEntryUrls.push(postBuildEntryUrlInfo.url)
|
|
616
|
+
})
|
|
617
|
+
},
|
|
457
618
|
})
|
|
458
619
|
} catch (e) {
|
|
459
620
|
buildTask.fail()
|
|
@@ -465,217 +626,105 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
465
626
|
`graph urls pre-versioning:
|
|
466
627
|
${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
467
628
|
)
|
|
468
|
-
if (versioning
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
urlVersionGenerator.augmentWithContent({
|
|
485
|
-
content: urlInfo.content,
|
|
486
|
-
contentType: urlInfo.contentType,
|
|
487
|
-
lineBreakNormalization,
|
|
488
|
-
})
|
|
489
|
-
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
490
|
-
const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
|
|
491
|
-
if (dependencyUrlInfo.isInline) {
|
|
492
|
-
// this content is part of the file, no need to take into account twice
|
|
493
|
-
return
|
|
494
|
-
}
|
|
495
|
-
if (dependencyUrlInfo.data.version) {
|
|
496
|
-
urlVersionGenerator.augmentWithDependencyVersion(
|
|
497
|
-
dependencyUrlInfo.data.version,
|
|
498
|
-
)
|
|
499
|
-
} else {
|
|
500
|
-
// because all dependencies are know, if the dependency has no version
|
|
501
|
-
// it means there is a circular dependency between this file
|
|
502
|
-
// and it's dependency
|
|
503
|
-
// in that case we'll use the dependency content
|
|
504
|
-
urlVersionGenerator.augmentWithContent({
|
|
505
|
-
content: dependencyUrlInfo.content,
|
|
506
|
-
contentType: dependencyUrlInfo.contentType,
|
|
507
|
-
lineBreakNormalization,
|
|
508
|
-
})
|
|
509
|
-
}
|
|
510
|
-
})
|
|
511
|
-
urlInfo.data.version = urlVersionGenerator.generate()
|
|
512
|
-
urlInfo.data.versionedUrl = injectVersionIntoBuildUrl({
|
|
513
|
-
buildUrl: urlInfo.url,
|
|
514
|
-
version: urlInfo.data.version,
|
|
515
|
-
versioning,
|
|
516
|
-
})
|
|
517
|
-
})
|
|
518
|
-
const versionMappings = {}
|
|
519
|
-
const usedVersionMappings = []
|
|
520
|
-
const versioningKitchen = createKitchen({
|
|
521
|
-
logger,
|
|
522
|
-
rootDirectoryUrl: buildDirectoryUrl,
|
|
523
|
-
urlGraph: finalGraph,
|
|
524
|
-
loadInlineUrlInfos: (versionedUrlInfo) => {
|
|
525
|
-
const rawUrlInfo = rawGraph.getUrlInfo(versionedUrlInfo.data.rawUrl)
|
|
526
|
-
const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
|
|
527
|
-
return {
|
|
528
|
-
originalContent: rawUrlInfo
|
|
529
|
-
? rawUrlInfo.originalContent
|
|
530
|
-
: undefined,
|
|
531
|
-
sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
|
|
532
|
-
contentType: versionedUrlInfo.contentType,
|
|
533
|
-
content: versionedUrlInfo.content,
|
|
534
|
-
}
|
|
535
|
-
},
|
|
536
|
-
plugins: [
|
|
537
|
-
jsenvPluginInline({
|
|
538
|
-
allowEscapeForVersioning: true,
|
|
539
|
-
}),
|
|
540
|
-
{
|
|
541
|
-
name: "jsenv:versioning",
|
|
542
|
-
appliesDuring: { build: true },
|
|
543
|
-
resolve: ({ parentUrl, specifier }) => {
|
|
544
|
-
const buildUrl = buildUrls[specifier]
|
|
545
|
-
if (buildUrl) {
|
|
546
|
-
return buildUrl
|
|
547
|
-
}
|
|
548
|
-
const url = new URL(specifier, parentUrl).href
|
|
549
|
-
return url
|
|
550
|
-
},
|
|
551
|
-
formatReferencedUrl: (reference) => {
|
|
552
|
-
if (reference.isInline) {
|
|
553
|
-
return null
|
|
554
|
-
}
|
|
555
|
-
// specifier comes from "normalize" hook done a bit earlier in this file
|
|
556
|
-
// we want to get back their build url to access their infos
|
|
557
|
-
const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
|
|
558
|
-
if (referencedUrlInfo.data.isEntryPoint) {
|
|
559
|
-
return reference.specifier
|
|
560
|
-
}
|
|
561
|
-
// data:* urls and so on
|
|
562
|
-
if (!referencedUrlInfo.url.startsWith("file:")) {
|
|
563
|
-
return null
|
|
564
|
-
}
|
|
565
|
-
const versionedUrl = referencedUrlInfo.data.versionedUrl
|
|
566
|
-
if (!versionedUrl) {
|
|
567
|
-
// happens for sourcemap
|
|
568
|
-
return `${baseUrl}${urlToRelativeUrl(
|
|
569
|
-
referencedUrlInfo.url,
|
|
570
|
-
buildDirectoryUrl,
|
|
571
|
-
)}`
|
|
572
|
-
}
|
|
573
|
-
const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
|
|
574
|
-
versionedUrl,
|
|
575
|
-
buildDirectoryUrl,
|
|
576
|
-
)}`
|
|
577
|
-
versionMappings[reference.specifier] = versionedSpecifier
|
|
578
|
-
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
579
|
-
if (parentUrlInfo.jsQuote) {
|
|
580
|
-
// the url is inline inside js quotes
|
|
581
|
-
usedVersionMappings.push(reference.specifier)
|
|
582
|
-
return () =>
|
|
583
|
-
`${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
|
|
584
|
-
reference.specifier,
|
|
585
|
-
)})+${parentUrlInfo.jsQuote}`
|
|
586
|
-
}
|
|
587
|
-
if (
|
|
588
|
-
reference.type === "js_import_meta_url_pattern" ||
|
|
589
|
-
reference.subtype === "import_dynamic"
|
|
590
|
-
) {
|
|
591
|
-
usedVersionMappings.push(reference.specifier)
|
|
592
|
-
return () => `__v__(${JSON.stringify(reference.specifier)})`
|
|
593
|
-
}
|
|
594
|
-
return versionedSpecifier
|
|
595
|
-
},
|
|
596
|
-
load: ({ url }) => {
|
|
597
|
-
const urlInfo = finalGraph.getUrlInfo(url)
|
|
598
|
-
return {
|
|
599
|
-
originalContent: urlInfo.originalContent,
|
|
600
|
-
contentType: urlInfo.contentType,
|
|
601
|
-
content: urlInfo.content,
|
|
602
|
-
sourcemap: urlInfo.sourcemap,
|
|
603
|
-
}
|
|
604
|
-
},
|
|
605
|
-
},
|
|
606
|
-
],
|
|
607
|
-
scenario: "build",
|
|
608
|
-
sourcemaps,
|
|
609
|
-
})
|
|
610
|
-
// arrange state before reloading all files
|
|
611
|
-
Object.keys(finalGraph.urlInfos).forEach((url) => {
|
|
612
|
-
const urlInfo = finalGraph.urlInfos[url]
|
|
613
|
-
urlInfo.data.promise = null
|
|
614
|
-
})
|
|
615
|
-
await loadUrlGraph({
|
|
616
|
-
urlGraph: finalGraph,
|
|
617
|
-
kitchen: versioningKitchen,
|
|
618
|
-
runtimeSupport,
|
|
619
|
-
startLoading: loadEntryFiles,
|
|
620
|
-
})
|
|
621
|
-
if (usedVersionMappings.length) {
|
|
622
|
-
const versionMappingsNeeded = {}
|
|
623
|
-
usedVersionMappings.forEach((specifier) => {
|
|
624
|
-
versionMappingsNeeded[specifier] = versionMappings[specifier]
|
|
625
|
-
})
|
|
626
|
-
await Promise.all(
|
|
627
|
-
Object.keys(finalGraph.urlInfos).map(async (buildUrl) => {
|
|
628
|
-
const buildUrlInfo = finalGraph.getUrlInfo(buildUrl)
|
|
629
|
-
if (!buildUrlInfo.data.isEntryPoint) {
|
|
630
|
-
return
|
|
631
|
-
}
|
|
632
|
-
await injectVersionMappings(buildUrlInfo, {
|
|
633
|
-
kitchen: finalGraphKitchen,
|
|
634
|
-
versionMappings: versionMappingsNeeded,
|
|
635
|
-
})
|
|
636
|
-
}),
|
|
637
|
-
)
|
|
638
|
-
}
|
|
639
|
-
} catch (e) {
|
|
640
|
-
versioningTask.fail()
|
|
641
|
-
throw e
|
|
642
|
-
}
|
|
643
|
-
versioningTask.done()
|
|
629
|
+
if (versioning) {
|
|
630
|
+
await applyUrlVersioning({
|
|
631
|
+
logger,
|
|
632
|
+
buildDirectoryUrl,
|
|
633
|
+
rawUrls,
|
|
634
|
+
buildUrls,
|
|
635
|
+
baseUrl,
|
|
636
|
+
postBuildEntryUrls,
|
|
637
|
+
sourcemaps,
|
|
638
|
+
runtimeCompat,
|
|
639
|
+
rawGraph,
|
|
640
|
+
finalGraph,
|
|
641
|
+
finalGraphKitchen,
|
|
642
|
+
lineBreakNormalization,
|
|
643
|
+
versioningMethod,
|
|
644
|
+
})
|
|
644
645
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
const buildInlineFileContents = {}
|
|
648
|
-
const buildManifest = {}
|
|
649
|
-
Object.keys(finalGraph.urlInfos).forEach((url) => {
|
|
650
|
-
if (!url.startsWith("file:")) {
|
|
646
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
647
|
+
if (!urlInfo.url.startsWith("file:")) {
|
|
651
648
|
return
|
|
652
649
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
const useVersionedUrl = versionedUrl && !buildUrlInfo.data.isEntryPoint
|
|
656
|
-
const buildUrl = useVersionedUrl ? versionedUrl : buildUrlInfo.url
|
|
657
|
-
if (!urlIsInsideOf(buildUrl, buildDirectoryUrl)) {
|
|
658
|
-
throw new Error(`build url outside build directory`)
|
|
650
|
+
if (urlInfo.external) {
|
|
651
|
+
return
|
|
659
652
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
653
|
+
if (urlInfo.type === "html") {
|
|
654
|
+
const htmlAst = parseHtmlString(urlInfo.content, {
|
|
655
|
+
storeOriginalPositions: false,
|
|
656
|
+
})
|
|
657
|
+
urlInfo.content = stringifyHtmlAst(htmlAst, {
|
|
658
|
+
removeOriginalPositionAttributes: true,
|
|
659
|
+
})
|
|
665
660
|
}
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
)
|
|
671
|
-
|
|
661
|
+
const version = urlInfo.data.version
|
|
662
|
+
const useVersionedUrl = version && canUseVersionedUrl(urlInfo, finalGraph)
|
|
663
|
+
const buildUrl = useVersionedUrl ? urlInfo.data.versionedUrl : urlInfo.url
|
|
664
|
+
const buildUrlSpecifier = Object.keys(buildUrls).find(
|
|
665
|
+
(key) => buildUrls[key] === buildUrl,
|
|
666
|
+
)
|
|
667
|
+
urlInfo.data.buildUrl = buildUrl
|
|
668
|
+
urlInfo.data.buildUrlIsVersioned = useVersionedUrl
|
|
669
|
+
urlInfo.data.buildUrlSpecifier = buildUrlSpecifier
|
|
670
|
+
})
|
|
671
|
+
await resyncRessourceHints({
|
|
672
|
+
finalGraphKitchen,
|
|
673
|
+
finalGraph,
|
|
674
|
+
rawUrls,
|
|
675
|
+
buildUrls,
|
|
676
|
+
})
|
|
677
|
+
const cleanupActions = []
|
|
678
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
679
|
+
// nothing uses this url anymore
|
|
680
|
+
// - versioning update inline content
|
|
681
|
+
// - file converted for import assertion of js_classic conversion
|
|
682
|
+
if (
|
|
683
|
+
!urlInfo.data.isEntryPoint &&
|
|
684
|
+
urlInfo.type !== "sourcemap" &&
|
|
685
|
+
urlInfo.dependents.size === 0
|
|
686
|
+
) {
|
|
687
|
+
cleanupActions.push(() => {
|
|
688
|
+
delete finalGraph.urlInfos[urlInfo.url]
|
|
689
|
+
})
|
|
672
690
|
}
|
|
673
691
|
})
|
|
692
|
+
cleanupActions.forEach((cleanupAction) => cleanupAction())
|
|
693
|
+
await injectServiceWorkerUrls({
|
|
694
|
+
finalGraphKitchen,
|
|
695
|
+
finalGraph,
|
|
696
|
+
lineBreakNormalization,
|
|
697
|
+
})
|
|
674
698
|
logger.debug(
|
|
675
699
|
`graph urls post-versioning:
|
|
676
700
|
${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
677
701
|
)
|
|
678
702
|
|
|
703
|
+
const buildManifest = {}
|
|
704
|
+
const buildFileContents = {}
|
|
705
|
+
const buildInlineContents = {}
|
|
706
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
707
|
+
if (urlInfo.external) {
|
|
708
|
+
return
|
|
709
|
+
}
|
|
710
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
711
|
+
return
|
|
712
|
+
}
|
|
713
|
+
const buildRelativeUrl = urlToRelativeUrl(
|
|
714
|
+
urlInfo.data.buildUrl,
|
|
715
|
+
buildDirectoryUrl,
|
|
716
|
+
)
|
|
717
|
+
if (urlInfo.isInline) {
|
|
718
|
+
buildInlineContents[buildRelativeUrl] = urlInfo.content
|
|
719
|
+
} else {
|
|
720
|
+
buildFileContents[buildRelativeUrl] = urlInfo.content
|
|
721
|
+
}
|
|
722
|
+
const buildRelativeUrlWithoutVersioning = urlToRelativeUrl(
|
|
723
|
+
urlInfo.url,
|
|
724
|
+
buildDirectoryUrl,
|
|
725
|
+
)
|
|
726
|
+
buildManifest[buildRelativeUrlWithoutVersioning] = buildRelativeUrl
|
|
727
|
+
})
|
|
679
728
|
if (writeOnFileSystem) {
|
|
680
729
|
if (buildDirectoryClean) {
|
|
681
730
|
await ensureEmptyDirectory(buildDirectoryUrl)
|
|
@@ -689,17 +738,253 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
689
738
|
)
|
|
690
739
|
}),
|
|
691
740
|
)
|
|
741
|
+
if (versioning && assetManifest && Object.keys(buildManifest).length) {
|
|
742
|
+
await writeFile(
|
|
743
|
+
new URL(assetManifestFileRelativeUrl, buildDirectoryUrl),
|
|
744
|
+
JSON.stringify(buildManifest, null, " "),
|
|
745
|
+
)
|
|
746
|
+
}
|
|
692
747
|
}
|
|
693
748
|
logger.info(createUrlGraphSummary(finalGraph, { title: "build files" }))
|
|
694
749
|
return {
|
|
695
750
|
buildFileContents,
|
|
696
|
-
|
|
751
|
+
buildInlineContents,
|
|
697
752
|
buildManifest,
|
|
698
753
|
}
|
|
699
754
|
}
|
|
700
755
|
|
|
701
|
-
const
|
|
702
|
-
|
|
756
|
+
const applyUrlVersioning = async ({
|
|
757
|
+
logger,
|
|
758
|
+
buildDirectoryUrl,
|
|
759
|
+
rawUrls,
|
|
760
|
+
buildUrls,
|
|
761
|
+
baseUrl,
|
|
762
|
+
postBuildEntryUrls,
|
|
763
|
+
sourcemaps,
|
|
764
|
+
runtimeCompat,
|
|
765
|
+
rawGraph,
|
|
766
|
+
finalGraph,
|
|
767
|
+
finalGraphKitchen,
|
|
768
|
+
lineBreakNormalization,
|
|
769
|
+
versioningMethod,
|
|
770
|
+
}) => {
|
|
771
|
+
const versioningTask = createTaskLog(logger, "inject version in urls")
|
|
772
|
+
try {
|
|
773
|
+
const urlsSorted = sortUrlGraphByDependencies(finalGraph)
|
|
774
|
+
urlsSorted.forEach((url) => {
|
|
775
|
+
if (url.startsWith("data:")) {
|
|
776
|
+
return
|
|
777
|
+
}
|
|
778
|
+
const urlInfo = finalGraph.getUrlInfo(url)
|
|
779
|
+
if (urlInfo.type === "sourcemap") {
|
|
780
|
+
return
|
|
781
|
+
}
|
|
782
|
+
// ignore:
|
|
783
|
+
// - inline files:
|
|
784
|
+
// they are already taken into account in the file where they appear
|
|
785
|
+
// - external files
|
|
786
|
+
// we don't know their content
|
|
787
|
+
// - unused files without reference
|
|
788
|
+
// File updated such as style.css -> style.css.js or file.js->file.es5.js
|
|
789
|
+
// Are used at some point just to be discarded later because they need to be converted
|
|
790
|
+
// There is no need to version them and we could not because the file have been ignored
|
|
791
|
+
// so their content is unknown
|
|
792
|
+
if (urlInfo.isInline) {
|
|
793
|
+
return
|
|
794
|
+
}
|
|
795
|
+
if (urlInfo.external) {
|
|
796
|
+
return
|
|
797
|
+
}
|
|
798
|
+
if (!urlInfo.data.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
799
|
+
return
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
const urlContent =
|
|
803
|
+
urlInfo.type === "html"
|
|
804
|
+
? stringifyHtmlAst(
|
|
805
|
+
parseHtmlString(urlInfo.content, {
|
|
806
|
+
storeOriginalPositions: false,
|
|
807
|
+
}),
|
|
808
|
+
{ removeOriginalPositionAttributes: true },
|
|
809
|
+
)
|
|
810
|
+
: urlInfo.content
|
|
811
|
+
const versionGenerator = createVersionGenerator()
|
|
812
|
+
versionGenerator.augmentWithContent({
|
|
813
|
+
content: urlContent,
|
|
814
|
+
contentType: urlInfo.contentType,
|
|
815
|
+
lineBreakNormalization,
|
|
816
|
+
})
|
|
817
|
+
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
818
|
+
// this dependency is inline (data:) or remote (http://, https://)
|
|
819
|
+
if (!dependencyUrl.startsWith("file:")) {
|
|
820
|
+
return
|
|
821
|
+
}
|
|
822
|
+
const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
|
|
823
|
+
if (
|
|
824
|
+
// this content is part of the file, no need to take into account twice
|
|
825
|
+
dependencyUrlInfo.isInline ||
|
|
826
|
+
// this dependency content is not known
|
|
827
|
+
dependencyUrlInfo.external
|
|
828
|
+
) {
|
|
829
|
+
return
|
|
830
|
+
}
|
|
831
|
+
if (dependencyUrlInfo.data.version) {
|
|
832
|
+
versionGenerator.augmentWithDependencyVersion(
|
|
833
|
+
dependencyUrlInfo.data.version,
|
|
834
|
+
)
|
|
835
|
+
} else {
|
|
836
|
+
// because all dependencies are know, if the dependency has no version
|
|
837
|
+
// it means there is a circular dependency between this file
|
|
838
|
+
// and it's dependency
|
|
839
|
+
// in that case we'll use the dependency content
|
|
840
|
+
versionGenerator.augmentWithContent({
|
|
841
|
+
content: dependencyUrlInfo.content,
|
|
842
|
+
contentType: dependencyUrlInfo.contentType,
|
|
843
|
+
lineBreakNormalization,
|
|
844
|
+
})
|
|
845
|
+
}
|
|
846
|
+
})
|
|
847
|
+
urlInfo.data.version = versionGenerator.generate()
|
|
848
|
+
|
|
849
|
+
urlInfo.data.versionedUrl = injectVersionIntoBuildUrl({
|
|
850
|
+
buildUrl: urlInfo.url,
|
|
851
|
+
version: urlInfo.data.version,
|
|
852
|
+
versioningMethod,
|
|
853
|
+
})
|
|
854
|
+
})
|
|
855
|
+
const versionMappings = {}
|
|
856
|
+
const usedVersionMappings = []
|
|
857
|
+
const versioningKitchen = createKitchen({
|
|
858
|
+
logger,
|
|
859
|
+
rootDirectoryUrl: buildDirectoryUrl,
|
|
860
|
+
urlGraph: finalGraph,
|
|
861
|
+
scenario: "build",
|
|
862
|
+
sourcemaps,
|
|
863
|
+
runtimeCompat,
|
|
864
|
+
plugins: [
|
|
865
|
+
jsenvPluginUrlReferences(),
|
|
866
|
+
jsenvPluginInline({
|
|
867
|
+
fetchInlineUrls: false,
|
|
868
|
+
analyzeConvertedScripts: true, // to be able to version their urls
|
|
869
|
+
allowEscapeForVersioning: true,
|
|
870
|
+
}),
|
|
871
|
+
{
|
|
872
|
+
name: "jsenv:versioning",
|
|
873
|
+
appliesDuring: { build: true },
|
|
874
|
+
resolveUrl: (reference) => {
|
|
875
|
+
if (reference.specifier[0] === "#") {
|
|
876
|
+
reference.external = true
|
|
877
|
+
}
|
|
878
|
+
const buildUrl = buildUrls[reference.specifier]
|
|
879
|
+
if (buildUrl) {
|
|
880
|
+
return buildUrl
|
|
881
|
+
}
|
|
882
|
+
const url = new URL(reference.specifier, reference.parentUrl).href
|
|
883
|
+
return url
|
|
884
|
+
},
|
|
885
|
+
formatUrl: (reference) => {
|
|
886
|
+
if (reference.isInline) {
|
|
887
|
+
return null
|
|
888
|
+
}
|
|
889
|
+
// specifier comes from "normalize" hook done a bit earlier in this file
|
|
890
|
+
// we want to get back their build url to access their infos
|
|
891
|
+
const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
|
|
892
|
+
if (!canUseVersionedUrl(referencedUrlInfo)) {
|
|
893
|
+
return reference.specifier
|
|
894
|
+
}
|
|
895
|
+
// data:* urls and so on
|
|
896
|
+
if (!referencedUrlInfo.url.startsWith("file:")) {
|
|
897
|
+
return null
|
|
898
|
+
}
|
|
899
|
+
const versionedUrl = referencedUrlInfo.data.versionedUrl
|
|
900
|
+
if (!versionedUrl) {
|
|
901
|
+
// happens for sourcemap
|
|
902
|
+
return `${baseUrl}${urlToRelativeUrl(
|
|
903
|
+
referencedUrlInfo.url,
|
|
904
|
+
buildDirectoryUrl,
|
|
905
|
+
)}`
|
|
906
|
+
}
|
|
907
|
+
const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
|
|
908
|
+
versionedUrl,
|
|
909
|
+
buildDirectoryUrl,
|
|
910
|
+
)}`
|
|
911
|
+
versionMappings[reference.specifier] = versionedSpecifier
|
|
912
|
+
buildUrls[versionedSpecifier] = versionedUrl
|
|
913
|
+
|
|
914
|
+
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
915
|
+
if (parentUrlInfo.jsQuote) {
|
|
916
|
+
// the url is inline inside js quotes
|
|
917
|
+
usedVersionMappings.push(reference.specifier)
|
|
918
|
+
return () =>
|
|
919
|
+
`${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
|
|
920
|
+
reference.specifier,
|
|
921
|
+
)})+${parentUrlInfo.jsQuote}`
|
|
922
|
+
}
|
|
923
|
+
if (
|
|
924
|
+
reference.type === "js_url_specifier" ||
|
|
925
|
+
reference.subtype === "import_dynamic"
|
|
926
|
+
) {
|
|
927
|
+
usedVersionMappings.push(reference.specifier)
|
|
928
|
+
return () => `__v__(${JSON.stringify(reference.specifier)})`
|
|
929
|
+
}
|
|
930
|
+
return versionedSpecifier
|
|
931
|
+
},
|
|
932
|
+
fetchUrlContent: (versionedUrlInfo) => {
|
|
933
|
+
if (!versionedUrlInfo.url.startsWith("file:")) {
|
|
934
|
+
return { external: true }
|
|
935
|
+
}
|
|
936
|
+
if (versionedUrlInfo.isInline) {
|
|
937
|
+
const rawUrlInfo = rawGraph.getUrlInfo(
|
|
938
|
+
rawUrls[versionedUrlInfo.url],
|
|
939
|
+
)
|
|
940
|
+
const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
|
|
941
|
+
return {
|
|
942
|
+
originalContent: rawUrlInfo
|
|
943
|
+
? rawUrlInfo.originalContent
|
|
944
|
+
: undefined,
|
|
945
|
+
sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
|
|
946
|
+
contentType: versionedUrlInfo.contentType,
|
|
947
|
+
content: versionedUrlInfo.content,
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return versionedUrlInfo
|
|
951
|
+
},
|
|
952
|
+
},
|
|
953
|
+
],
|
|
954
|
+
})
|
|
955
|
+
await loadUrlGraph({
|
|
956
|
+
urlGraph: finalGraph,
|
|
957
|
+
kitchen: versioningKitchen,
|
|
958
|
+
startLoading: (cookEntryFile) => {
|
|
959
|
+
postBuildEntryUrls.forEach((postBuildEntryUrl) => {
|
|
960
|
+
cookEntryFile({
|
|
961
|
+
trace: `entryPoint`,
|
|
962
|
+
type: "entry_point",
|
|
963
|
+
specifier: postBuildEntryUrl,
|
|
964
|
+
})
|
|
965
|
+
})
|
|
966
|
+
},
|
|
967
|
+
})
|
|
968
|
+
if (usedVersionMappings.length) {
|
|
969
|
+
const versionMappingsNeeded = {}
|
|
970
|
+
usedVersionMappings.forEach((specifier) => {
|
|
971
|
+
versionMappingsNeeded[specifier] = versionMappings[specifier]
|
|
972
|
+
})
|
|
973
|
+
await injectGlobalVersionMapping({
|
|
974
|
+
finalGraphKitchen,
|
|
975
|
+
finalGraph,
|
|
976
|
+
versionMappings: versionMappingsNeeded,
|
|
977
|
+
})
|
|
978
|
+
}
|
|
979
|
+
} catch (e) {
|
|
980
|
+
versioningTask.fail()
|
|
981
|
+
throw e
|
|
982
|
+
}
|
|
983
|
+
versioningTask.done()
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
const injectVersionIntoBuildUrl = ({ buildUrl, version, versioningMethod }) => {
|
|
987
|
+
if (versioningMethod === "search_param") {
|
|
703
988
|
return injectQueryParams(buildUrl, {
|
|
704
989
|
v: version,
|
|
705
990
|
})
|
|
@@ -735,3 +1020,16 @@ const assertEntryPoints = ({ entryPoints }) => {
|
|
|
735
1020
|
}
|
|
736
1021
|
})
|
|
737
1022
|
}
|
|
1023
|
+
|
|
1024
|
+
const canUseVersionedUrl = (urlInfo) => {
|
|
1025
|
+
if (urlInfo.data.isEntryPoint) {
|
|
1026
|
+
return false
|
|
1027
|
+
}
|
|
1028
|
+
if (urlInfo.type === "webmanifest") {
|
|
1029
|
+
return false
|
|
1030
|
+
}
|
|
1031
|
+
if (urlInfo.subtype === "service_worker") {
|
|
1032
|
+
return !urlInfo.data.isWebWorkerEntryPoint
|
|
1033
|
+
}
|
|
1034
|
+
return true
|
|
1035
|
+
}
|