cacheableComponents

tcmts.cli.web.cacheableComponents · #asypu5qo · term · runs on the server

uses tcmts.cli.npm.isPureExport, which uses tcmts.cli.npm.npmFacts, which uses node:path

The server components among hashes that render the same tree for the same props, every time, so a tree rendered once can be kept, by its props, for good: their code, through everything it uses, reaches nothing outside the codebase (reaches: not the clock, randomness, the network, files, the environment), uses nothing of #tcm/host (the server library's tables, cookies, sessions, the request), and of npm packages only React and exports their code shows to be pure (isPureExport), and reads no state something else could change (stateless). Worked out from the code, as pure constants are: nothing says so.

import type { CodebaseCore } from "#codebase/tcmts/cli/codebase";
import { reaches } from "#codebase/tcmts/cli/effects";
import { stateless } from "#codebase/tcmts/cli/kept";
import { isPureExport, parseExtRef } from "#codebase/tcmts/cli/npm";
import type { DefSource } from "#codebase/tcmts/loader";

export function cacheableComponents(
  cb: CodebaseCore,
  hashes: Iterable<string>,
  src: DefSource = cb.source(),
): Set<string> {
  const list = [...hashes];
  const outside = reaches(cb, list, src);
  const out = new Set<string>();
  // whether a component's code, or what it uses, imports anything but React and Node (whose effects `reaches` sees)
  const foreign = new Map<string, boolean>();
  const usesForeign = (comp: string): boolean => {
    const known = foreign.get(comp);
    if (known !== undefined) return known;
    foreign.set(comp, false);
    let uses = false;
    for (const m of src.members(comp)) {
      for (const d of m.deps) {
        if (d.pos !== "value") continue;
        if (!d.ref.startsWith("#")) {
          // (an npm package's export whose code is pure, worked out from it, is as good as the codebase's own)
          const e = !/^(npm:react@|node:)/.test(d.ref) ? parseExtRef(d.ref) : undefined;
          uses ||= !!e && !isPureExport(cb.lay.cacheDir, e);
          if (!e && !/^(npm:react@|node:)/.test(d.ref)) uses = true;
        } else {
          const dep = src.get(d.ref.slice(1));
          if (dep && dep.componentHash !== comp) uses ||= usesForeign(dep.componentHash);
        }
        if (uses) break;
      }
      if (uses) break;
    }
    foreign.set(comp, uses);
    return uses;
  };
  for (const h of list) {
    const rec = src.get(h);
    if (
      !rec ||
      outside.get(h)?.length ||
      usesForeign(rec.componentHash) ||
      !stateless(src, h, () => false)
    )
      continue;
    out.add(h);
  }
  return out;
}

uses

used by