utopian-minify 0.0.5

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/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # utopian-minify
2
+
3
+ A post-processing tool that creates dual builds with import maps for cross-origin dependency caching. It runs after your bundler's build, creates a second "mini" build with dependencies externalized to a CDN via import maps, and rewrites `index.html` to conditionally load the mini build when the [Sustainable Browser Extension](https://chromewebstore.google.com/detail/sustainable-browser/cdpbgdconlejjfnpifkpalpcfohmiolf) is installed.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -D utopian-minify
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Add to your `package.json` scripts:
14
+
15
+ ```json
16
+ {
17
+ "scripts": {
18
+ "build": "vite build",
19
+ "postbuild": "utopian-minify"
20
+ }
21
+ }
22
+ ```
23
+
24
+ The bundler is auto-detected from your config file (`vite.config.ts`, `webpack.config.js`, `rollup.config.mjs`, etc.).
25
+
26
+ ### CLI Options
27
+
28
+ ```bash
29
+ utopian-minify --bundler vite # explicit bundler override
30
+ utopian-minify --outDir dist # custom output directory
31
+ utopian-minify --exclude lodash,dayjs # exclude packages from externalization
32
+ utopian-minify --verbose # detailed logging
33
+ ```
34
+
35
+ | Option | Default | Description |
36
+ |--------|---------|-------------|
37
+ | `--bundler` | auto-detect | Bundler to use (`vite`, more coming) |
38
+ | `--root` | `cwd` | Project root directory |
39
+ | `--outDir` | `dist` | Build output directory |
40
+ | `--exclude` | none | Comma-separated packages to keep bundled |
41
+ | `--verbose` | off | Print detailed build info |
42
+
43
+ ## How It Works
44
+
45
+ 1. Reads your `package.json` dependencies and their exact installed versions from `node_modules`
46
+ 2. Runs a second build with all dependencies marked as external
47
+ 3. Scans the mini build output with [es-module-lexer](https://github.com/nicolo-ribaudo/es-module-lexer) to find the actual import specifiers used
48
+ 4. Generates an import map mapping each specifier to a `native://esm/{pkg}@{version}` URL
49
+ 5. Rewrites `index.html` with the import map and conditional loading:
50
+
51
+ ```html
52
+ <script type="importmap">
53
+ { "imports": { "react": "native://esm/react@18.3.1" } }
54
+ </script>
55
+ <script type="module">
56
+ if (window.NATIVE_SCHEME_SUPPORT) {
57
+ await import("/mini/index-abc123.js");
58
+ } else {
59
+ await import("/assets/index-abc123.js");
60
+ }
61
+ </script>
62
+ ```
63
+
64
+ ## Output
65
+
66
+ ```
67
+ dist/
68
+ ├── index.html # unified loader with import map
69
+ ├── assets/ # standard build (fallback)
70
+ │ ├── index-xxxxx.js
71
+ │ └── index-xxxxx.css
72
+ └── mini/ # externalized build
73
+ └── index-xxxxx.js
74
+ ```
75
+
76
+ ## Bundler Support
77
+
78
+ Currently supports **Vite**. Webpack and Rollup adapters are planned. The architecture uses a bundler adapter pattern — contributions for new adapters are welcome.
79
+
80
+ ## License
81
+
82
+ MIT
@@ -0,0 +1,4 @@
1
+ import type { BundlerAdapter } from "./types.js";
2
+ export declare function detectBundler(rootDir: string): string;
3
+ export declare function loadAdapter(bundlerName: string): Promise<BundlerAdapter>;
4
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/adapters/detect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAUjD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAYrD;AAED,wBAAsB,WAAW,CAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,CAYzB"}
@@ -0,0 +1,31 @@
1
+ import { existsSync } from "fs";
2
+ import { resolve } from "path";
3
+ const KNOWN_BUNDLERS = [
4
+ { name: "vite", configBase: "vite.config" },
5
+ { name: "webpack", configBase: "webpack.config" },
6
+ { name: "rollup", configBase: "rollup.config" },
7
+ ];
8
+ const CONFIG_EXTENSIONS = [".ts", ".js", ".mjs", ".mts"];
9
+ export function detectBundler(rootDir) {
10
+ for (const { name, configBase } of KNOWN_BUNDLERS) {
11
+ for (const ext of CONFIG_EXTENSIONS) {
12
+ if (existsSync(resolve(rootDir, configBase + ext))) {
13
+ return name;
14
+ }
15
+ }
16
+ }
17
+ throw new Error("Could not detect bundler. No vite.config.*, webpack.config.*, or rollup.config.* found.\n" +
18
+ "Use --bundler <name> to specify explicitly.");
19
+ }
20
+ export async function loadAdapter(bundlerName) {
21
+ switch (bundlerName) {
22
+ case "vite": {
23
+ const { createViteAdapter } = await import("./vite.js");
24
+ return createViteAdapter();
25
+ }
26
+ default:
27
+ throw new Error(`Unsupported bundler: "${bundlerName}". Currently supported: vite.\n` +
28
+ `Webpack and Rollup adapters are planned for a future release.`);
29
+ }
30
+ }
31
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/adapters/detect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,MAAM,cAAc,GAAG;IACrB,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE;IAC3C,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,EAAE;IACjD,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE;CAChD,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,KAAK,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,cAAc,EAAE,CAAC;QAClD,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,IAAI,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;gBACnD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CACb,2FAA2F;QACzF,6CAA6C,CAChD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,WAAmB;IAEnB,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YACxD,OAAO,iBAAiB,EAAE,CAAC;QAC7B,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CACb,yBAAyB,WAAW,iCAAiC;gBACnE,+DAA+D,CAClE,CAAC;IACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface BuildWithExternalsOptions {
2
+ rootDir: string;
3
+ outDir: string;
4
+ externals: string[];
5
+ configFile: string | false;
6
+ }
7
+ export interface BuildResult {
8
+ /** Relative path to the entry JS file within outDir, e.g. "assets/index-abc123.js" */
9
+ entryFile: string;
10
+ }
11
+ export interface ParsedBuildOutput {
12
+ stylePath: string;
13
+ headContent: string;
14
+ bodyContent: string;
15
+ }
16
+ export interface BundlerAdapter {
17
+ name: string;
18
+ configFileNames: string[];
19
+ buildWithExternals(options: BuildWithExternalsOptions): Promise<BuildResult>;
20
+ parseHtmlOutput(html: string): ParsedBuildOutput;
21
+ }
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAAC;CAClD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adapters/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { BundlerAdapter } from "./types.js";
2
+ export declare function createViteAdapter(): BundlerAdapter;
3
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../../src/adapters/vite.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,YAAY,CAAC;AAmCpB,wBAAgB,iBAAiB,IAAI,cAAc,CA4DlD"}
@@ -0,0 +1,72 @@
1
+ import { readdirSync } from "fs";
2
+ import { join } from "path";
3
+ function extractAdditionalHeadContent(html) {
4
+ const headMatch = html.match(/<head>([\s\S]*?)<\/head>/);
5
+ if (!headMatch || !headMatch[1])
6
+ return "";
7
+ const headContent = headMatch[1];
8
+ const lines = [];
9
+ const headLines = headContent.split("\n");
10
+ for (const line of headLines) {
11
+ const trimmed = line.trim();
12
+ if (trimmed.match(/<script type="module" crossorigin src="\/assets\//) ||
13
+ trimmed.match(/<link rel="stylesheet" crossorigin href="\/assets\//)) {
14
+ continue;
15
+ }
16
+ if (trimmed.length > 0) {
17
+ lines.push(line);
18
+ }
19
+ }
20
+ return lines.length > 0 ? "\n" + lines.join("\n") : "";
21
+ }
22
+ function extractBodyContent(html) {
23
+ const bodyMatch = html.match(/<body>([\s\S]*?)<\/body>/);
24
+ if (!bodyMatch || !bodyMatch[1])
25
+ return "";
26
+ return bodyMatch[1];
27
+ }
28
+ export function createViteAdapter() {
29
+ return {
30
+ name: "vite",
31
+ configFileNames: ["vite.config"],
32
+ async buildWithExternals(options) {
33
+ const { build: viteBuild } = await import("vite");
34
+ const config = {
35
+ root: options.rootDir,
36
+ mode: "production",
37
+ build: {
38
+ outDir: options.outDir,
39
+ emptyOutDir: true,
40
+ copyPublicDir: false,
41
+ rollupOptions: {
42
+ external: (id) => options.externals.some((dep) => id === dep || id.startsWith(dep + "/")),
43
+ output: {
44
+ format: "es",
45
+ entryFileNames: "assets/index-[hash].js",
46
+ chunkFileNames: "assets/[name]-[hash].js",
47
+ assetFileNames: "assets/[name]-[hash].[ext]",
48
+ },
49
+ },
50
+ },
51
+ configFile: options.configFile,
52
+ };
53
+ await viteBuild(config);
54
+ // Find the entry file produced by the build
55
+ const assetsDir = join(options.outDir, "assets");
56
+ const jsFiles = readdirSync(assetsDir).filter((f) => f.startsWith("index-") && f.endsWith(".js"));
57
+ if (jsFiles.length === 0) {
58
+ throw new Error("No entry JS file found in build output");
59
+ }
60
+ return { entryFile: `assets/${jsFiles[0]}` };
61
+ },
62
+ parseHtmlOutput(html) {
63
+ const styleMatch = html.match(/<link rel="stylesheet" crossorigin href="(\/assets\/[^"]+)">/);
64
+ return {
65
+ stylePath: styleMatch?.[1] || "",
66
+ headContent: extractAdditionalHeadContent(html),
67
+ bodyContent: extractBodyContent(html),
68
+ };
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../../src/adapters/vite.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ import { createDualBuild } from './postprocess.js';
3
+ import { detectBundler, loadAdapter } from './adapters/detect.js';
4
+ // Parse command line arguments
5
+ const args = process.argv.slice(2);
6
+ const options = {};
7
+ for (let i = 0; i < args.length; i++) {
8
+ const arg = args[i];
9
+ if (arg === '--verbose') {
10
+ options.verbose = true;
11
+ continue;
12
+ }
13
+ const key = arg?.replace('--', '');
14
+ const value = args[i + 1];
15
+ if (key === 'exclude' && value) {
16
+ options.exclude = value.split(',');
17
+ i++;
18
+ }
19
+ else if (key === 'root' && value) {
20
+ options.root = value;
21
+ i++;
22
+ }
23
+ else if (key === 'outDir' && value) {
24
+ options.outDir = value;
25
+ i++;
26
+ }
27
+ else if (key === 'bundler' && value) {
28
+ options.bundler = value;
29
+ i++;
30
+ }
31
+ }
32
+ // Default to current working directory as root (where the command is run)
33
+ if (!options.root) {
34
+ options.root = process.cwd();
35
+ }
36
+ const bundlerName = options.bundler || detectBundler(options.root);
37
+ const adapter = await loadAdapter(bundlerName);
38
+ createDualBuild(options, adapter)
39
+ .then(() => {
40
+ process.exit(0);
41
+ })
42
+ .catch((error) => {
43
+ console.error('Post-processing failed:', error);
44
+ process.exit(1);
45
+ });
46
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAUlE,+BAA+B;AAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAe,EAAE,CAAC;AAE/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEpB,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;QACxB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACvB,SAAS;IACX,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAE1B,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,EAAE,CAAC;QAC/B,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC,EAAE,CAAC;IACN,CAAC;SAAM,IAAI,GAAG,KAAK,MAAM,IAAI,KAAK,EAAE,CAAC;QACnC,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC;QACrB,CAAC,EAAE,CAAC;IACN,CAAC;SAAM,IAAI,GAAG,KAAK,QAAQ,IAAI,KAAK,EAAE,CAAC;QACrC,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;QACvB,CAAC,EAAE,CAAC;IACN,CAAC;SAAM,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,EAAE,CAAC;QACtC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;QACxB,CAAC,EAAE,CAAC;IACN,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAClB,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AAC/B,CAAC;AAED,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACnE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;AAE/C,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC;KAC9B,IAAI,CAAC,GAAG,EAAE;IACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;IAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { createDualBuild } from './postprocess.js';
2
+ export type { PostProcessOptions } from './postprocess.js';
3
+ export type { BundlerAdapter, BuildResult, BuildWithExternalsOptions, ParsedBuildOutput } from './adapters/types.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { createDualBuild } from './postprocess.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { BundlerAdapter } from "./adapters/types.js";
2
+ export interface PostProcessOptions {
3
+ root?: string;
4
+ outDir?: string;
5
+ exclude?: string[];
6
+ verbose?: boolean;
7
+ }
8
+ export declare function createDualBuild(options: PostProcessOptions | undefined, adapter: BundlerAdapter): Promise<void>;
9
+ //# sourceMappingURL=postprocess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postprocess.d.ts","sourceRoot":"","sources":["../src/postprocess.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA8LD,wBAAsB,eAAe,CACnC,OAAO,EAAE,kBAAkB,YAAK,EAChC,OAAO,EAAE,cAAc,iBAmLxB"}
@@ -0,0 +1,278 @@
1
+ import { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync, } from "fs";
2
+ import { join, resolve } from "path";
3
+ import { gzipSync } from "zlib";
4
+ import { init as initLexer, parse as parseImports } from "es-module-lexer";
5
+ function getInstalledVersions(rootPath, depNames, verbose) {
6
+ const versions = {};
7
+ for (const depName of depNames) {
8
+ const depPackageJsonPath = resolve(rootPath, "node_modules", depName, "package.json");
9
+ if (!existsSync(depPackageJsonPath)) {
10
+ throw new Error(`Could not find ${depName} in node_modules. Run your package manager's install command first.`);
11
+ }
12
+ const depPackageJson = JSON.parse(readFileSync(depPackageJsonPath, "utf-8"));
13
+ if (!depPackageJson.version) {
14
+ throw new Error(`No version field in ${depPackageJsonPath}`);
15
+ }
16
+ versions[depName] = depPackageJson.version;
17
+ if (verbose) {
18
+ console.log(` ${depName}@${depPackageJson.version}`);
19
+ }
20
+ }
21
+ return versions;
22
+ }
23
+ /**
24
+ * Gets runtime dependencies from package.json
25
+ */
26
+ async function getPackageJsonDependencies(rootPath) {
27
+ const dependencies = {};
28
+ try {
29
+ const packageJsonPath = resolve(rootPath, "package.json");
30
+ if (existsSync(packageJsonPath)) {
31
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
32
+ if (packageJson.dependencies) {
33
+ Object.assign(dependencies, packageJson.dependencies);
34
+ }
35
+ }
36
+ }
37
+ catch (error) {
38
+ console.warn("Warning: Could not read package.json:", error);
39
+ }
40
+ return dependencies;
41
+ }
42
+ /**
43
+ * Scans JS files for bare import specifiers that match externalized dependencies.
44
+ * Uses es-module-lexer for accurate parsing of minified ES module output.
45
+ * Returns all unique specifiers found (e.g. "react", "react/jsx-runtime").
46
+ */
47
+ async function collectExternalImports(jsDir, dependencies) {
48
+ const specifiers = new Set();
49
+ if (!existsSync(jsDir))
50
+ return specifiers;
51
+ await initLexer;
52
+ const files = readdirSync(jsDir).filter((f) => f.endsWith(".js"));
53
+ for (const file of files) {
54
+ const content = readFileSync(join(jsDir, file), "utf-8");
55
+ const [imports] = parseImports(content);
56
+ for (const imp of imports) {
57
+ const specifier = imp.n;
58
+ if (!specifier)
59
+ continue;
60
+ for (const dep of dependencies) {
61
+ if (specifier === dep || specifier.startsWith(dep + "/")) {
62
+ specifiers.add(specifier);
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ }
68
+ return specifiers;
69
+ }
70
+ /**
71
+ * Maps a bare specifier to its package name (handling scoped packages).
72
+ */
73
+ function specifierToPackageName(specifier) {
74
+ if (specifier.startsWith("@")) {
75
+ const parts = specifier.split("/");
76
+ return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : specifier;
77
+ }
78
+ return specifier.split("/")[0] || specifier;
79
+ }
80
+ /**
81
+ * Generates an import map with native://esm/ URLs for all import specifiers.
82
+ *
83
+ * Uses ?deps= to pin peerDependency versions on esm.sh. Unlike ?external=
84
+ * (which emits bare specifiers requiring import map resolution inside CDN
85
+ * modules — broken with native:// protocol), ?deps= makes esm.sh resolve
86
+ * dependencies internally via absolute URLs like /react@18.3.1/es2022/react.mjs.
87
+ * All CDN modules pinned to the same version share the same absolute URL,
88
+ * ensuring a single module instance without relying on the import map.
89
+ */
90
+ function generateImportMap(rootPath, specifiers, installedVersions, verbose) {
91
+ const importMap = {};
92
+ // Cache ?deps= params per package: pins peerDependencies to exact versions
93
+ const depsParamCache = {};
94
+ for (const specifier of specifiers) {
95
+ const packageName = specifierToPackageName(specifier);
96
+ const version = installedVersions[packageName];
97
+ if (!version) {
98
+ console.warn(`Warning: No version found for ${packageName}, skipping ${specifier}`);
99
+ continue;
100
+ }
101
+ if (!(packageName in depsParamCache)) {
102
+ const depPkgJsonPath = resolve(rootPath, "node_modules", packageName, "package.json");
103
+ let depsParam = "";
104
+ if (existsSync(depPkgJsonPath)) {
105
+ const depPkgJson = JSON.parse(readFileSync(depPkgJsonPath, "utf-8"));
106
+ const peerDeps = Object.keys(depPkgJson.peerDependencies || {});
107
+ const pinnedPeers = peerDeps
108
+ .filter((d) => d in installedVersions)
109
+ .map((d) => `${d}@${installedVersions[d]}`);
110
+ if (pinnedPeers.length > 0) {
111
+ depsParam = `?deps=${pinnedPeers.join(",")}`;
112
+ }
113
+ }
114
+ depsParamCache[packageName] = depsParam;
115
+ }
116
+ const depsParam = depsParamCache[packageName];
117
+ const subpath = specifier === packageName ? "" : specifier.slice(packageName.length);
118
+ importMap[specifier] = `native://esm/${packageName}@${version}${subpath}${depsParam}`;
119
+ if (verbose) {
120
+ console.log(` ${specifier} -> ${importMap[specifier]}`);
121
+ }
122
+ }
123
+ return importMap;
124
+ }
125
+ function findEntryFile(assetsDir) {
126
+ const jsFiles = readdirSync(assetsDir).filter((f) => f.startsWith("index-") && f.endsWith(".js"));
127
+ if (jsFiles.length === 0) {
128
+ throw new Error(`No entry JS file found in ${assetsDir}`);
129
+ }
130
+ return jsFiles[0];
131
+ }
132
+ const CONFIG_EXTENSIONS = [".ts", ".js", ".mjs", ".mts"];
133
+ function findConfigFile(rootDir, configFileNames) {
134
+ for (const base of configFileNames) {
135
+ for (const ext of CONFIG_EXTENSIONS) {
136
+ const p = resolve(rootDir, base + ext);
137
+ if (existsSync(p))
138
+ return p;
139
+ }
140
+ }
141
+ return false;
142
+ }
143
+ export async function createDualBuild(options = {}, adapter) {
144
+ const { root = process.cwd(), outDir = "dist", exclude = [], verbose = false, } = options;
145
+ const rootDir = resolve(root);
146
+ const outputDir = resolve(rootDir, outDir);
147
+ const miniDir = resolve(outputDir, "mini");
148
+ try {
149
+ // Get package.json dependencies (runtime only)
150
+ const packageJsonDeps = await getPackageJsonDependencies(rootDir);
151
+ const allDeps = Object.keys(packageJsonDeps);
152
+ // Filter out excluded packages
153
+ const depsToExternalize = allDeps.filter((dep) => !exclude.includes(dep));
154
+ if (depsToExternalize.length === 0) {
155
+ console.log("utopian-minify: No dependencies to externalize");
156
+ return;
157
+ }
158
+ // Read exact versions from node_modules
159
+ if (verbose)
160
+ console.log("Dependencies:");
161
+ const installedVersions = getInstalledVersions(rootDir, depsToExternalize, verbose);
162
+ console.log(`utopian-minify: Externalizing ${depsToExternalize.length} dependencies`);
163
+ // Check if build exists
164
+ if (!existsSync(outputDir)) {
165
+ console.error("Error: No build found at", outputDir);
166
+ console.error(" Please run 'vite build' first before post-processing");
167
+ return;
168
+ }
169
+ // Read existing build files
170
+ const standardIndexPath = join(outputDir, "index.html");
171
+ if (!existsSync(standardIndexPath)) {
172
+ console.error("Error: No index.html found in build directory");
173
+ return;
174
+ }
175
+ const standardHtml = readFileSync(standardIndexPath, "utf-8");
176
+ const standardOutput = adapter.parseHtmlOutput(standardHtml);
177
+ // Find standard build entry JS by scanning the assets directory
178
+ const standardAssetsDir = join(outputDir, "assets");
179
+ const standardEntryFile = findEntryFile(standardAssetsDir);
180
+ const standardScriptPath = `/assets/${standardEntryFile}`;
181
+ if (verbose) {
182
+ const standardScriptFullPath = join(standardAssetsDir, standardEntryFile);
183
+ const content = readFileSync(standardScriptFullPath);
184
+ const gzipped = gzipSync(content);
185
+ console.log(`Standard build script: ${standardScriptPath} (${gzipped.length} bytes gzipped)`);
186
+ }
187
+ // Detect bundler config file
188
+ const configFile = findConfigFile(rootDir, adapter.configFileNames);
189
+ // Run mini build with externalized dependencies
190
+ if (verbose) {
191
+ console.log("Building mini version with externalized dependencies...");
192
+ console.log("Dependencies to externalize:", depsToExternalize);
193
+ }
194
+ const buildResult = await adapter.buildWithExternals({
195
+ rootDir,
196
+ outDir: miniDir,
197
+ externals: depsToExternalize,
198
+ configFile,
199
+ });
200
+ if (verbose)
201
+ console.log("Mini build completed");
202
+ // Scan mini build output for actual external import specifiers
203
+ const miniAssetsDir = join(miniDir, "assets");
204
+ const externalSpecifiers = await collectExternalImports(miniAssetsDir, depsToExternalize);
205
+ if (verbose) {
206
+ console.log(`Found ${externalSpecifiers.size} external import specifiers`);
207
+ }
208
+ // With ?deps=, CDN modules resolve dependencies internally via absolute URLs,
209
+ // so only specifiers from the build output need import map entries.
210
+ // Adding unused deps could create duplicate modules (e.g. react-router loaded
211
+ // both via import map AND internally by react-router-dom from CDN).
212
+ // Generate import map for externalized specifiers
213
+ const importMap = generateImportMap(rootDir, externalSpecifiers, installedVersions, verbose);
214
+ // Mini build entry path (will be served from /mini/ in the final output)
215
+ const miniScriptPath = `/mini/${buildResult.entryFile.replace(/^assets\//, "")}`;
216
+ const miniIndexPath = join(miniDir, "index.html");
217
+ // Move mini assets to dist/mini and rename with file size
218
+ const targetMiniDir = join(outputDir, "mini");
219
+ if (existsSync(miniAssetsDir)) {
220
+ const assetFiles = readdirSync(miniAssetsDir);
221
+ mkdirSync(targetMiniDir, { recursive: true });
222
+ // Move only JavaScript files (CSS is the same as standard build)
223
+ const jsFiles = assetFiles.filter((file) => file.endsWith(".js"));
224
+ if (verbose)
225
+ console.log(`Moving ${jsFiles.length} JavaScript files`);
226
+ jsFiles.forEach((file) => {
227
+ const sourcePath = join(miniAssetsDir, file);
228
+ const targetPath = join(targetMiniDir, file);
229
+ cpSync(sourcePath, targetPath);
230
+ });
231
+ if (verbose) {
232
+ // Log gzip size of entry without renaming
233
+ const entryFileName = miniScriptPath.split("/").pop() || "";
234
+ const entryPath = join(targetMiniDir, entryFileName);
235
+ if (existsSync(entryPath)) {
236
+ const content = readFileSync(entryPath);
237
+ const gzipped = gzipSync(content);
238
+ console.log(`Mini build script: ${miniScriptPath} (${gzipped.length} bytes gzipped)`);
239
+ }
240
+ }
241
+ }
242
+ // Create the unified index.html with conditional loading
243
+ const unifiedHtml = `<!DOCTYPE html>
244
+ <html lang="en">
245
+ <head>
246
+ ${standardOutput.headContent}
247
+
248
+ <script type="importmap">
249
+ ${JSON.stringify({ imports: importMap }, null, 6)}
250
+ </script>
251
+
252
+ <script type="module">
253
+ if (window.NATIVE_SCHEME_SUPPORT) {
254
+ await import("${miniScriptPath}");
255
+ } else {
256
+ await import("${standardScriptPath}");
257
+ }
258
+ </script>
259
+ <link rel="stylesheet" crossorigin href="${standardOutput.stylePath}" />
260
+ </head>
261
+ <body>${standardOutput.bodyContent}</body>
262
+ </html>`;
263
+ writeFileSync(standardIndexPath, unifiedHtml);
264
+ // Clean up the mini build's separate files
265
+ if (existsSync(miniIndexPath)) {
266
+ rmSync(miniIndexPath);
267
+ }
268
+ if (existsSync(miniAssetsDir)) {
269
+ rmSync(miniAssetsDir, { recursive: true });
270
+ }
271
+ console.log("utopian-minify: Post-processing complete");
272
+ }
273
+ catch (error) {
274
+ console.error("Error during post-processing:", error);
275
+ throw error;
276
+ }
277
+ }
278
+ //# sourceMappingURL=postprocess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postprocess.js","sourceRoot":"","sources":["../src/postprocess.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "utopian-minify",
3
+ "version": "0.0.5",
4
+ "description": "A post-processing tool that creates dual builds with import maps for cross-origin caching",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git@github.com:Utopian-Contributors/vite-utopian.git"
8
+ },
9
+ "type": "module",
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "bin": {
13
+ "utopian-minify": "./dist/cli.js"
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
+ },
20
+ "./postprocess": {
21
+ "types": "./dist/postprocess.d.ts",
22
+ "import": "./dist/postprocess.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "scripts": {
29
+ "build": "rimraf dist && tsc && chmod +x dist/cli.js",
30
+ "dev": "tsc --watch",
31
+ "clean": "rm -rf dist",
32
+ "test": "vitest run",
33
+ "prepublishOnly": "yarn clean && yarn build"
34
+ },
35
+ "author": "Ludwig Schubert (@UtopianContrib)",
36
+ "license": "MIT",
37
+ "peerDependencies": {
38
+ "vite": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
39
+ },
40
+ "peerDependenciesMeta": {
41
+ "vite": {
42
+ "optional": true
43
+ }
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "^22.10.4",
47
+ "prettier": "^3.6.2",
48
+ "rimraf": "^6.0.1",
49
+ "tsc": "^2.0.4",
50
+ "typescript": "^5.9.3",
51
+ "vite": "^7.1.9"
52
+ },
53
+ "dependencies": {
54
+ "es-module-lexer": "^2.0.0"
55
+ }
56
+ }