|
8 | 8 |
|
9 | 9 | import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
10 | 10 | import { runWebpack } from '@angular-devkit/build-webpack';
|
11 |
| -import * as path from 'path'; |
| 11 | +import { readFile } from 'node:fs/promises'; |
| 12 | +import * as path from 'node:path'; |
12 | 13 | import { Observable, concatMap, from } from 'rxjs';
|
13 | 14 | import webpack, { Configuration } from 'webpack';
|
14 | 15 | import { ExecutionTransformer } from '../../transforms';
|
@@ -191,6 +192,8 @@ async function initialize(
|
191 | 192 | // Purge old build disk cache.
|
192 | 193 | await purgeStaleBuildCache(context);
|
193 | 194 |
|
| 195 | + await checkTsConfigForPreserveWhitespacesSetting(context, options.tsConfig); |
| 196 | + |
194 | 197 | const browserslist = (await import('browserslist')).default;
|
195 | 198 | const originalOutputPath = options.outputPath;
|
196 | 199 | // Assets are processed directly by the builder except when watching
|
@@ -223,6 +226,32 @@ async function initialize(
|
223 | 226 | return { config: transformedConfig, i18n, projectRoot, projectSourceRoot };
|
224 | 227 | }
|
225 | 228 |
|
| 229 | +async function checkTsConfigForPreserveWhitespacesSetting( |
| 230 | + context: BuilderContext, |
| 231 | + tsConfigPath: string, |
| 232 | +): Promise<void> { |
| 233 | + // We don't use the `readTsConfig` method on purpose here. |
| 234 | + // To only catch cases were `preserveWhitespaces` is set directly in the `tsconfig.server.json`, |
| 235 | + // which in the majority of cases will cause a mistmatch between client and server builds. |
| 236 | + // Technically we should check if `tsconfig.server.json` and `tsconfig.app.json` values match. |
| 237 | + |
| 238 | + // But: |
| 239 | + // 1. It is not guaranteed that `tsconfig.app.json` is used to build the client side of this app. |
| 240 | + // 2. There is no easy way to access the build build config from the server builder. |
| 241 | + // 4. This will no longer be an issue with a single compilation model were the same tsconfig is used for both browser and server builds. |
| 242 | + const content = await readFile(path.join(context.workspaceRoot, tsConfigPath), 'utf-8'); |
| 243 | + const { parse } = await import('jsonc-parser'); |
| 244 | + const tsConfig = parse(content, [], { allowTrailingComma: true }); |
| 245 | + if (tsConfig.angularCompilerOptions?.preserveWhitespaces !== undefined) { |
| 246 | + context.logger.warn( |
| 247 | + `"preserveWhitespaces" was set in "${tsConfigPath}". ` + |
| 248 | + 'Make sure that this setting is set consistently in both "tsconfig.server.json" for your server side ' + |
| 249 | + 'and "tsconfig.app.json" for your client side. A mismatched value will cause hydration to break.\n' + |
| 250 | + 'For more information see: https://angular.io/guide/hydration#preserve-whitespaces', |
| 251 | + ); |
| 252 | + } |
| 253 | +} |
| 254 | + |
226 | 255 | /**
|
227 | 256 | * Add `@angular/platform-server` exports.
|
228 | 257 | * This is needed so that DI tokens can be referenced and set at runtime outside of the bundle.
|
|
0 commit comments