@jsenv/core 41.5.14 → 41.5.16
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/build/build.js +29 -4
- package/dist/start_dev_server/start_dev_server.js +33 -0
- package/package.json +2 -2
- package/src/build/build_urls_generator.js +12 -4
- package/src/dev/dev_server_plugins/dev_server_plugin_serve_source_files.js +16 -0
- package/src/kitchen/url_graph/url_graph.js +4 -0
- package/src/plugins/autoreload/jsenv_plugin_hot_search_param.js +13 -0
package/dist/build/build.js
CHANGED
|
@@ -2131,6 +2131,10 @@ const createUrlInfo = (url, context) => {
|
|
|
2131
2131
|
modifiedTimestamp: 0,
|
|
2132
2132
|
descendantModifiedTimestamp: 0,
|
|
2133
2133
|
dereferencedTimestamp: 0,
|
|
2134
|
+
// when a client last fetched this url outside a hot request; in other
|
|
2135
|
+
// words the last time this url entered a fresh page (see
|
|
2136
|
+
// jsenv_plugin_hot_search_param)
|
|
2137
|
+
servedWithoutHotTimestamp: 0,
|
|
2134
2138
|
originalContentEtag: null,
|
|
2135
2139
|
contentEtag: null,
|
|
2136
2140
|
isValid: () => false,
|
|
@@ -9445,6 +9449,7 @@ const jsenvPluginHotSearchParam = () => {
|
|
|
9445
9449
|
modifiedTimestamp,
|
|
9446
9450
|
descendantModifiedTimestamp,
|
|
9447
9451
|
dereferencedTimestamp,
|
|
9452
|
+
servedWithoutHotTimestamp,
|
|
9448
9453
|
} = referencedUrlInfo;
|
|
9449
9454
|
if (
|
|
9450
9455
|
!modifiedTimestamp &&
|
|
@@ -9468,6 +9473,18 @@ const jsenvPluginHotSearchParam = () => {
|
|
|
9468
9473
|
descendantModifiedTimestamp,
|
|
9469
9474
|
dereferencedTimestamp,
|
|
9470
9475
|
);
|
|
9476
|
+
// These timestamps say "this url changed at some point", not "the client
|
|
9477
|
+
// is running an outdated version of it": they are never cleared, so a
|
|
9478
|
+
// file modified once keeps them for the rest of the dev server's life.
|
|
9479
|
+
// A client that fetched this url after that modification (a page load:
|
|
9480
|
+
// see rememberServedWithoutHot in the dev server) already runs the
|
|
9481
|
+
// latest content. Sending it "?hot" then makes the browser evaluate a
|
|
9482
|
+
// second, identical copy of a module it already has — a second module
|
|
9483
|
+
// scope for a file that never changed, which breaks everything a module
|
|
9484
|
+
// holds once (registries, contexts, singletons).
|
|
9485
|
+
if (latestTimestamp <= servedWithoutHotTimestamp) {
|
|
9486
|
+
return null;
|
|
9487
|
+
}
|
|
9471
9488
|
return {
|
|
9472
9489
|
hot: latestTimestamp,
|
|
9473
9490
|
};
|
|
@@ -12193,8 +12210,16 @@ const createBuildUrlsGenerator = ({
|
|
|
12193
12210
|
// THAT bundle). They are told apart by the entry point they come from —
|
|
12194
12211
|
// sharing the file would leave one entry importing exports the file on disk
|
|
12195
12212
|
// does not have.
|
|
12213
|
+
//
|
|
12214
|
+
// A source file is shared between entry points only while they write it to
|
|
12215
|
+
// the same assets directory. Two entry points with their own directory each
|
|
12216
|
+
// get their own copy: the file lands where the entry point that references
|
|
12217
|
+
// it lands, so removing one entry point's directory takes nothing away from
|
|
12218
|
+
// another.
|
|
12196
12219
|
const insideBuildDirectory = urlIsOrIsInsideOf(url, buildDirectoryUrl);
|
|
12197
|
-
const key = insideBuildDirectory
|
|
12220
|
+
const key = insideBuildDirectory
|
|
12221
|
+
? `${entryKey} ${url}`
|
|
12222
|
+
: `${assetsDirectory} ${url}`;
|
|
12198
12223
|
const buildUrlFromMap = buildUrlMap.get(key);
|
|
12199
12224
|
if (buildUrlFromMap) {
|
|
12200
12225
|
return buildUrlFromMap;
|
|
@@ -12226,7 +12251,7 @@ const createBuildUrlsGenerator = ({
|
|
|
12226
12251
|
}
|
|
12227
12252
|
if (urlInfo.type === "entry_build") {
|
|
12228
12253
|
const buildUrl = new URL(urlInfo.filenameHint, buildDirectoryUrl).href;
|
|
12229
|
-
associateBuildUrl(
|
|
12254
|
+
associateBuildUrl(key, buildUrl);
|
|
12230
12255
|
return buildUrl;
|
|
12231
12256
|
}
|
|
12232
12257
|
if (
|
|
@@ -12244,7 +12269,7 @@ const createBuildUrlsGenerator = ({
|
|
|
12244
12269
|
const urlObject = new URL(url);
|
|
12245
12270
|
const { search } = urlObject;
|
|
12246
12271
|
const buildUrl = `${buildDirectoryUrl}${directoryPath}${search}`;
|
|
12247
|
-
associateBuildUrl(
|
|
12272
|
+
associateBuildUrl(key, buildUrl);
|
|
12248
12273
|
return buildUrl;
|
|
12249
12274
|
}
|
|
12250
12275
|
|
|
@@ -12259,7 +12284,7 @@ const createBuildUrlsGenerator = ({
|
|
|
12259
12284
|
let { search, hash } = urlObject;
|
|
12260
12285
|
const name = reserveName(directoryPath, getUrlName(url, urlInfo));
|
|
12261
12286
|
const buildUrl = `${buildDirectoryUrl}${directoryPath}${name}${search}${hash}`;
|
|
12262
|
-
associateBuildUrl(
|
|
12287
|
+
associateBuildUrl(key, buildUrl);
|
|
12263
12288
|
return buildUrl;
|
|
12264
12289
|
};
|
|
12265
12290
|
|
|
@@ -7170,6 +7170,7 @@ const jsenvPluginHotSearchParam = () => {
|
|
|
7170
7170
|
modifiedTimestamp,
|
|
7171
7171
|
descendantModifiedTimestamp,
|
|
7172
7172
|
dereferencedTimestamp,
|
|
7173
|
+
servedWithoutHotTimestamp,
|
|
7173
7174
|
} = referencedUrlInfo;
|
|
7174
7175
|
if (
|
|
7175
7176
|
!modifiedTimestamp &&
|
|
@@ -7193,6 +7194,18 @@ const jsenvPluginHotSearchParam = () => {
|
|
|
7193
7194
|
descendantModifiedTimestamp,
|
|
7194
7195
|
dereferencedTimestamp,
|
|
7195
7196
|
);
|
|
7197
|
+
// These timestamps say "this url changed at some point", not "the client
|
|
7198
|
+
// is running an outdated version of it": they are never cleared, so a
|
|
7199
|
+
// file modified once keeps them for the rest of the dev server's life.
|
|
7200
|
+
// A client that fetched this url after that modification (a page load:
|
|
7201
|
+
// see rememberServedWithoutHot in the dev server) already runs the
|
|
7202
|
+
// latest content. Sending it "?hot" then makes the browser evaluate a
|
|
7203
|
+
// second, identical copy of a module it already has — a second module
|
|
7204
|
+
// scope for a file that never changed, which breaks everything a module
|
|
7205
|
+
// holds once (registries, contexts, singletons).
|
|
7206
|
+
if (latestTimestamp <= servedWithoutHotTimestamp) {
|
|
7207
|
+
return null;
|
|
7208
|
+
}
|
|
7196
7209
|
return {
|
|
7197
7210
|
hot: latestTimestamp,
|
|
7198
7211
|
};
|
|
@@ -9675,6 +9688,10 @@ const createUrlInfo = (url, context) => {
|
|
|
9675
9688
|
modifiedTimestamp: 0,
|
|
9676
9689
|
descendantModifiedTimestamp: 0,
|
|
9677
9690
|
dereferencedTimestamp: 0,
|
|
9691
|
+
// when a client last fetched this url outside a hot request; in other
|
|
9692
|
+
// words the last time this url entered a fresh page (see
|
|
9693
|
+
// jsenv_plugin_hot_search_param)
|
|
9694
|
+
servedWithoutHotTimestamp: 0,
|
|
9678
9695
|
originalContentEtag: null,
|
|
9679
9696
|
contentEtag: null,
|
|
9680
9697
|
isValid: () => false,
|
|
@@ -11922,7 +11939,20 @@ const devServerPluginServeSourceFiles = ({
|
|
|
11922
11939
|
);
|
|
11923
11940
|
return response;
|
|
11924
11941
|
};
|
|
11942
|
+
// What the client holds for this url is what we last sent it: a
|
|
11943
|
+
// request without "?hot" is a page loading this url into an empty
|
|
11944
|
+
// module registry, so from here on the client runs this exact
|
|
11945
|
+
// content. Remembering when that happened is what allows
|
|
11946
|
+
// jsenv_plugin_hot_search_param to tell a modification the client
|
|
11947
|
+
// has already received from one it must re-execute to see.
|
|
11948
|
+
const rememberServedWithoutHot = () => {
|
|
11949
|
+
if (request.searchParams.has("hot")) {
|
|
11950
|
+
return;
|
|
11951
|
+
}
|
|
11952
|
+
urlInfo.servedWithoutHotTimestamp = Date.now();
|
|
11953
|
+
};
|
|
11925
11954
|
const respondWithNotModified = () => {
|
|
11955
|
+
rememberServedWithoutHot();
|
|
11926
11956
|
const headers = {
|
|
11927
11957
|
"cache-control": `private,max-age=0,must-revalidate`,
|
|
11928
11958
|
};
|
|
@@ -12007,6 +12037,9 @@ const devServerPluginServeSourceFiles = ({
|
|
|
12007
12037
|
) {
|
|
12008
12038
|
return respondWithNotModified();
|
|
12009
12039
|
}
|
|
12040
|
+
if (urlInfo.status === 200) {
|
|
12041
|
+
rememberServedWithoutHot();
|
|
12042
|
+
}
|
|
12010
12043
|
response = {
|
|
12011
12044
|
url: reference.url,
|
|
12012
12045
|
// a plugin can cook a complete response body for an url that is
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "41.5.
|
|
3
|
+
"version": "41.5.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Tool to develop, test and build js projects",
|
|
6
6
|
"repository": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "node --conditions=dev:jsenv ./scripts/build/build.mjs",
|
|
46
46
|
"build:file_size": "node ./scripts/build/build_file_size.mjs --log",
|
|
47
|
-
"build:packages": "npm run build --
|
|
47
|
+
"build:packages": "npm run build -- ./packages/",
|
|
48
48
|
"database:install": "npx @jsenv/database install",
|
|
49
49
|
"database:manage": "node --conditions=dev:jsenv ./packages/backend/database/src/cli/manage.js",
|
|
50
50
|
"database:setup": "npm run database:setup --workspaces --if-present --conditions=dev:jsenv",
|
|
@@ -59,8 +59,16 @@ export const createBuildUrlsGenerator = ({
|
|
|
59
59
|
// THAT bundle). They are told apart by the entry point they come from —
|
|
60
60
|
// sharing the file would leave one entry importing exports the file on disk
|
|
61
61
|
// does not have.
|
|
62
|
+
//
|
|
63
|
+
// A source file is shared between entry points only while they write it to
|
|
64
|
+
// the same assets directory. Two entry points with their own directory each
|
|
65
|
+
// get their own copy: the file lands where the entry point that references
|
|
66
|
+
// it lands, so removing one entry point's directory takes nothing away from
|
|
67
|
+
// another.
|
|
62
68
|
const insideBuildDirectory = urlIsOrIsInsideOf(url, buildDirectoryUrl);
|
|
63
|
-
const key = insideBuildDirectory
|
|
69
|
+
const key = insideBuildDirectory
|
|
70
|
+
? `${entryKey} ${url}`
|
|
71
|
+
: `${assetsDirectory} ${url}`;
|
|
64
72
|
const buildUrlFromMap = buildUrlMap.get(key);
|
|
65
73
|
if (buildUrlFromMap) {
|
|
66
74
|
return buildUrlFromMap;
|
|
@@ -92,7 +100,7 @@ export const createBuildUrlsGenerator = ({
|
|
|
92
100
|
}
|
|
93
101
|
if (urlInfo.type === "entry_build") {
|
|
94
102
|
const buildUrl = new URL(urlInfo.filenameHint, buildDirectoryUrl).href;
|
|
95
|
-
associateBuildUrl(
|
|
103
|
+
associateBuildUrl(key, buildUrl);
|
|
96
104
|
return buildUrl;
|
|
97
105
|
}
|
|
98
106
|
if (
|
|
@@ -110,7 +118,7 @@ export const createBuildUrlsGenerator = ({
|
|
|
110
118
|
const urlObject = new URL(url);
|
|
111
119
|
const { search } = urlObject;
|
|
112
120
|
const buildUrl = `${buildDirectoryUrl}${directoryPath}${search}`;
|
|
113
|
-
associateBuildUrl(
|
|
121
|
+
associateBuildUrl(key, buildUrl);
|
|
114
122
|
return buildUrl;
|
|
115
123
|
}
|
|
116
124
|
|
|
@@ -125,7 +133,7 @@ export const createBuildUrlsGenerator = ({
|
|
|
125
133
|
let { search, hash } = urlObject;
|
|
126
134
|
const name = reserveName(directoryPath, getUrlName(url, urlInfo));
|
|
127
135
|
const buildUrl = `${buildDirectoryUrl}${directoryPath}${name}${search}${hash}`;
|
|
128
|
-
associateBuildUrl(
|
|
136
|
+
associateBuildUrl(key, buildUrl);
|
|
129
137
|
return buildUrl;
|
|
130
138
|
};
|
|
131
139
|
|
|
@@ -387,7 +387,20 @@ export const devServerPluginServeSourceFiles = ({
|
|
|
387
387
|
);
|
|
388
388
|
return response;
|
|
389
389
|
};
|
|
390
|
+
// What the client holds for this url is what we last sent it: a
|
|
391
|
+
// request without "?hot" is a page loading this url into an empty
|
|
392
|
+
// module registry, so from here on the client runs this exact
|
|
393
|
+
// content. Remembering when that happened is what allows
|
|
394
|
+
// jsenv_plugin_hot_search_param to tell a modification the client
|
|
395
|
+
// has already received from one it must re-execute to see.
|
|
396
|
+
const rememberServedWithoutHot = () => {
|
|
397
|
+
if (request.searchParams.has("hot")) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
urlInfo.servedWithoutHotTimestamp = Date.now();
|
|
401
|
+
};
|
|
390
402
|
const respondWithNotModified = () => {
|
|
403
|
+
rememberServedWithoutHot();
|
|
391
404
|
const headers = {
|
|
392
405
|
"cache-control": `private,max-age=0,must-revalidate`,
|
|
393
406
|
};
|
|
@@ -472,6 +485,9 @@ export const devServerPluginServeSourceFiles = ({
|
|
|
472
485
|
) {
|
|
473
486
|
return respondWithNotModified();
|
|
474
487
|
}
|
|
488
|
+
if (urlInfo.status === 200) {
|
|
489
|
+
rememberServedWithoutHot();
|
|
490
|
+
}
|
|
475
491
|
response = {
|
|
476
492
|
url: reference.url,
|
|
477
493
|
// a plugin can cook a complete response body for an url that is
|
|
@@ -183,6 +183,10 @@ const createUrlInfo = (url, context) => {
|
|
|
183
183
|
modifiedTimestamp: 0,
|
|
184
184
|
descendantModifiedTimestamp: 0,
|
|
185
185
|
dereferencedTimestamp: 0,
|
|
186
|
+
// when a client last fetched this url outside a hot request; in other
|
|
187
|
+
// words the last time this url entered a fresh page (see
|
|
188
|
+
// jsenv_plugin_hot_search_param)
|
|
189
|
+
servedWithoutHotTimestamp: 0,
|
|
186
190
|
originalContentEtag: null,
|
|
187
191
|
contentEtag: null,
|
|
188
192
|
isValid: () => false,
|
|
@@ -48,6 +48,7 @@ export const jsenvPluginHotSearchParam = () => {
|
|
|
48
48
|
modifiedTimestamp,
|
|
49
49
|
descendantModifiedTimestamp,
|
|
50
50
|
dereferencedTimestamp,
|
|
51
|
+
servedWithoutHotTimestamp,
|
|
51
52
|
} = referencedUrlInfo;
|
|
52
53
|
if (
|
|
53
54
|
!modifiedTimestamp &&
|
|
@@ -71,6 +72,18 @@ export const jsenvPluginHotSearchParam = () => {
|
|
|
71
72
|
descendantModifiedTimestamp,
|
|
72
73
|
dereferencedTimestamp,
|
|
73
74
|
);
|
|
75
|
+
// These timestamps say "this url changed at some point", not "the client
|
|
76
|
+
// is running an outdated version of it": they are never cleared, so a
|
|
77
|
+
// file modified once keeps them for the rest of the dev server's life.
|
|
78
|
+
// A client that fetched this url after that modification (a page load:
|
|
79
|
+
// see rememberServedWithoutHot in the dev server) already runs the
|
|
80
|
+
// latest content. Sending it "?hot" then makes the browser evaluate a
|
|
81
|
+
// second, identical copy of a module it already has — a second module
|
|
82
|
+
// scope for a file that never changed, which breaks everything a module
|
|
83
|
+
// holds once (registries, contexts, singletons).
|
|
84
|
+
if (latestTimestamp <= servedWithoutHotTimestamp) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
74
87
|
return {
|
|
75
88
|
hot: latestTimestamp,
|
|
76
89
|
};
|