sliftutils 1.7.7 → 1.7.9

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.
@@ -12,15 +12,26 @@ async function main() {
12
12
  if (!outputFolder) {
13
13
  throw new Error("No output folder provided. Please use the --outputFolder option.");
14
14
  }
15
- // We prefer production, as this is what the bundler uses internally. This ensures that in the build and when run, we will have the same environment, which will result in the same requires being called.
15
+ // We prefer production, as this is what the bundler uses internally. This ensures that in the build and when run, we will have the same environment, which will result in the same requires being called.
16
16
  process.env.NODE_ENV = process.env.NODE_ENV || "production";
17
17
  require(entryPoint);
18
18
 
19
+ // Warm pass: this process only exists to compile the entry's whole graph
20
+ // (and this bundler's own modules, compiled at our startup) into typenode's
21
+ // on-disk cache, then exit. The caller runs a SECOND, fresh process for the
22
+ // real bundle — that process reads everything from the warm cache and so
23
+ // never has typenode lazy-load the TypeScript compiler. Without this, a
24
+ // cold-cache build (e.g. a fresh CI/server checkout, or an entry whose files
25
+ // no other entry imports) leaves `typescript` in require.cache and the
26
+ // bundler serializes the entire 9 MB+ compiler into the output bundle.
27
+ if (process.argv[4] === "--warm") {
28
+ return;
29
+ }
30
+
19
31
  let name = path.basename(entryPoint);
20
32
  if (name.endsWith(".ts") || name.endsWith(".tsx")) {
21
33
  name = name.split(".").slice(0, -1).join(".");
22
34
  }
23
- name += ".js";
24
35
 
25
36
  let modules = Object.values(require.cache).filter(x => x?.id !== module.id);
26
37
 
@@ -30,16 +41,21 @@ async function main() {
30
41
  entryPoints: [entryPoint],
31
42
  });
32
43
 
33
- let finalPath = `${outputFolder}/${name}`;
34
- let tempPath = `${finalPath}.tmp`;
35
-
36
- try {
37
- await fs.promises.writeFile(tempPath, bundled.bundle);
38
- await fs.promises.rename(tempPath, finalPath);
39
- } finally {
44
+ // Two artifacts: `name.js` without the sourcemap (the sourcemap is usually bigger than the code
45
+ // itself, so this is what production serves) and `name.debug.js` with the inline sourcemap
46
+ // appended (serve it behind something like a ?debug query param).
47
+ async function write(finalPath: string, contents: string) {
48
+ let tempPath = `${finalPath}.tmp`;
40
49
  try {
41
- await fs.promises.unlink(tempPath);
42
- } catch { }
50
+ await fs.promises.writeFile(tempPath, contents);
51
+ await fs.promises.rename(tempPath, finalPath);
52
+ } finally {
53
+ try {
54
+ await fs.promises.unlink(tempPath);
55
+ } catch { }
56
+ }
43
57
  }
58
+ await write(`${outputFolder}/${name}.js`, bundled.bundle);
59
+ await write(`${outputFolder}/${name}.debug.js`, bundled.bundle + "\n" + bundled.sourceMapComment);
44
60
  }
45
61
  main().catch(err => { console.error(err); process.exitCode = 1; }).finally(() => process.exit());
@@ -10,5 +10,13 @@ export async function bundleEntryCaller(config: {
10
10
  entryPoint = path.resolve(entryPoint).replace(/\\/g, "/");
11
11
  outputFolder = path.resolve(outputFolder).replace(/\\/g, "/");
12
12
  let bundleEntryPath = path.resolve(__dirname, "bundleEntry.ts").replace(/\\/g, "/");
13
- await runPromise(`node -r ./node_modules/typenode/index.js ${JSON.stringify(bundleEntryPath)} ${JSON.stringify(entryPoint)} ${JSON.stringify(outputFolder)}`);
13
+ let base = `node -r ./node_modules/typenode/index.js ${JSON.stringify(bundleEntryPath)} ${JSON.stringify(entryPoint)} ${JSON.stringify(outputFolder)}`;
14
+ // Run twice in SEPARATE processes. The first ("--warm") only imports the
15
+ // entry, which compiles its whole graph into typenode's on-disk cache. The
16
+ // second is a fresh process that imports from that warm cache — so typenode
17
+ // never has to compile anything and never lazy-loads the TypeScript compiler,
18
+ // which would otherwise be captured in require.cache and serialized (9 MB+)
19
+ // into the output bundle. See bundleEntry.ts.
20
+ await runPromise(`${base} --warm`);
21
+ await runPromise(base);
14
22
  }
@@ -9,7 +9,12 @@ export async function bundle(config: {
9
9
  rootPath: string;
10
10
  entryPoints: string[];
11
11
  }): Promise<{
12
+ // The runnable bundle, WITHOUT the sourcemap comment (the sourcemap is usually bigger than the
13
+ // code itself, so the default artifact ships without it).
12
14
  bundle: string;
15
+ // The trailing inline-sourcemap line comment. Append to `bundle` (with a newline) for the debug
16
+ // variant of the bundle.
17
+ sourceMapComment: string;
13
18
  }> {
14
19
  const { modules, rootPath, entryPoints } = config;
15
20
 
@@ -55,9 +60,9 @@ export async function bundle(config: {
55
60
  code += `\n;globalThis.require(${JSON.stringify(entryPoint)});`;
56
61
  }
57
62
  code += "\n;});";
58
- code += "\n" + encodeSourceMapLineComment(finalizeInProgressSourceMap(inProgressSourceMap));
59
63
  return {
60
64
  bundle: code,
65
+ sourceMapComment: encodeSourceMapLineComment(finalizeInProgressSourceMap(inProgressSourceMap)),
61
66
  };
62
67
  }
63
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.7.7",
3
+ "version": "1.7.9",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [