@analogjs/vite-plugin-angular 3.0.0-alpha.32 → 3.0.0-alpha.34

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@analogjs/vite-plugin-angular",
3
- "version": "3.0.0-alpha.32",
3
+ "version": "3.0.0-alpha.34",
4
4
  "description": "Vite Plugin for Angular",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@analogjs/angular-compiler": "3.0.0-alpha.32",
39
+ "@analogjs/angular-compiler": "3.0.0-alpha.34",
40
40
  "es-toolkit": "^1.45.1",
41
41
  "obug": "^2.1.1",
42
42
  "oxc-parser": "^0.124.0",
@@ -1,4 +1,5 @@
1
1
  import { debugStyles } from "./utils/debug.js";
2
+ import { isTailwindReferenceError } from "./utils/tailwind-reference.js";
2
3
  import { createHash } from "node:crypto";
3
4
  import { preprocessCSS } from "vite";
4
5
  //#region packages/vite-plugin-angular/src/lib/angular-jit-plugin.ts
@@ -21,6 +22,7 @@ function jitPlugin({ inlineStylesExtension }) {
21
22
  try {
22
23
  styles = (await preprocessCSS(decodedStyles, `${styleIdHash}.${inlineStylesExtension}?direct`, config))?.code;
23
24
  } catch (e) {
25
+ if (isTailwindReferenceError(e)) throw e;
24
26
  const errorMessage = e instanceof Error ? e.message : String(e);
25
27
  debugStyles("jit css compilation error", {
26
28
  styleIdHash,
@@ -1 +1 @@
1
- {"version":3,"file":"angular-jit-plugin.js","names":[],"sources":["../../../src/lib/angular-jit-plugin.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { Plugin, ResolvedConfig, preprocessCSS } from 'vite';\nimport { debugStyles } from './utils/debug.js';\n\nexport function jitPlugin({\n inlineStylesExtension,\n}: {\n inlineStylesExtension: string;\n}): Plugin {\n let config: ResolvedConfig;\n\n return {\n name: '@analogjs/vite-plugin-angular-jit',\n configResolved(_config) {\n config = _config;\n },\n resolveId(id: string) {\n if (id.startsWith('virtual:angular')) {\n return `\\0${id}`;\n }\n\n return;\n },\n async load(id: string) {\n if (id.includes('virtual:angular:jit:style:inline;')) {\n const styleId = id.split('style:inline;')[1];\n // styleId may exceed 255 bytes of base64-encoded content, limit to 16\n const styleIdHash = createHash('sha256')\n .update(styleId)\n .digest('hex')\n .slice(0, 16);\n\n const decodedStyles = Buffer.from(\n decodeURIComponent(styleId),\n 'base64',\n ).toString();\n\n let styles: string | undefined = '';\n\n try {\n const compiled = await preprocessCSS(\n decodedStyles,\n `${styleIdHash}.${inlineStylesExtension}?direct`,\n config,\n );\n styles = compiled?.code;\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : String(e);\n debugStyles('jit css compilation error', {\n styleIdHash,\n error: errorMessage,\n });\n console.warn(\n '[@analogjs/vite-plugin-angular]: Failed to preprocess inline JIT stylesheet %s. Returning an empty stylesheet instead. %s',\n styleIdHash,\n errorMessage,\n );\n }\n\n return `export default \\`${styles}\\``;\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;AAIA,SAAgB,UAAU,EACxB,yBAGS;CACT,IAAI;AAEJ,QAAO;EACL,MAAM;EACN,eAAe,SAAS;AACtB,YAAS;;EAEX,UAAU,IAAY;AACpB,OAAI,GAAG,WAAW,kBAAkB,CAClC,QAAO,KAAK;;EAKhB,MAAM,KAAK,IAAY;AACrB,OAAI,GAAG,SAAS,oCAAoC,EAAE;IACpD,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC;IAE1C,MAAM,cAAc,WAAW,SAAS,CACrC,OAAO,QAAQ,CACf,OAAO,MAAM,CACb,MAAM,GAAG,GAAG;IAEf,MAAM,gBAAgB,OAAO,KAC3B,mBAAmB,QAAQ,EAC3B,SACD,CAAC,UAAU;IAEZ,IAAI,SAA6B;AAEjC,QAAI;AAMF,eALiB,MAAM,cACrB,eACA,GAAG,YAAY,GAAG,sBAAsB,UACxC,OACD,GACkB;aACZ,GAAG;KACV,MAAM,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AAC/D,iBAAY,6BAA6B;MACvC;MACA,OAAO;MACR,CAAC;AACF,aAAQ,KACN,6HACA,aACA,aACD;;AAGH,WAAO,oBAAoB,OAAO;;;EAKvC"}
1
+ {"version":3,"file":"angular-jit-plugin.js","names":[],"sources":["../../../src/lib/angular-jit-plugin.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport { Plugin, ResolvedConfig, preprocessCSS } from 'vite';\nimport { debugStyles } from './utils/debug.js';\nimport { isTailwindReferenceError } from './utils/tailwind-reference.js';\n\nexport function jitPlugin({\n inlineStylesExtension,\n}: {\n inlineStylesExtension: string;\n}): Plugin {\n let config: ResolvedConfig;\n\n return {\n name: '@analogjs/vite-plugin-angular-jit',\n configResolved(_config) {\n config = _config;\n },\n resolveId(id: string) {\n if (id.startsWith('virtual:angular')) {\n return `\\0${id}`;\n }\n\n return;\n },\n async load(id: string) {\n if (id.includes('virtual:angular:jit:style:inline;')) {\n const styleId = id.split('style:inline;')[1];\n // styleId may exceed 255 bytes of base64-encoded content, limit to 16\n const styleIdHash = createHash('sha256')\n .update(styleId)\n .digest('hex')\n .slice(0, 16);\n\n const decodedStyles = Buffer.from(\n decodeURIComponent(styleId),\n 'base64',\n ).toString();\n\n let styles: string | undefined = '';\n\n try {\n const compiled = await preprocessCSS(\n decodedStyles,\n `${styleIdHash}.${inlineStylesExtension}?direct`,\n config,\n );\n styles = compiled?.code;\n } catch (e) {\n if (isTailwindReferenceError(e)) {\n throw e;\n }\n const errorMessage = e instanceof Error ? e.message : String(e);\n debugStyles('jit css compilation error', {\n styleIdHash,\n error: errorMessage,\n });\n console.warn(\n '[@analogjs/vite-plugin-angular]: Failed to preprocess inline JIT stylesheet %s. Returning an empty stylesheet instead. %s',\n styleIdHash,\n errorMessage,\n );\n }\n\n return `export default \\`${styles}\\``;\n }\n\n return;\n },\n };\n}\n"],"mappings":";;;;;AAKA,SAAgB,UAAU,EACxB,yBAGS;CACT,IAAI;AAEJ,QAAO;EACL,MAAM;EACN,eAAe,SAAS;AACtB,YAAS;;EAEX,UAAU,IAAY;AACpB,OAAI,GAAG,WAAW,kBAAkB,CAClC,QAAO,KAAK;;EAKhB,MAAM,KAAK,IAAY;AACrB,OAAI,GAAG,SAAS,oCAAoC,EAAE;IACpD,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC;IAE1C,MAAM,cAAc,WAAW,SAAS,CACrC,OAAO,QAAQ,CACf,OAAO,MAAM,CACb,MAAM,GAAG,GAAG;IAEf,MAAM,gBAAgB,OAAO,KAC3B,mBAAmB,QAAQ,EAC3B,SACD,CAAC,UAAU;IAEZ,IAAI,SAA6B;AAEjC,QAAI;AAMF,eALiB,MAAM,cACrB,eACA,GAAG,YAAY,GAAG,sBAAsB,UACxC,OACD,GACkB;aACZ,GAAG;AACV,SAAI,yBAAyB,EAAE,CAC7B,OAAM;KAER,MAAM,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;AAC/D,iBAAY,6BAA6B;MACvC;MACA,OAAO;MACR,CAAC;AACF,aAAQ,KACN,6HACA,aACA,aACD;;AAGH,WAAO,oBAAoB,OAAO;;;EAKvC"}
@@ -160,6 +160,20 @@ export declare function evictDeletedFileMetadata(file: string, { removeActiveGra
160
160
  }): void;
161
161
  export declare function injectViteIgnoreForHmrMetadata(code: string): string;
162
162
  export declare function isIgnoredHmrFile(file: string): boolean;
163
+ /**
164
+ * Builds a resolved stylePreprocessor function from plugin options.
165
+ *
166
+ * When `tailwindCss` is configured, creates an injector that prepends
167
+ * `@reference "<rootStylesheet>"` into component CSS that uses Tailwind
168
+ * utilities. Uses absolute paths because Angular's externalRuntimeStyles
169
+ * serves component CSS as virtual modules (hash-based IDs) with no
170
+ * meaningful directory — relative paths can't resolve from a hash.
171
+ *
172
+ * If both `tailwindCss` and `stylePreprocessor` are provided, they are
173
+ * chained: Tailwind reference injection runs first, then the user's
174
+ * custom preprocessor.
175
+ */
176
+ export declare function buildStylePreprocessor(options?: PluginOptions): StylePreprocessor | undefined;
163
177
  export declare function angular(options?: PluginOptions): Plugin[];
164
178
  export declare function createFsWatcherCacheInvalidator(invalidateFsCaches: () => void, invalidateTsconfigCaches: () => void, performCompilation: () => Promise<void>): () => Promise<void>;
165
179
  /**
@@ -2,6 +2,7 @@ import { angularFullVersion, cjt, createAngularCompilation, sourceFileCache } fr
2
2
  import { getJsTransformConfigKey, isRolldown } from "./utils/rolldown.js";
3
3
  import { buildOptimizerPlugin } from "./angular-build-optimizer-plugin.js";
4
4
  import { activateDeferredDebug, applyDebugOption, debugCompilationApi, debugCompiler, debugCompilerV, debugHmr, debugHmrV, debugStyles, debugStylesV, debugTailwind, debugTailwindV } from "./utils/debug.js";
5
+ import { inspectCssTailwindDirectives, isTailwindReferenceError, throwTailwindReferenceTextError } from "./utils/tailwind-reference.js";
5
6
  import { jitPlugin } from "./angular-jit-plugin.js";
6
7
  import { createCompilerPlugin, createRolldownCompilerPlugin } from "./compiler-plugin.js";
7
8
  import { StyleUrlsResolver, TemplateUrlsResolver, getAngularComponentMetadata } from "./component-resolvers.js";
@@ -89,14 +90,16 @@ function buildStylePreprocessor(options) {
89
90
  });
90
91
  if (!existsSync(rootStylesheet)) console.warn(`[@analogjs/vite-plugin-angular] tailwindCss.rootStylesheet not found at "${rootStylesheet}". @reference directives will point to a non-existent file, which will cause Tailwind CSS errors. Ensure the path is absolute and the file exists.`);
91
92
  tailwindPreprocessor = (code, filename) => {
92
- if (code.includes("@reference") || code.includes("@import \"tailwindcss\"") || code.includes("@import 'tailwindcss'")) {
93
+ const directiveState = inspectCssTailwindDirectives(code);
94
+ if (directiveState.hasReferenceDirective || directiveState.hasTailwindImportDirective) {
93
95
  debugTailwindV("skip (already has @reference or is root)", { filename });
94
96
  return code;
95
97
  }
96
- if (!(prefixes ? prefixes.some((prefix) => code.includes(prefix)) : code.includes("@apply"))) {
98
+ if (!(prefixes ? prefixes.some((prefix) => directiveState.commentlessCode.includes(prefix)) : directiveState.commentlessCode.includes("@apply"))) {
97
99
  debugTailwindV("skip (no Tailwind usage detected)", { filename });
98
100
  return code;
99
101
  }
102
+ if (directiveState.hasReferenceText) throwTailwindReferenceTextError(filename, rootStylesheet);
100
103
  debugTailwind("injected @reference via preprocessor", { filename });
101
104
  return `@reference "${rootStylesheet}";\n${code}`;
102
105
  };
@@ -203,8 +206,33 @@ function angular(options) {
203
206
  }
204
207
  }
205
208
  if (tw.prefixes !== void 0 && tw.prefixes.length === 0) console.warn(`${PREFIX} tailwindCss.prefixes is an empty array. No component stylesheets will receive @reference injection. Either remove the prefixes option (to use @apply detection) or specify your prefixes: ['tw:']\n`);
209
+ /**
210
+ * Duplicate analog() registrations are a real bug for the non-SSR/client
211
+ * build because each plugin instance creates its own component-style state.
212
+ *
213
+ * That state includes the style maps/registries used to:
214
+ * - track transformed component styles
215
+ * - map owner components back to stylesheet requests
216
+ * - coordinate Tailwind/@reference processing and style reload behavior
217
+ *
218
+ * If two plugin instances are active for the same client build, one
219
+ * instance can record stylesheet metadata while the other services the
220
+ * request. The result is "missing" component CSS even though compilation
221
+ * appeared to succeed.
222
+ *
223
+ * SSR is different. Analog's Nitro/SSR build path reuses the already
224
+ * resolved plugin graph and then runs an additional `build.ssr === true`
225
+ * pass for the server bundle. In that flow Vite can expose multiple
226
+ * `@analogjs/vite-plugin-angular` entries in `config.plugins`, but that is
227
+ * not the same failure mode as a duplicated client build. The server build
228
+ * does not rely on the client-side style maps that this guard is protecting.
229
+ *
230
+ * Because of that, we only throw for duplicate registrations on non-SSR
231
+ * builds. Throwing during SSR would be a false positive that breaks valid
232
+ * Analog SSR/Nitro builds.
233
+ */
206
234
  const analogInstances = resolvedPlugins.filter((p) => p.name === "@analogjs/vite-plugin-angular");
207
- if (analogInstances.length > 1) throw new Error(`${PREFIX} analog() is registered ${analogInstances.length} times. Each instance creates separate style maps, causing component styles to be lost. Remove duplicate registrations.`);
235
+ if (analogInstances.length > 1 && !config.build?.ssr) throw new Error(`${PREFIX} analog() is registered ${analogInstances.length} times. Each instance creates separate style maps, causing component styles to be lost. Remove duplicate registrations.`);
208
236
  if (existsSync(tw.rootStylesheet)) try {
209
237
  const rootContent = readFileSync(tw.rootStylesheet, "utf-8");
210
238
  if (!rootContent.includes("@import \"tailwindcss\"") && !rootContent.includes("@import 'tailwindcss'")) console.warn(`${PREFIX} tailwindCss.rootStylesheet does not contain @import "tailwindcss". The @reference directive will point to a file without Tailwind configuration.\n\n File: ${tw.rootStylesheet}\n`);
@@ -857,6 +885,7 @@ function angular(options) {
857
885
  }
858
886
  const typescriptResult = fileEmitter(id);
859
887
  if (!typescriptResult) {
888
+ debugCompilerV("transform skip (file not emitted by Angular)", { id });
860
889
  if (!id.includes("@ng/component") && /(Component|Directive|Pipe|Injectable|NgModule)\(/.test(code)) this.warn(`[@analogjs/vite-plugin-angular]: "${id}" contains Angular decorators but is not in the TypeScript program. Ensure it is included in your tsconfig.`);
861
890
  return;
862
891
  }
@@ -1002,11 +1031,14 @@ function angular(options) {
1002
1031
  const tw = pluginOptions.tailwindCss;
1003
1032
  if (!tw || !id.includes(".css")) return;
1004
1033
  if (id.split("?")[0] === tw.rootStylesheet) return;
1005
- if (code.includes("@reference") || code.includes("@import \"tailwindcss\"") || code.includes("@import 'tailwindcss'")) return;
1034
+ const directiveState = inspectCssTailwindDirectives(code);
1035
+ if (directiveState.hasReferenceDirective || directiveState.hasTailwindImportDirective) return;
1006
1036
  const rootBasename = basename(tw.rootStylesheet);
1007
- if (code.includes(rootBasename)) return;
1037
+ if (directiveState.commentlessCode.includes(rootBasename)) return;
1008
1038
  const prefixes = tw.prefixes;
1009
- if (prefixes ? prefixes.some((p) => code.includes(p)) : code.includes("@apply")) {
1039
+ const needsRef = prefixes ? prefixes.some((p) => directiveState.commentlessCode.includes(p)) : directiveState.commentlessCode.includes("@apply");
1040
+ if (needsRef && directiveState.hasReferenceText) throwTailwindReferenceTextError(id, tw.rootStylesheet);
1041
+ if (needsRef) {
1010
1042
  debugTailwind("injected @reference via pre-transform", { id: id.split("/").slice(-2).join("/") });
1011
1043
  return `@reference "${tw.rootStylesheet}";\n${code}`;
1012
1044
  }
@@ -1033,6 +1065,74 @@ function angular(options) {
1033
1065
  absolute: true
1034
1066
  });
1035
1067
  }
1068
+ function ensureIncludeCache() {
1069
+ if (pluginOptions.include.length > 0 && includeCache.length === 0) includeCache = findIncludes();
1070
+ return includeCache;
1071
+ }
1072
+ function getTsconfigCacheKey(resolvedTsConfigPath, config) {
1073
+ return [
1074
+ resolvedTsConfigPath,
1075
+ config.mode === "production" ? "prod" : "dev",
1076
+ isTest ? "test" : "app",
1077
+ config.build?.lib ? "lib" : "nolib",
1078
+ pluginOptions.hmr ? "hmr" : "nohmr",
1079
+ pluginOptions.hasTailwindCss ? "tw" : "notw"
1080
+ ].join("|");
1081
+ }
1082
+ function getCachedTsconfigOptions(resolvedTsConfigPath, config) {
1083
+ const isProd = config.mode === "production";
1084
+ const tsconfigKey = getTsconfigCacheKey(resolvedTsConfigPath, config);
1085
+ let cached = tsconfigOptionsCache.get(tsconfigKey);
1086
+ if (!cached) {
1087
+ const read = compilerCli.readConfiguration(resolvedTsConfigPath, {
1088
+ suppressOutputPathCheck: true,
1089
+ outDir: void 0,
1090
+ sourceMap: false,
1091
+ inlineSourceMap: !isProd,
1092
+ inlineSources: !isProd,
1093
+ declaration: false,
1094
+ declarationMap: false,
1095
+ allowEmptyCodegenFiles: false,
1096
+ annotationsAs: "decorators",
1097
+ enableResourceInlining: false,
1098
+ noEmitOnError: false,
1099
+ mapRoot: void 0,
1100
+ sourceRoot: void 0,
1101
+ supportTestBed: false,
1102
+ supportJitMode: false
1103
+ });
1104
+ cached = {
1105
+ options: read.options,
1106
+ rootNames: read.rootNames
1107
+ };
1108
+ tsconfigOptionsCache.set(tsconfigKey, cached);
1109
+ }
1110
+ return cached;
1111
+ }
1112
+ function resolveCompilationApiTsConfigPath(resolvedTsConfigPath, config) {
1113
+ const includedFiles = ensureIncludeCache();
1114
+ if (includedFiles.length === 0) return resolvedTsConfigPath;
1115
+ const cached = getCachedTsconfigOptions(resolvedTsConfigPath, config);
1116
+ const mergedRootNames = union(cached.rootNames, includedFiles).map((file) => normalizePath(file));
1117
+ if (mergedRootNames.length === cached.rootNames.length) return resolvedTsConfigPath;
1118
+ const wrapperDir = join(isAbsolute(config.cacheDir) ? config.cacheDir : resolve(config.root, config.cacheDir), "analog-angular", "compilation-api");
1119
+ const rawTsconfig = ts.readConfigFile(resolvedTsConfigPath, ts.sys.readFile).config ?? {};
1120
+ const wrapperPayload = {
1121
+ extends: normalizePath(resolvedTsConfigPath),
1122
+ files: [...mergedRootNames].sort(),
1123
+ ...rawTsconfig.references ? { references: rawTsconfig.references } : {}
1124
+ };
1125
+ const wrapperPath = join(wrapperDir, `tsconfig.includes.${createHash("sha1").update(JSON.stringify(wrapperPayload)).digest("hex").slice(0, 12)}.json`);
1126
+ mkdirSync(wrapperDir, { recursive: true });
1127
+ if (!existsSync(wrapperPath)) writeFileSync(wrapperPath, `${JSON.stringify(wrapperPayload, null, 2)}\n`, "utf-8");
1128
+ debugCompilationApi("generated include wrapper tsconfig", {
1129
+ originalTsconfig: resolvedTsConfigPath,
1130
+ wrapperTsconfig: wrapperPath,
1131
+ includeCount: includedFiles.length,
1132
+ rootNameCount: mergedRootNames.length
1133
+ });
1134
+ return wrapperPath;
1135
+ }
1036
1136
  function resolveTsConfigPath() {
1037
1137
  const tsconfigValue = pluginOptions.tsconfigGetter();
1038
1138
  return getTsConfigPath(tsConfigResolutionContext.root, tsconfigValue, tsConfigResolutionContext.isProd, isTest, tsConfigResolutionContext.isLib);
@@ -1060,8 +1160,8 @@ function angular(options) {
1060
1160
  debugCompilationApi("incremental update", { files: [...modifiedFiles] });
1061
1161
  await angularCompilation.update(modifiedFiles);
1062
1162
  }
1063
- const resolvedTsConfigPath = resolveTsConfigPath();
1064
- const compilationResult = await angularCompilation.initialize(resolvedTsConfigPath, {
1163
+ const compilationApiTsConfigPath = resolveCompilationApiTsConfigPath(resolveTsConfigPath(), config);
1164
+ const compilationResult = await angularCompilation.initialize(compilationApiTsConfigPath, {
1065
1165
  fileReplacements: toAngularCompilationFileReplacements(pluginOptions.fileReplacements, pluginOptions.workspaceRoot),
1066
1166
  modifiedFiles,
1067
1167
  async transformStylesheet(data, containingFile, resourceFile, order, className) {
@@ -1111,6 +1211,7 @@ function angular(options) {
1111
1211
  try {
1112
1212
  stylesheetResult = await preprocessCSS(preprocessed.code, `${filename}?direct`, resolvedConfig);
1113
1213
  } catch (e) {
1214
+ if (isTailwindReferenceError(e)) throw e;
1114
1215
  debugStyles("preprocessCSS error", {
1115
1216
  filename,
1116
1217
  resourceFile: resourceFile ?? "(inline)",
@@ -1281,41 +1382,7 @@ function angular(options) {
1281
1382
  const modifiedFiles = new Set(ids ?? []);
1282
1383
  sourceFileCache$1.invalidate(modifiedFiles);
1283
1384
  if (ids?.length) for (const id of ids || []) fileTransformMap.delete(id);
1284
- if (pluginOptions.include.length > 0 && includeCache.length === 0) includeCache = findIncludes();
1285
- const resolvedTsConfigPath = resolveTsConfigPath();
1286
- const tsconfigKey = [
1287
- resolvedTsConfigPath,
1288
- isProd ? "prod" : "dev",
1289
- isTest ? "test" : "app",
1290
- config.build?.lib ? "lib" : "nolib",
1291
- pluginOptions.hmr ? "hmr" : "nohmr",
1292
- pluginOptions.hasTailwindCss ? "tw" : "notw"
1293
- ].join("|");
1294
- let cached = tsconfigOptionsCache.get(tsconfigKey);
1295
- if (!cached) {
1296
- const read = compilerCli.readConfiguration(resolvedTsConfigPath, {
1297
- suppressOutputPathCheck: true,
1298
- outDir: void 0,
1299
- sourceMap: false,
1300
- inlineSourceMap: !isProd,
1301
- inlineSources: !isProd,
1302
- declaration: false,
1303
- declarationMap: false,
1304
- allowEmptyCodegenFiles: false,
1305
- annotationsAs: "decorators",
1306
- enableResourceInlining: false,
1307
- noEmitOnError: false,
1308
- mapRoot: void 0,
1309
- sourceRoot: void 0,
1310
- supportTestBed: false,
1311
- supportJitMode: false
1312
- });
1313
- cached = {
1314
- options: read.options,
1315
- rootNames: read.rootNames
1316
- };
1317
- tsconfigOptionsCache.set(tsconfigKey, cached);
1318
- }
1385
+ const cached = getCachedTsconfigOptions(resolveTsConfigPath(), config);
1319
1386
  const tsCompilerOptions = { ...cached.options };
1320
1387
  let rootNames = [...cached.rootNames];
1321
1388
  if (shouldExternalizeStyles()) tsCompilerOptions["externalRuntimeStyles"] = true;
@@ -1341,7 +1408,7 @@ function angular(options) {
1341
1408
  }
1342
1409
  if (isTest) tsCompilerOptions["supportTestBed"] = true;
1343
1410
  const replacements = pluginOptions.fileReplacements.map((rp) => join(pluginOptions.workspaceRoot, rp.ssr || rp.with));
1344
- rootNames = union(rootNames, includeCache, replacements);
1411
+ rootNames = union(rootNames, ensureIncludeCache(), replacements);
1345
1412
  const hostKey = JSON.stringify(tsCompilerOptions);
1346
1413
  let host;
1347
1414
  if (cachedHost && cachedHostKey === hostKey) host = cachedHost;