@jsenv/core 29.9.2 → 30.0.0-alpha.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "29.9.2",
3
+ "version": "30.0.0-alpha.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -69,6 +69,7 @@
69
69
  "@jsenv/abort": "4.2.4",
70
70
  "@jsenv/ast": "1.4.8",
71
71
  "@jsenv/babel-plugins": "1.1.0",
72
+ "@jsenv/plugin-bundling": "1.0.0",
72
73
  "@jsenv/filesystem": "4.1.6",
73
74
  "@jsenv/importmap": "1.2.1",
74
75
  "@jsenv/integrity": "0.0.1",
@@ -80,20 +81,16 @@
80
81
  "@jsenv/url-meta": "7.0.0",
81
82
  "@jsenv/urls": "1.2.8",
82
83
  "@jsenv/utils": "2.0.1",
83
- "acorn-import-assertions": "1.8.0",
84
84
  "construct-style-sheets-polyfill": "3.1.0",
85
85
  "cuid": "2.1.8",
86
- "html-minifier": "4.0.0",
87
86
  "istanbul-lib-coverage": "3.2.0",
88
87
  "istanbul-lib-instrument": "5.2.1",
89
88
  "istanbul-lib-report": "3.0.0",
90
89
  "istanbul-reports": "3.1.5",
91
90
  "launch-editor": "2.6.0",
92
91
  "pidtree": "0.6.0",
93
- "rollup": "3.7.4",
94
92
  "string-width": "5.1.2",
95
93
  "strip-ansi": "7.0.1",
96
- "terser": "5.16.1",
97
94
  "v8-to-istanbul": "9.0.1",
98
95
  "wrap-ansi": "8.0.1"
99
96
  },
@@ -105,7 +102,8 @@
105
102
  "@jsenv/file-size-impact": "13.0.2",
106
103
  "@jsenv/https-local": "3.0.1",
107
104
  "@jsenv/package-workspace": "0.5.1",
108
- "@jsenv/performance-impact": "3.0.2",
105
+ "@jsenv/plugin-minification": "1.0.0",
106
+ "@jsenv/performance-impact": "4.1.0",
109
107
  "eslint": "8.29.0",
110
108
  "eslint-plugin-html": "7.1.0",
111
109
  "eslint-plugin-import": "2.26.0",
@@ -32,6 +32,7 @@ import {
32
32
  ensureEmptyDirectory,
33
33
  writeFileSync,
34
34
  registerDirectoryLifecycle,
35
+ comparePathnames,
35
36
  } from "@jsenv/filesystem"
36
37
  import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
37
38
  import {
@@ -97,8 +98,6 @@ export const defaultRuntimeCompat = {
97
98
  * Directory where asset files will be written
98
99
  * @param {string|url} [buildParameters.base=""]
99
100
  * Urls in build file contents will be prefixed with this string
100
- * @param {boolean|object} [buildParameters.minification=true]
101
- * Minify build file contents
102
101
  * @param {boolean} [buildParameters.versioning=true]
103
102
  * Controls if url in build file contents are versioned
104
103
  * @param {('search_param'|'filename')} [buildParameters.versioningMethod="search_param"]
@@ -132,8 +131,6 @@ export const build = async ({
132
131
  fileSystemMagicRedirection,
133
132
  directoryReferenceAllowed,
134
133
  transpilation = {},
135
- bundling = true,
136
- minification = !runtimeCompat.node,
137
134
  versioning = !runtimeCompat.node,
138
135
  versioningMethod = "search_param", // "filename", "search_param"
139
136
  lineBreakNormalization = process.platform === "win32",
@@ -264,8 +261,6 @@ build ${entryPointKeys.length} entry points`)
264
261
  babelHelpersAsImport: !useExplicitJsClassicConversion,
265
262
  jsClassicFallback: false,
266
263
  },
267
- minification,
268
- bundling,
269
264
  }),
270
265
  ],
271
266
  sourcemaps,
@@ -1172,7 +1167,9 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1172
1167
  urlInfo,
1173
1168
  kitchen: finalGraphKitchen,
1174
1169
  versionMappings: versionMappingsNeeded,
1175
- minification,
1170
+ minification: plugins.some(
1171
+ (plugin) => plugin.name === "jsenv:minification",
1172
+ ),
1176
1173
  })
1177
1174
  })
1178
1175
  }
@@ -1428,8 +1425,15 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1428
1425
  }
1429
1426
 
1430
1427
  const buildManifest = {}
1431
- const buildFileContents = {}
1432
- const buildInlineContents = {}
1428
+ const buildContents = {}
1429
+ const buildInlineRelativeUrls = []
1430
+ const getBuildRelativeUrl = (url) => {
1431
+ const urlObject = new URL(url)
1432
+ urlObject.searchParams.delete("as_js_classic")
1433
+ url = urlObject.href
1434
+ const buildRelativeUrl = urlToRelativeUrl(url, buildDirectoryUrl)
1435
+ return buildRelativeUrl
1436
+ }
1433
1437
  GRAPH.forEach(finalGraph, (urlInfo) => {
1434
1438
  if (!urlInfo.shouldHandle) {
1435
1439
  return
@@ -1441,33 +1445,39 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
1441
1445
  return
1442
1446
  }
1443
1447
  if (urlInfo.isInline) {
1444
- const buildRelativeUrl = urlToRelativeUrl(
1445
- urlInfo.url,
1446
- buildDirectoryUrl,
1447
- )
1448
- buildInlineContents[buildRelativeUrl] = urlInfo.content
1448
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url)
1449
+ buildContents[buildRelativeUrl] = urlInfo.content
1450
+ buildInlineRelativeUrls.push(buildRelativeUrl)
1449
1451
  } else {
1450
1452
  const versionedUrl = versionedUrlMap.get(urlInfo.url)
1451
1453
  if (versionedUrl && canUseVersionedUrl(urlInfo)) {
1452
- const buildRelativeUrl = urlToRelativeUrl(
1453
- urlInfo.url,
1454
- buildDirectoryUrl,
1455
- )
1456
- const versionedBuildRelativeUrl = urlToRelativeUrl(
1457
- versionedUrl,
1458
- buildDirectoryUrl,
1459
- )
1460
- buildFileContents[versionedBuildRelativeUrl] = urlInfo.content
1454
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url)
1455
+ const versionedBuildRelativeUrl = getBuildRelativeUrl(versionedUrl)
1456
+ if (versioningMethod === "search_param") {
1457
+ buildContents[buildRelativeUrl] = urlInfo.content
1458
+ } else {
1459
+ buildContents[versionedBuildRelativeUrl] = urlInfo.content
1460
+ }
1461
1461
  buildManifest[buildRelativeUrl] = versionedBuildRelativeUrl
1462
1462
  } else {
1463
- const buildRelativeUrl = urlToRelativeUrl(
1464
- urlInfo.url,
1465
- buildDirectoryUrl,
1466
- )
1467
- buildFileContents[buildRelativeUrl] = urlInfo.content
1463
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url)
1464
+ buildContents[buildRelativeUrl] = urlInfo.content
1468
1465
  }
1469
1466
  }
1470
1467
  })
1468
+ const buildFileContents = {}
1469
+ const buildInlineContents = {}
1470
+ Object.keys(buildContents)
1471
+ .sort((a, b) => comparePathnames(a, b))
1472
+ .forEach((buildRelativeUrl) => {
1473
+ if (buildInlineRelativeUrls.includes(buildRelativeUrl)) {
1474
+ buildInlineContents[buildRelativeUrl] =
1475
+ buildContents[buildRelativeUrl]
1476
+ } else {
1477
+ buildFileContents[buildRelativeUrl] = buildContents[buildRelativeUrl]
1478
+ }
1479
+ })
1480
+
1471
1481
  if (writeOnFileSystem) {
1472
1482
  if (directoryToClean) {
1473
1483
  await ensureEmptyDirectory(directoryToClean)
@@ -10,9 +10,6 @@ import { jsenvPluginCommonJsGlobals } from "./commonjs_globals/jsenv_plugin_comm
10
10
  import { jsenvPluginImportMetaScenarios } from "./import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js"
11
11
  import { jsenvPluginTranspilation } from "./transpilation/jsenv_plugin_transpilation.js"
12
12
  import { jsenvPluginNodeRuntime } from "./node_runtime/jsenv_plugin_node_runtime.js"
13
- // build only
14
- import { jsenvPluginBundling } from "./bundling/jsenv_plugin_bundling.js"
15
- import { jsenvPluginMinification } from "./minification/jsenv_plugin_minification.js"
16
13
  // autoreload
17
14
  import { jsenvPluginImportMetaHot } from "./import_meta_hot/jsenv_plugin_import_meta_hot.js"
18
15
  import { jsenvPluginAutoreload } from "./autoreload/jsenv_plugin_autoreload.js"
@@ -35,8 +32,6 @@ export const getCorePlugins = ({
35
32
  directoryReferenceAllowed,
36
33
  supervisor,
37
34
  transpilation = true,
38
- minification = false,
39
- bundling = false,
40
35
 
41
36
  clientMainFileUrl,
42
37
  clientAutoreload = false,
@@ -91,8 +86,6 @@ export const getCorePlugins = ({
91
86
  jsenvPluginImportMetaScenarios(),
92
87
 
93
88
  jsenvPluginNodeRuntime({ runtimeCompat }),
94
- jsenvPluginBundling(bundling),
95
- jsenvPluginMinification(minification),
96
89
 
97
90
  jsenvPluginImportMetaHot(),
98
91
  ...(clientAutoreload
@@ -1,6 +1,6 @@
1
- import { createUrlGraphLoader } from "@jsenv/core/src/kitchen/url_graph/url_graph_loader.js"
2
- import { bundleJsModules } from "@jsenv/core/src/plugins/bundling/js_module/bundle_js_modules.js"
1
+ import { bundleJsModules } from "@jsenv/plugin-bundling"
3
2
 
3
+ import { createUrlGraphLoader } from "@jsenv/core/src/kitchen/url_graph/url_graph_loader.js"
4
4
  import { convertJsModuleToJsClassic } from "./convert_js_module_to_js_classic.js"
5
5
 
6
6
  export const jsenvPluginAsJsClassicLibrary = ({
@@ -1,15 +1,15 @@
1
1
  import { pathToFileURL } from "node:url"
2
2
  import { injectJsImport } from "@jsenv/ast"
3
3
 
4
+ export const globalThisClientFileUrl = new URL(
5
+ "./client/global_this.js",
6
+ import.meta.url,
7
+ ).href
8
+
4
9
  export const babelPluginGlobalThisAsJsenvImport = (
5
10
  babel,
6
11
  { getImportSpecifier },
7
12
  ) => {
8
- const globalThisClientFileUrl = new URL(
9
- "./client/global_this.js",
10
- import.meta.url,
11
- ).href
12
-
13
13
  return {
14
14
  name: "global-this-as-jsenv-import",
15
15
  visitor: {
@@ -5,9 +5,18 @@ import { babelPluginInstrument } from "@jsenv/core/src/test/coverage/babel_plugi
5
5
  import { RUNTIME_COMPAT } from "@jsenv/core/src/kitchen/compat/runtime_compat.js"
6
6
  import { getBaseBabelPluginStructure } from "./helpers/babel_plugin_structure.js"
7
7
  import { babelPluginBabelHelpersAsJsenvImports } from "./helpers/babel_plugin_babel_helpers_as_jsenv_imports.js"
8
- import { babelPluginNewStylesheetAsJsenvImport } from "./new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js"
9
- import { babelPluginGlobalThisAsJsenvImport } from "./global_this/babel_plugin_global_this_as_jsenv_import.js"
10
- import { babelPluginRegeneratorRuntimeAsJsenvImport } from "./regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js"
8
+ import {
9
+ babelPluginNewStylesheetAsJsenvImport,
10
+ newStylesheetClientFileUrl,
11
+ } from "./new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js"
12
+ import {
13
+ babelPluginGlobalThisAsJsenvImport,
14
+ globalThisClientFileUrl,
15
+ } from "./global_this/babel_plugin_global_this_as_jsenv_import.js"
16
+ import {
17
+ babelPluginRegeneratorRuntimeAsJsenvImport,
18
+ regeneratorRuntimeClientFileUrl,
19
+ } from "./regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js"
11
20
 
12
21
  export const jsenvPluginBabel = ({
13
22
  getCustomBabelPlugins,
@@ -106,6 +115,17 @@ export const jsenvPluginBabel = ({
106
115
  return {
107
116
  name: "jsenv:babel",
108
117
  appliesDuring: "*",
118
+ transformUrlContent: (urlInfo) => {
119
+ if (urlInfo.url === regeneratorRuntimeClientFileUrl) {
120
+ urlInfo.data.isBabelClientFile = true
121
+ }
122
+ if (urlInfo.url === globalThisClientFileUrl) {
123
+ urlInfo.data.isBabelClientFile = true
124
+ }
125
+ if (urlInfo.url === newStylesheetClientFileUrl) {
126
+ urlInfo.data.isBabelClientFile = true
127
+ }
128
+ },
109
129
  finalizeUrlContent: {
110
130
  js_classic: transformWithBabel,
111
131
  js_module: transformWithBabel,
@@ -1,15 +1,15 @@
1
1
  import { pathToFileURL } from "node:url"
2
2
  import { injectJsImport } from "@jsenv/ast"
3
3
 
4
+ export const newStylesheetClientFileUrl = new URL(
5
+ "./client/new_stylesheet.js",
6
+ import.meta.url,
7
+ ).href
8
+
4
9
  export const babelPluginNewStylesheetAsJsenvImport = (
5
10
  babel,
6
11
  { getImportSpecifier },
7
12
  ) => {
8
- const newStylesheetClientFileUrl = new URL(
9
- "./client/new_stylesheet.js",
10
- import.meta.url,
11
- ).href
12
-
13
13
  return {
14
14
  name: "new-stylesheet-as-jsenv-import",
15
15
  visitor: {
@@ -1,15 +1,15 @@
1
1
  import { pathToFileURL } from "node:url"
2
2
  import { injectJsImport } from "@jsenv/ast"
3
3
 
4
+ export const regeneratorRuntimeClientFileUrl = new URL(
5
+ "./client/regenerator_runtime.js",
6
+ import.meta.url,
7
+ ).href
8
+
4
9
  export const babelPluginRegeneratorRuntimeAsJsenvImport = (
5
10
  babel,
6
11
  { getImportSpecifier },
7
12
  ) => {
8
- const regeneratorRuntimeClientFileUrl = new URL(
9
- "./client/regenerator_runtime.js",
10
- import.meta.url,
11
- ).href
12
-
13
13
  return {
14
14
  name: "regenerator-runtime-as-jsenv-import",
15
15
  visitor: {
@@ -1,21 +0,0 @@
1
- import { fileSystemPathToUrl, urlToFileSystemPath } from "@jsenv/urls"
2
-
3
- export const fileUrlConverter = {
4
- asFilePath: (fileUrl) => {
5
- const filePath = urlToFileSystemPath(fileUrl)
6
- const urlObject = new URL(fileUrl)
7
- const { searchParams } = urlObject
8
- return `${filePath}${stringifyQuery(searchParams)}`
9
- },
10
- asFileUrl: (filePath) => {
11
- return decodeURIComponent(fileSystemPathToUrl(filePath)).replace(
12
- /[=](?=&|$)/g,
13
- "",
14
- )
15
- },
16
- }
17
-
18
- const stringifyQuery = (searchParams) => {
19
- const search = searchParams.toString()
20
- return search ? `?${search}` : ""
21
- }
@@ -1,140 +0,0 @@
1
- /*
2
- * Each @import found in css is replaced by the file content
3
- * - There is no need to worry about urls (such as background-image: url())
4
- * because they are absolute (file://*) and will be made relative again by jsenv build
5
- * - The sourcemap are not generated but ideally they should be
6
- * It can be quite challenging, see "bundle_sourcemap.js"
7
- */
8
-
9
- import { createMagicSource } from "@jsenv/sourcemap"
10
- import { applyPostCss, postCssPluginUrlVisitor } from "@jsenv/ast"
11
-
12
- import { sortByDependencies } from "@jsenv/core/src/kitchen/url_graph/sort_by_dependencies.js"
13
-
14
- // Do not use until https://github.com/parcel-bundler/parcel-css/issues/181
15
- export const bundleCss = async ({ cssUrlInfos, context }) => {
16
- const bundledCssUrlInfos = {}
17
- const cssBundleInfos = await performCssBundling({
18
- cssEntryUrlInfos: cssUrlInfos,
19
- context,
20
- })
21
- cssUrlInfos.forEach((cssUrlInfo) => {
22
- bundledCssUrlInfos[cssUrlInfo.url] = {
23
- data: {
24
- bundlerName: "parcel",
25
- },
26
- contentType: "text/css",
27
- content: cssBundleInfos[cssUrlInfo.url].bundleContent,
28
- }
29
- })
30
- return bundledCssUrlInfos
31
- }
32
-
33
- const performCssBundling = async ({ cssEntryUrlInfos, context }) => {
34
- const cssBundleInfos = await loadCssUrls({
35
- cssEntryUrlInfos,
36
- context,
37
- })
38
- const cssUrlsSorted = sortByDependencies(cssBundleInfos)
39
- cssUrlsSorted.forEach((cssUrl) => {
40
- const cssBundleInfo = cssBundleInfos[cssUrl]
41
- const magicSource = createMagicSource(cssBundleInfo.content)
42
- cssBundleInfo.cssUrls.forEach((cssUrl) => {
43
- if (cssUrl.type === "@import") {
44
- magicSource.replace({
45
- start: cssUrl.atRuleStart,
46
- end: cssUrl.atRuleEnd,
47
- replacement: cssBundleInfos[cssUrl.url].bundleContent,
48
- })
49
- }
50
- })
51
- const { content } = magicSource.toContentAndSourcemap()
52
- cssBundleInfo.bundleContent = content.trim()
53
- })
54
- return cssBundleInfos
55
- }
56
-
57
- const parseCssUrls = async ({ css, url }) => {
58
- const cssUrls = []
59
- await applyPostCss({
60
- sourcemaps: false,
61
- plugins: [
62
- postCssPluginUrlVisitor({
63
- urlVisitor: ({
64
- type,
65
- specifier,
66
- specifierStart,
67
- specifierEnd,
68
- atRuleStart,
69
- atRuleEnd,
70
- }) => {
71
- cssUrls.push({
72
- type,
73
- url: new URL(specifier, url).href,
74
- specifierStart,
75
- specifierEnd,
76
- atRuleStart,
77
- atRuleEnd,
78
- })
79
- },
80
- }),
81
- ],
82
- url,
83
- content: css,
84
- })
85
-
86
- return cssUrls
87
- }
88
-
89
- const loadCssUrls = async ({ cssEntryUrlInfos, context }) => {
90
- const cssBundleInfos = {}
91
- const promises = []
92
- const promiseMap = new Map()
93
-
94
- const load = (cssUrlInfo) => {
95
- const promiseFromData = promiseMap.get(cssUrlInfo.url)
96
- if (promiseFromData) return promiseFromData
97
- const promise = _load(cssUrlInfo)
98
- promises.push(promise)
99
- promiseMap.set(cssUrlInfo.url, promise)
100
- return promise
101
- }
102
-
103
- const _load = async (cssUrlInfo) => {
104
- const cssUrls = await parseCssUrls({
105
- css: cssUrlInfo.content,
106
- url: cssUrlInfo.url,
107
- })
108
- const cssBundleInfo = {
109
- content: cssUrlInfo.content,
110
- cssUrls,
111
- dependencies: [],
112
- }
113
- cssBundleInfos[cssUrlInfo.url] = cssBundleInfo
114
- cssUrls.forEach((cssUrl) => {
115
- if (cssUrl.type === "@import") {
116
- cssBundleInfo.dependencies.push(cssUrl.url)
117
- const importedCssUrlInfo = context.urlGraph.getUrlInfo(cssUrl.url)
118
- load(importedCssUrlInfo)
119
- }
120
- })
121
- }
122
-
123
- cssEntryUrlInfos.forEach((cssEntryUrlInfo) => {
124
- load(cssEntryUrlInfo)
125
- })
126
-
127
- const waitAll = async () => {
128
- if (promises.length === 0) {
129
- return
130
- }
131
- const promisesToWait = promises.slice()
132
- promises.length = 0
133
- await Promise.all(promisesToWait)
134
- await waitAll()
135
- }
136
- await waitAll()
137
- promiseMap.clear()
138
-
139
- return cssBundleInfos
140
- }
@@ -1,13 +0,0 @@
1
- /*
2
- * TODO:
3
- * for each js_classic where subtype is a worker
4
- * take the url info and find importScripts calls
5
- * and replace them with the corresponding url info file content
6
- * we'll ikely need to save the importScripts node location to be able to do that
7
- */
8
-
9
- // import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
10
-
11
- export const bundleJsClassicWorkers = () => {
12
- return {}
13
- }