@stacksjs/stx 0.2.158 → 0.2.160
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-externalize.d.ts +33 -0
- package/dist/build-externalize.js +54 -37
- package/dist/cli.js +435 -435
- package/dist/craft.js +110 -110
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -0
- package/dist/pwa.js +74 -74
- package/dist/ssg.js +279 -279
- package/dist/variable-extractor.js +3 -3
- package/package.json +5 -5
|
@@ -18,6 +18,12 @@
|
|
|
18
18
|
* runtime is byte-identical everywhere and becomes a single asset, while
|
|
19
19
|
* per-page CSS dedupes only where pages genuinely share a stylesheet.
|
|
20
20
|
*
|
|
21
|
+
* The rewrite itself is `externalizeHtml`, which touches no filesystem. SSR has
|
|
22
|
+
* the same problem in a worse form — a static build inlines the runtime once
|
|
23
|
+
* per page, a server inlines it once per *request* — and it cannot use a
|
|
24
|
+
* post-pass over a directory because there are no files. Sharing the pure
|
|
25
|
+
* function means the two paths cannot drift into rewriting HTML differently.
|
|
26
|
+
*
|
|
21
27
|
* @module build-externalize
|
|
22
28
|
*/
|
|
23
29
|
/** Where externalized assets are written, relative to the output directory. */
|
|
@@ -30,6 +36,33 @@ export interface ExternalizeResult {
|
|
|
30
36
|
/** Bytes removed from HTML (before any compression). */
|
|
31
37
|
bytesInlined: number;
|
|
32
38
|
}
|
|
39
|
+
/** A blob lifted out of the HTML, ready to be written or served. */
|
|
40
|
+
export interface ExternalizedAsset {
|
|
41
|
+
/** Content-addressed filename, e.g. `runtime.1a2b3c4d.js`. */
|
|
42
|
+
filename: string;
|
|
43
|
+
contents: string;
|
|
44
|
+
/** MIME type, so a server can respond without re-deriving it from the name. */
|
|
45
|
+
contentType: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ExternalizeHtmlResult {
|
|
48
|
+
html: string;
|
|
49
|
+
/** Distinct assets this page referenced. Deduped within the page. */
|
|
50
|
+
assets: ExternalizedAsset[];
|
|
51
|
+
/** Bytes removed from the HTML, before any compression. */
|
|
52
|
+
bytesInlined: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Lift the shared blobs out of one HTML document.
|
|
56
|
+
*
|
|
57
|
+
* Pure: returns the rewritten HTML and the assets it extracted, and writes
|
|
58
|
+
* nothing. Callers decide whether those assets become files on disk or entries
|
|
59
|
+
* in a server's cache.
|
|
60
|
+
*
|
|
61
|
+
* Safe to run twice — a tag that is already a `src`/`href` reference has no
|
|
62
|
+
* inline body to match, so a second pass extracts nothing and returns the input
|
|
63
|
+
* unchanged.
|
|
64
|
+
*/
|
|
65
|
+
export declare function externalizeHtml(html: string, basePath?: string): ExternalizeHtmlResult;
|
|
33
66
|
/**
|
|
34
67
|
* Rewrite every HTML file under `outDir`, moving the signals runtime and the
|
|
35
68
|
* generated stylesheet into `_stx/` and linking to them.
|
|
@@ -18,46 +18,63 @@ function listHtmlFiles(dir) {
|
|
|
18
18
|
walk(dir);
|
|
19
19
|
return found;
|
|
20
20
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (!css.trim())
|
|
21
|
+
const BLOB_KINDS = [
|
|
22
|
+
{
|
|
23
|
+
pattern: /<script\b([^>]*\bdata-stx-runtime\b[^>]*)>([\s\S]*?)<\/script>/gi,
|
|
24
|
+
prefix: "runtime",
|
|
25
|
+
extension: "js",
|
|
26
|
+
contentType: "text/javascript; charset=utf-8",
|
|
27
|
+
replace: (href) => `<script data-stx-runtime src="${href}"></script>`
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
pattern: /<script\b([^>]*\bdata-stx-router\b[^>]*)>([\s\S]*?)<\/script>/gi,
|
|
31
|
+
prefix: "router",
|
|
32
|
+
extension: "js",
|
|
33
|
+
contentType: "text/javascript; charset=utf-8",
|
|
34
|
+
replace: (href) => `<script data-stx-router src="${href}"></script>`
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
pattern: /<style\b([^>]*\bdata-crosswind=(?:"generated"|'generated')[^>]*)>([\s\S]*?)<\/style>/gi,
|
|
38
|
+
prefix: "crosswind",
|
|
39
|
+
extension: "css",
|
|
40
|
+
contentType: "text/css; charset=utf-8",
|
|
41
|
+
replace: (href) => `<link data-crosswind="generated" rel="stylesheet" href="${href}">`
|
|
42
|
+
}
|
|
43
|
+
];
|
|
44
|
+
export function externalizeHtml(html, basePath = `/${EXTERNALIZED_ASSET_DIR}`) {
|
|
45
|
+
const assets = [], seen = new Set;
|
|
46
|
+
let bytesInlined = 0, out = html;
|
|
47
|
+
for (const kind of BLOB_KINDS)
|
|
48
|
+
out = out.replace(kind.pattern, (whole, attrs, body) => {
|
|
49
|
+
if (/\b(?:src|href)\s*=/.test(attrs) || !body.trim())
|
|
51
50
|
return whole;
|
|
52
|
-
const filename =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const filename = `${kind.prefix}.${contentHash(body)}.${kind.extension}`;
|
|
52
|
+
if (!seen.has(filename)) {
|
|
53
|
+
seen.add(filename);
|
|
54
|
+
assets.push({ filename, contents: body, contentType: kind.contentType });
|
|
55
|
+
}
|
|
56
|
+
bytesInlined += body.length;
|
|
57
|
+
return kind.replace(`${basePath}/${filename}`);
|
|
56
58
|
});
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
return { html: out, assets, bytesInlined };
|
|
60
|
+
}
|
|
61
|
+
export function externalizeSharedAssets(outDir) {
|
|
62
|
+
const result = { pages: 0, assets: 0, bytesInlined: 0 }, assetDir = path.join(outDir, EXTERNALIZED_ASSET_DIR), written = new Set;
|
|
63
|
+
for (const file of listHtmlFiles(outDir)) {
|
|
64
|
+
const original = fs.readFileSync(file, "utf8"), { html, assets, bytesInlined } = externalizeHtml(original);
|
|
65
|
+
if (html === original)
|
|
66
|
+
continue;
|
|
67
|
+
for (const asset of assets) {
|
|
68
|
+
if (written.has(asset.filename))
|
|
69
|
+
continue;
|
|
70
|
+
written.add(asset.filename);
|
|
71
|
+
fs.mkdirSync(assetDir, { recursive: !0 });
|
|
72
|
+
fs.writeFileSync(path.join(assetDir, asset.filename), asset.contents);
|
|
73
|
+
result.assets++;
|
|
60
74
|
}
|
|
75
|
+
fs.writeFileSync(file, html);
|
|
76
|
+
result.bytesInlined += bytesInlined;
|
|
77
|
+
result.pages++;
|
|
61
78
|
}
|
|
62
79
|
return result;
|
|
63
80
|
}
|