@angular-devkit/build-angular 17.1.0-next.0 → 17.1.0-next.2
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 +22 -19
- package/src/builders/application/build-action.d.ts +1 -0
- package/src/builders/application/build-action.js +20 -12
- package/src/builders/application/execute-post-bundle.js +8 -4
- package/src/builders/application/index.js +9 -1
- package/src/builders/application/options.js +1 -1
- package/src/builders/browser-esbuild/builder-status-warnings.js +1 -3
- package/src/builders/dev-server/builder.js +5 -0
- package/src/builders/dev-server/vite-server.js +12 -5
- package/src/builders/karma/index.js +4 -1
- package/src/builders/karma/schema.d.ts +6 -2
- package/src/builders/karma/schema.json +12 -2
- package/src/builders/ssr-dev-server/index.js +27 -18
- package/src/tools/esbuild/angular/angular-host.js +6 -0
- package/src/tools/esbuild/angular/compiler-plugin.js +1 -1
- package/src/tools/esbuild/angular/component-stylesheets.js +1 -1
- package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +2 -1
- package/src/tools/esbuild/angular/jit-plugin-callbacks.js +15 -15
- package/src/tools/esbuild/angular/source-file-cache.js +0 -1
- package/src/tools/esbuild/compiler-plugin-options.js +4 -2
- package/src/tools/esbuild/global-styles.js +4 -2
- package/src/tools/esbuild/i18n-locale-plugin.d.ts +4 -0
- package/src/tools/esbuild/i18n-locale-plugin.js +48 -18
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +3 -0
- package/src/tools/esbuild/stylesheets/bundle-options.js +11 -6
- package/src/tools/esbuild/stylesheets/css-inline-fonts-plugin.d.ts +25 -0
- package/src/tools/esbuild/stylesheets/css-inline-fonts-plugin.js +57 -0
- package/src/tools/esbuild/watcher.d.ts +1 -0
- package/src/tools/esbuild/watcher.js +56 -106
- package/src/tools/sass/rebasing-importer.js +29 -4
- package/src/utils/check-port.js +15 -29
- package/src/utils/delete-output-dir.d.ts +1 -1
- package/src/utils/delete-output-dir.js +11 -2
- package/src/utils/index-file/inline-fonts.d.ts +6 -1
- package/src/utils/index-file/inline-fonts.js +30 -14
- package/src/utils/server-rendering/esm-in-memory-loader/node-18-utils.js +6 -5
- package/src/utils/server-rendering/esm-in-memory-loader/register-hooks.js +1 -3
- package/src/utils/spinner.js +1 -1
package/package.json
CHANGED
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "17.1.0-next.
|
|
3
|
+
"version": "17.1.0-next.2",
|
|
4
4
|
"description": "Angular Webpack Build Facade",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
7
7
|
"builders": "builders.json",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@ampproject/remapping": "2.2.1",
|
|
10
|
-
"@angular-devkit/architect": "0.1701.0-next.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1701.0-next.
|
|
12
|
-
"@angular-devkit/core": "17.1.0-next.
|
|
13
|
-
"@babel/core": "7.23.
|
|
14
|
-
"@babel/generator": "7.23.
|
|
10
|
+
"@angular-devkit/architect": "0.1701.0-next.2",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1701.0-next.2",
|
|
12
|
+
"@angular-devkit/core": "17.1.0-next.2",
|
|
13
|
+
"@babel/core": "7.23.6",
|
|
14
|
+
"@babel/generator": "7.23.6",
|
|
15
15
|
"@babel/helper-annotate-as-pure": "7.22.5",
|
|
16
16
|
"@babel/helper-split-export-declaration": "7.22.6",
|
|
17
17
|
"@babel/plugin-transform-async-generator-functions": "7.23.4",
|
|
18
18
|
"@babel/plugin-transform-async-to-generator": "7.23.3",
|
|
19
|
-
"@babel/plugin-transform-runtime": "7.23.
|
|
20
|
-
"@babel/preset-env": "7.23.
|
|
21
|
-
"@babel/runtime": "7.23.
|
|
19
|
+
"@babel/plugin-transform-runtime": "7.23.6",
|
|
20
|
+
"@babel/preset-env": "7.23.6",
|
|
21
|
+
"@babel/runtime": "7.23.6",
|
|
22
22
|
"@discoveryjs/json-ext": "0.5.7",
|
|
23
|
-
"@ngtools/webpack": "17.1.0-next.
|
|
23
|
+
"@ngtools/webpack": "17.1.0-next.2",
|
|
24
24
|
"@vitejs/plugin-basic-ssl": "1.0.2",
|
|
25
25
|
"ansi-colors": "4.1.3",
|
|
26
26
|
"autoprefixer": "10.4.16",
|
|
27
27
|
"babel-loader": "9.1.3",
|
|
28
28
|
"babel-plugin-istanbul": "6.1.1",
|
|
29
29
|
"browserslist": "^4.21.5",
|
|
30
|
-
"browser-sync": "2.29.3",
|
|
31
|
-
"chokidar": "3.5.3",
|
|
32
30
|
"copy-webpack-plugin": "11.0.0",
|
|
33
31
|
"critters": "0.0.20",
|
|
34
32
|
"css-loader": "6.8.1",
|
|
35
|
-
"esbuild-wasm": "0.19.
|
|
33
|
+
"esbuild-wasm": "0.19.9",
|
|
36
34
|
"fast-glob": "3.3.2",
|
|
37
35
|
"https-proxy-agent": "7.0.2",
|
|
38
36
|
"http-proxy-middleware": "2.0.6",
|
|
@@ -50,8 +48,8 @@
|
|
|
50
48
|
"ora": "5.4.1",
|
|
51
49
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
52
50
|
"picomatch": "3.0.1",
|
|
53
|
-
"piscina": "4.2.
|
|
54
|
-
"postcss": "8.4.
|
|
51
|
+
"piscina": "4.2.1",
|
|
52
|
+
"postcss": "8.4.32",
|
|
55
53
|
"postcss-loader": "7.3.3",
|
|
56
54
|
"resolve-url-loader": "5.0.0",
|
|
57
55
|
"rxjs": "7.8.1",
|
|
@@ -60,12 +58,13 @@
|
|
|
60
58
|
"semver": "7.5.4",
|
|
61
59
|
"source-map-loader": "4.0.1",
|
|
62
60
|
"source-map-support": "0.5.21",
|
|
63
|
-
"terser": "5.
|
|
61
|
+
"terser": "5.26.0",
|
|
64
62
|
"text-table": "0.2.0",
|
|
65
63
|
"tree-kill": "1.2.2",
|
|
66
64
|
"tslib": "2.6.2",
|
|
67
|
-
"undici": "
|
|
68
|
-
"vite": "5.0.
|
|
65
|
+
"undici": "6.0.1",
|
|
66
|
+
"vite": "5.0.7",
|
|
67
|
+
"watchpack": "2.4.0",
|
|
69
68
|
"webpack": "5.89.0",
|
|
70
69
|
"webpack-dev-middleware": "6.1.1",
|
|
71
70
|
"webpack-dev-server": "4.15.1",
|
|
@@ -73,13 +72,14 @@
|
|
|
73
72
|
"webpack-subresource-integrity": "5.1.0"
|
|
74
73
|
},
|
|
75
74
|
"optionalDependencies": {
|
|
76
|
-
"esbuild": "0.19.
|
|
75
|
+
"esbuild": "0.19.9"
|
|
77
76
|
},
|
|
78
77
|
"peerDependencies": {
|
|
79
78
|
"@angular/compiler-cli": "^17.0.0 || ^17.1.0-next.0",
|
|
80
79
|
"@angular/localize": "^17.0.0 || ^17.1.0-next.0",
|
|
81
80
|
"@angular/platform-server": "^17.0.0 || ^17.1.0-next.0",
|
|
82
81
|
"@angular/service-worker": "^17.0.0 || ^17.1.0-next.0",
|
|
82
|
+
"browser-sync": "^2.29.3",
|
|
83
83
|
"jest": "^29.5.0",
|
|
84
84
|
"jest-environment-jsdom": "^29.5.0",
|
|
85
85
|
"karma": "^6.3.0",
|
|
@@ -98,6 +98,9 @@
|
|
|
98
98
|
"@angular/service-worker": {
|
|
99
99
|
"optional": true
|
|
100
100
|
},
|
|
101
|
+
"browser-sync": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
101
104
|
"jest": {
|
|
102
105
|
"optional": true
|
|
103
106
|
},
|
|
@@ -24,4 +24,5 @@ export declare function runEsBuildBuildAction(action: (rebuildState?: RebuildSta
|
|
|
24
24
|
deleteOutputPath?: boolean;
|
|
25
25
|
poll?: number;
|
|
26
26
|
signal?: AbortSignal;
|
|
27
|
+
preserveSymlinks?: boolean;
|
|
27
28
|
}): AsyncIterable<(ExecutionResult['outputWithFiles'] | ExecutionResult['output']) & BuilderOutput>;
|
|
@@ -34,15 +34,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
34
34
|
};
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.runEsBuildBuildAction = void 0;
|
|
37
|
+
const node_fs_1 = require("node:fs");
|
|
37
38
|
const node_path_1 = __importDefault(require("node:path"));
|
|
38
39
|
const sass_language_1 = require("../../tools/esbuild/stylesheets/sass-language");
|
|
39
40
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
40
41
|
const delete_output_dir_1 = require("../../utils/delete-output-dir");
|
|
41
42
|
const environment_options_1 = require("../../utils/environment-options");
|
|
42
43
|
async function* runEsBuildBuildAction(action, options) {
|
|
43
|
-
const { writeToFileSystemFilter, writeToFileSystem = true, watch, poll, logger, deleteOutputPath, cacheOptions, outputPath, verbose, projectRoot, workspaceRoot, progress, } = options;
|
|
44
|
+
const { writeToFileSystemFilter, writeToFileSystem = true, watch, poll, logger, deleteOutputPath, cacheOptions, outputPath, verbose, projectRoot, workspaceRoot, progress, preserveSymlinks, } = options;
|
|
44
45
|
if (deleteOutputPath && writeToFileSystem) {
|
|
45
|
-
await (0, delete_output_dir_1.deleteOutputDir)(workspaceRoot, outputPath);
|
|
46
|
+
await (0, delete_output_dir_1.deleteOutputDir)(workspaceRoot, outputPath, ['browser', 'server']);
|
|
46
47
|
}
|
|
47
48
|
const withProgress = progress ? utils_1.withSpinner : utils_1.withNoProgress;
|
|
48
49
|
// Initial build
|
|
@@ -62,20 +63,25 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
62
63
|
if (progress) {
|
|
63
64
|
logger.info('Watch mode enabled. Watching for file changes...');
|
|
64
65
|
}
|
|
66
|
+
const ignored = [
|
|
67
|
+
// Ignore the output and cache paths to avoid infinite rebuild cycles
|
|
68
|
+
outputPath,
|
|
69
|
+
cacheOptions.basePath,
|
|
70
|
+
`${workspaceRoot.replace(/\\/g, '/')}/**/.*/**`,
|
|
71
|
+
];
|
|
72
|
+
if (!preserveSymlinks) {
|
|
73
|
+
// Ignore all node modules directories to avoid excessive file watchers.
|
|
74
|
+
// Package changes are handled below by watching manifest and lock files.
|
|
75
|
+
// NOTE: this is not enable when preserveSymlinks is true as this would break `npm link` usages.
|
|
76
|
+
ignored.push('**/node_modules/**');
|
|
77
|
+
}
|
|
65
78
|
// Setup a watcher
|
|
66
79
|
const { createWatcher } = await Promise.resolve().then(() => __importStar(require('../../tools/esbuild/watcher')));
|
|
67
80
|
watcher = createWatcher({
|
|
68
81
|
polling: typeof poll === 'number',
|
|
69
82
|
interval: poll,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
outputPath,
|
|
73
|
-
cacheOptions.basePath,
|
|
74
|
-
// Ignore all node modules directories to avoid excessive file watchers.
|
|
75
|
-
// Package changes are handled below by watching manifest and lock files.
|
|
76
|
-
'**/node_modules/**',
|
|
77
|
-
`${workspaceRoot.replace(/\\/g, '/')}/**/.*/**`,
|
|
78
|
-
],
|
|
83
|
+
followSymlinks: preserveSymlinks,
|
|
84
|
+
ignored,
|
|
79
85
|
});
|
|
80
86
|
// Setup abort support
|
|
81
87
|
options.signal?.addEventListener('abort', () => void watcher?.close());
|
|
@@ -96,7 +102,9 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
96
102
|
'.pnp.cjs',
|
|
97
103
|
'.pnp.data.json',
|
|
98
104
|
];
|
|
99
|
-
watcher.add(packageWatchFiles
|
|
105
|
+
watcher.add(packageWatchFiles
|
|
106
|
+
.map((file) => node_path_1.default.join(workspaceRoot, file))
|
|
107
|
+
.filter((file) => (0, node_fs_1.existsSync)(file)));
|
|
100
108
|
// Watch locations provided by the initial build result
|
|
101
109
|
watcher.add(result.watchFiles);
|
|
102
110
|
}
|
|
@@ -39,9 +39,11 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
39
39
|
* NOTE: we don't perform critical CSS inlining as this will be done during server rendering.
|
|
40
40
|
*/
|
|
41
41
|
let indexContentOutputNoCssInlining;
|
|
42
|
+
// When using prerender/app-shell the index HTML file can be regenerated.
|
|
43
|
+
// Thus, we use a Map so that we do not generate 2 files with the same filename.
|
|
44
|
+
const additionalHtmlOutputFiles = new Map();
|
|
42
45
|
// Generate index HTML file
|
|
43
46
|
// If localization is enabled, index generation is handled in the inlining process.
|
|
44
|
-
// NOTE: Localization with SSR is not currently supported.
|
|
45
47
|
if (indexHtmlOptions) {
|
|
46
48
|
const { content, contentWithoutCriticalCssInlined, errors, warnings } = await (0, index_html_generator_1.generateIndexHtml)(initialFiles, outputFiles, {
|
|
47
49
|
...options,
|
|
@@ -50,9 +52,10 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
50
52
|
indexContentOutputNoCssInlining = contentWithoutCriticalCssInlined;
|
|
51
53
|
allErrors.push(...errors);
|
|
52
54
|
allWarnings.push(...warnings);
|
|
53
|
-
|
|
55
|
+
additionalHtmlOutputFiles.set(indexHtmlOptions.output, (0, utils_1.createOutputFileFromText)(indexHtmlOptions.output, content, bundler_context_1.BuildOutputFileType.Browser));
|
|
54
56
|
if (ssrOptions) {
|
|
55
|
-
|
|
57
|
+
const serverIndexHtmlFilename = 'index.server.html';
|
|
58
|
+
additionalHtmlOutputFiles.set(serverIndexHtmlFilename, (0, utils_1.createOutputFileFromText)(serverIndexHtmlFilename, contentWithoutCriticalCssInlined, bundler_context_1.BuildOutputFileType.Server));
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
61
|
// Pre-render (SSG) and App-shell
|
|
@@ -64,9 +67,10 @@ async function executePostBundleSteps(options, outputFiles, assetFiles, initialF
|
|
|
64
67
|
allWarnings.push(...warnings);
|
|
65
68
|
prerenderedRoutes.push(...Array.from(generatedRoutes));
|
|
66
69
|
for (const [path, content] of Object.entries(output)) {
|
|
67
|
-
|
|
70
|
+
additionalHtmlOutputFiles.set(path, (0, utils_1.createOutputFileFromText)(path, content, bundler_context_1.BuildOutputFileType.Browser));
|
|
68
71
|
}
|
|
69
72
|
}
|
|
73
|
+
additionalOutputFiles.push(...additionalHtmlOutputFiles.values());
|
|
70
74
|
// Augment the application with service worker support
|
|
71
75
|
// If localization is enabled, service worker is handled in the inlining process.
|
|
72
76
|
if (serviceWorker) {
|
|
@@ -29,6 +29,13 @@ context, infrastructureSettings, plugins) {
|
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
const normalizedOptions = await (0, options_1.normalizeOptions)(context, projectName, options, plugins);
|
|
32
|
+
// Setup an abort controller with a builder teardown if no signal is present
|
|
33
|
+
let signal = context.signal;
|
|
34
|
+
if (!signal) {
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
signal = controller.signal;
|
|
37
|
+
context.addTeardown(() => controller.abort('builder-teardown'));
|
|
38
|
+
}
|
|
32
39
|
yield* (0, build_action_1.runEsBuildBuildAction)(async (rebuildState) => {
|
|
33
40
|
const startTime = process.hrtime.bigint();
|
|
34
41
|
const result = await (0, execute_build_1.executeBuild)(normalizedOptions, context, rebuildState);
|
|
@@ -38,6 +45,7 @@ context, infrastructureSettings, plugins) {
|
|
|
38
45
|
return result;
|
|
39
46
|
}, {
|
|
40
47
|
watch: normalizedOptions.watch,
|
|
48
|
+
preserveSymlinks: normalizedOptions.preserveSymlinks,
|
|
41
49
|
poll: normalizedOptions.poll,
|
|
42
50
|
deleteOutputPath: normalizedOptions.deleteOutputPath,
|
|
43
51
|
cacheOptions: normalizedOptions.cacheOptions,
|
|
@@ -53,7 +61,7 @@ context, infrastructureSettings, plugins) {
|
|
|
53
61
|
? undefined
|
|
54
62
|
: (file) => file.type !== bundler_context_1.BuildOutputFileType.Server,
|
|
55
63
|
logger: context.logger,
|
|
56
|
-
signal
|
|
64
|
+
signal,
|
|
57
65
|
});
|
|
58
66
|
}
|
|
59
67
|
exports.buildApplicationInternal = buildApplicationInternal;
|
|
@@ -181,7 +181,7 @@ async function normalizeOptions(context, projectName, options, plugins) {
|
|
|
181
181
|
const { allowedCommonJsDependencies, aot, baseHref, crossOrigin, externalDependencies, extractLicenses, inlineStyleLanguage = 'css', outExtension, serviceWorker, poll, polyfills, statsJson, stylePreprocessorOptions, subresourceIntegrity, verbose, watch, progress = true, externalPackages, deleteOutputPath, namedChunks, budgets, deployUrl, } = options;
|
|
182
182
|
// Return all the normalized options
|
|
183
183
|
return {
|
|
184
|
-
advancedOptimizations: !!aot,
|
|
184
|
+
advancedOptimizations: !!aot && optimizationOptions.scripts,
|
|
185
185
|
allowedCommonJsDependencies,
|
|
186
186
|
baseHref,
|
|
187
187
|
cacheOptions,
|
|
@@ -30,9 +30,7 @@ function logBuilderStatusWarnings(options, { logger }) {
|
|
|
30
30
|
if (typeof value === 'object' && Object.keys(value).length === 0) {
|
|
31
31
|
continue;
|
|
32
32
|
}
|
|
33
|
-
if (unsupportedOption === 'vendorChunk' ||
|
|
34
|
-
unsupportedOption === 'resourcesOutputPath' ||
|
|
35
|
-
unsupportedOption === 'deployUrl') {
|
|
33
|
+
if (unsupportedOption === 'vendorChunk' || unsupportedOption === 'resourcesOutputPath') {
|
|
36
34
|
logger.warn(`The '${unsupportedOption}' option is not used by this builder and will be ignored.`);
|
|
37
35
|
continue;
|
|
38
36
|
}
|
|
@@ -65,6 +65,11 @@ function execute(options, context, transforms = {}, extensions) {
|
|
|
65
65
|
if (transforms?.logging || transforms?.webpackConfiguration) {
|
|
66
66
|
throw new Error('The `application` and `browser-esbuild` builders do not support Webpack transforms.');
|
|
67
67
|
}
|
|
68
|
+
if (normalizedOptions.forceEsbuild &&
|
|
69
|
+
builderName === '@angular-devkit/build-angular:browser') {
|
|
70
|
+
// The compatibility builder should be used if esbuild is force enabled with the official Webpack-based builder.
|
|
71
|
+
builderName = '@angular-devkit/build-angular:browser-esbuild';
|
|
72
|
+
}
|
|
68
73
|
return (0, rxjs_1.defer)(() => Promise.resolve().then(() => __importStar(require('./vite-server')))).pipe((0, rxjs_1.switchMap)(({ serveWithVite }) => serveWithVite(normalizedOptions, builderName, context, transforms, extensions)));
|
|
69
74
|
}
|
|
70
75
|
if (extensions?.buildPlugins?.length) {
|
|
@@ -74,8 +74,11 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
74
74
|
}
|
|
75
75
|
// Set all packages as external to support Vite's prebundle caching
|
|
76
76
|
browserOptions.externalPackages = serverOptions.cacheOptions.enabled;
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const baseHref = browserOptions.baseHref;
|
|
78
|
+
if (serverOptions.servePath === undefined && baseHref !== undefined) {
|
|
79
|
+
// Remove trailing slash
|
|
80
|
+
serverOptions.servePath =
|
|
81
|
+
baseHref[baseHref.length - 1] === '/' ? baseHref.slice(0, -1) : baseHref;
|
|
79
82
|
}
|
|
80
83
|
// The development server currently only supports a single locale when localizing.
|
|
81
84
|
// This matches the behavior of the Webpack-based development server but could be expanded in the future.
|
|
@@ -157,7 +160,7 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
157
160
|
assetFiles.clear();
|
|
158
161
|
if (result.assetFiles) {
|
|
159
162
|
for (const asset of result.assetFiles) {
|
|
160
|
-
assetFiles.set('/' + normalizePath(asset.destination), asset.source);
|
|
163
|
+
assetFiles.set('/' + normalizePath(asset.destination), normalizePath(asset.source));
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
166
|
// To avoid disconnecting the array objects from the option, these arrays need to be mutated instead of replaced.
|
|
@@ -179,7 +182,7 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
179
182
|
if (server) {
|
|
180
183
|
// Update fs allow list to include any new assets from the build option.
|
|
181
184
|
server.config.server.fs.allow = [
|
|
182
|
-
...new Set(...server.config.server.fs.allow, ...assetFiles.values()),
|
|
185
|
+
...new Set([...server.config.server.fs.allow, ...assetFiles.values()]),
|
|
183
186
|
];
|
|
184
187
|
handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
|
|
185
188
|
}
|
|
@@ -350,7 +353,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
350
353
|
css: {
|
|
351
354
|
devSourcemap: true,
|
|
352
355
|
},
|
|
353
|
-
// Vite will normalize the `base` option by adding a leading
|
|
356
|
+
// Vite will normalize the `base` option by adding a leading slash.
|
|
354
357
|
base: serverOptions.servePath,
|
|
355
358
|
resolve: {
|
|
356
359
|
mainFields: ['es2020', 'browser', 'module', 'main'],
|
|
@@ -476,6 +479,10 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
476
479
|
// Rewrite all build assets to a vite raw fs URL
|
|
477
480
|
const assetSourcePath = assets.get(pathname);
|
|
478
481
|
if (assetSourcePath !== undefined) {
|
|
482
|
+
// Workaround to disable Vite transformer middleware.
|
|
483
|
+
// See: https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/middlewares/transform.ts#L201 and
|
|
484
|
+
// https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/transformRequest.ts#L204-L206
|
|
485
|
+
req.headers.accept = 'text/html';
|
|
479
486
|
// The encoding needs to match what happens in the vite static middleware.
|
|
480
487
|
// ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
|
|
481
488
|
req.url = `${server.config.base}@fs/${encodeURI(assetSourcePath)}`;
|
|
@@ -90,9 +90,12 @@ function execute(options, context, transforms = {}) {
|
|
|
90
90
|
: getBuiltInKarmaConfig(context.workspaceRoot, projectName);
|
|
91
91
|
karmaOptions.singleRun = singleRun;
|
|
92
92
|
// Convert browsers from a string to an array
|
|
93
|
-
if (options.browsers) {
|
|
93
|
+
if (typeof options.browsers === 'string' && options.browsers) {
|
|
94
94
|
karmaOptions.browsers = options.browsers.split(',');
|
|
95
95
|
}
|
|
96
|
+
else if (options.browsers === false) {
|
|
97
|
+
karmaOptions.browsers = [];
|
|
98
|
+
}
|
|
96
99
|
if (options.reporters) {
|
|
97
100
|
// Split along commas to make it more natural, and remove empty strings.
|
|
98
101
|
const reporters = options.reporters
|
|
@@ -7,9 +7,9 @@ export interface Schema {
|
|
|
7
7
|
*/
|
|
8
8
|
assets?: AssetPattern[];
|
|
9
9
|
/**
|
|
10
|
-
* Override which browsers tests are run against.
|
|
10
|
+
* Override which browsers tests are run against. Set to `false` to not use any browser.
|
|
11
11
|
*/
|
|
12
|
-
browsers?:
|
|
12
|
+
browsers?: Browsers;
|
|
13
13
|
/**
|
|
14
14
|
* Output a code coverage report.
|
|
15
15
|
*/
|
|
@@ -117,6 +117,10 @@ export interface AssetPatternClass {
|
|
|
117
117
|
*/
|
|
118
118
|
output: string;
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Override which browsers tests are run against. Set to `false` to not use any browser.
|
|
122
|
+
*/
|
|
123
|
+
export type Browsers = boolean | string;
|
|
120
124
|
export interface FileReplacement {
|
|
121
125
|
replace?: string;
|
|
122
126
|
replaceWith?: string;
|
|
@@ -199,8 +199,18 @@
|
|
|
199
199
|
"description": "Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set."
|
|
200
200
|
},
|
|
201
201
|
"browsers": {
|
|
202
|
-
"
|
|
203
|
-
"
|
|
202
|
+
"description": "Override which browsers tests are run against. Set to `false` to not use any browser.",
|
|
203
|
+
"oneOf": [
|
|
204
|
+
{
|
|
205
|
+
"type": "string",
|
|
206
|
+
"description": "A comma seperate list of browsers to run tests against."
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"const": false,
|
|
210
|
+
"type": "boolean",
|
|
211
|
+
"description": "Does use run tests against a browser."
|
|
212
|
+
}
|
|
213
|
+
]
|
|
204
214
|
},
|
|
205
215
|
"codeCoverage": {
|
|
206
216
|
"type": "boolean",
|
|
@@ -35,7 +35,6 @@ const architect_1 = require("@angular-devkit/architect");
|
|
|
35
35
|
const core_1 = require("@angular-devkit/core");
|
|
36
36
|
const path_1 = require("path");
|
|
37
37
|
const rxjs_1 = require("rxjs");
|
|
38
|
-
const operators_1 = require("rxjs/operators");
|
|
39
38
|
const url = __importStar(require("url"));
|
|
40
39
|
const error_1 = require("../../utils/error");
|
|
41
40
|
const utils_1 = require("./utils");
|
|
@@ -60,7 +59,17 @@ function execute(options, context) {
|
|
|
60
59
|
progress: options.progress,
|
|
61
60
|
verbose: options.verbose,
|
|
62
61
|
});
|
|
63
|
-
|
|
62
|
+
let browserSync;
|
|
63
|
+
try {
|
|
64
|
+
browserSync = require('browser-sync');
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return (0, rxjs_1.of)({
|
|
68
|
+
success: false,
|
|
69
|
+
error: '"browser-sync" is not installed, most likely you need to run `npm install browser-sync --save-dev` in your project.',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const bsInstance = browserSync.create();
|
|
64
73
|
context.logger.error(core_1.tags.stripIndents `
|
|
65
74
|
****************************************************************************************
|
|
66
75
|
This is a simple server for use in testing or debugging Angular applications locally.
|
|
@@ -69,35 +78,35 @@ function execute(options, context) {
|
|
|
69
78
|
DON'T USE IT FOR PRODUCTION!
|
|
70
79
|
****************************************************************************************
|
|
71
80
|
`);
|
|
72
|
-
return (0, rxjs_1.zip)(browserTargetRun, serverTargetRun, (0, utils_1.getAvailablePort)()).pipe((0,
|
|
81
|
+
return (0, rxjs_1.zip)(browserTargetRun, serverTargetRun, (0, utils_1.getAvailablePort)()).pipe((0, rxjs_1.switchMap)(([br, sr, nodeServerPort]) => {
|
|
73
82
|
return (0, rxjs_1.combineLatest)([br.output, sr.output]).pipe(
|
|
74
83
|
// This is needed so that if both server and browser emit close to each other
|
|
75
84
|
// we only emit once. This typically happens on the first build.
|
|
76
|
-
(0,
|
|
85
|
+
(0, rxjs_1.debounceTime)(120), (0, rxjs_1.switchMap)(([b, s]) => {
|
|
77
86
|
if (!s.success || !b.success) {
|
|
78
87
|
return (0, rxjs_1.of)([b, s]);
|
|
79
88
|
}
|
|
80
|
-
return startNodeServer(s, nodeServerPort, context.logger, !!options.inspect).pipe((0,
|
|
89
|
+
return startNodeServer(s, nodeServerPort, context.logger, !!options.inspect).pipe((0, rxjs_1.map)(() => [b, s]), (0, rxjs_1.catchError)((err) => {
|
|
81
90
|
context.logger.error(`A server error has occurred.\n${mapErrorToMessage(err)}`);
|
|
82
91
|
return rxjs_1.EMPTY;
|
|
83
92
|
}));
|
|
84
|
-
}), (0,
|
|
93
|
+
}), (0, rxjs_1.map)(([b, s]) => [
|
|
85
94
|
{
|
|
86
95
|
success: b.success && s.success,
|
|
87
96
|
error: b.error || s.error,
|
|
88
97
|
},
|
|
89
98
|
nodeServerPort,
|
|
90
|
-
]), (0,
|
|
99
|
+
]), (0, rxjs_1.tap)(([builderOutput]) => {
|
|
91
100
|
if (builderOutput.success) {
|
|
92
101
|
context.logger.info('\nCompiled successfully.');
|
|
93
102
|
}
|
|
94
|
-
}), (0,
|
|
103
|
+
}), (0, rxjs_1.debounce)(([builderOutput]) => builderOutput.success && !options.inspect
|
|
95
104
|
? (0, utils_1.waitUntilServerIsListening)(nodeServerPort)
|
|
96
|
-
: rxjs_1.EMPTY), (0,
|
|
105
|
+
: rxjs_1.EMPTY), (0, rxjs_1.finalize)(() => {
|
|
97
106
|
void br.stop();
|
|
98
107
|
void sr.stop();
|
|
99
108
|
}));
|
|
100
|
-
}), (0,
|
|
109
|
+
}), (0, rxjs_1.concatMap)(([builderOutput, nodeServerPort]) => {
|
|
101
110
|
if (!builderOutput.success) {
|
|
102
111
|
return (0, rxjs_1.of)(builderOutput);
|
|
103
112
|
}
|
|
@@ -106,7 +115,7 @@ function execute(options, context) {
|
|
|
106
115
|
return (0, rxjs_1.of)(builderOutput);
|
|
107
116
|
}
|
|
108
117
|
else {
|
|
109
|
-
return (0, rxjs_1.from)(initBrowserSync(bsInstance, nodeServerPort, options, context)).pipe((0,
|
|
118
|
+
return (0, rxjs_1.from)(initBrowserSync(bsInstance, nodeServerPort, options, context)).pipe((0, rxjs_1.tap)((bs) => {
|
|
110
119
|
const baseUrl = getBaseUrl(bs);
|
|
111
120
|
context.logger.info(core_1.tags.oneLine `
|
|
112
121
|
**
|
|
@@ -114,19 +123,19 @@ function execute(options, context) {
|
|
|
114
123
|
open your browser on ${baseUrl}
|
|
115
124
|
**
|
|
116
125
|
`);
|
|
117
|
-
}), (0,
|
|
126
|
+
}), (0, rxjs_1.map)(() => builderOutput));
|
|
118
127
|
}
|
|
119
|
-
}), (0,
|
|
128
|
+
}), (0, rxjs_1.map)((builderOutput) => ({
|
|
120
129
|
success: builderOutput.success,
|
|
121
130
|
error: builderOutput.error,
|
|
122
131
|
baseUrl: getBaseUrl(bsInstance),
|
|
123
132
|
port: bsInstance.getOption('port'),
|
|
124
|
-
})), (0,
|
|
133
|
+
})), (0, rxjs_1.finalize)(() => {
|
|
125
134
|
if (bsInstance) {
|
|
126
135
|
bsInstance.exit();
|
|
127
136
|
bsInstance.cleanup();
|
|
128
137
|
}
|
|
129
|
-
}), (0,
|
|
138
|
+
}), (0, rxjs_1.catchError)((error) => (0, rxjs_1.of)({
|
|
130
139
|
success: false,
|
|
131
140
|
error: mapErrorToMessage(error),
|
|
132
141
|
})));
|
|
@@ -152,10 +161,10 @@ function startNodeServer(serverOutput, port, logger, inspectMode = false) {
|
|
|
152
161
|
if (inspectMode) {
|
|
153
162
|
args.unshift('--inspect-brk');
|
|
154
163
|
}
|
|
155
|
-
return (0, rxjs_1.of)(null).pipe((0,
|
|
156
|
-
(0,
|
|
164
|
+
return (0, rxjs_1.of)(null).pipe((0, rxjs_1.delay)(0), // Avoid EADDRINUSE error since it will cause the kill event to be finish.
|
|
165
|
+
(0, rxjs_1.switchMap)(() => (0, utils_1.spawnAsObservable)('node', args, { env, shell: true })), (0, rxjs_1.tap)((res) => log({ stderr: res.stderr, stdout: res.stdout }, logger)), (0, rxjs_1.ignoreElements)(),
|
|
157
166
|
// Emit a signal after the process has been started
|
|
158
|
-
(0,
|
|
167
|
+
(0, rxjs_1.startWith)(undefined));
|
|
159
168
|
}
|
|
160
169
|
async function initBrowserSync(browserSyncInstance, nodeServerPort, options, context) {
|
|
161
170
|
if (browserSyncInstance.active) {
|
|
@@ -28,6 +28,12 @@ exports.ensureSourceFileVersions = ensureSourceFileVersions;
|
|
|
28
28
|
function createAngularCompilerHost(compilerOptions, hostOptions) {
|
|
29
29
|
// Create TypeScript compiler host
|
|
30
30
|
const host = typescript_1.default.createIncrementalCompilerHost(compilerOptions);
|
|
31
|
+
// Set the parsing mode to the same as TS 5.3 default for tsc. This provides a parse
|
|
32
|
+
// performance improvement by skipping non-type related JSDoc parsing.
|
|
33
|
+
// NOTE: The check for this enum can be removed when TS 5.3 support is the minimum.
|
|
34
|
+
if (typescript_1.default.JSDocParsingMode) {
|
|
35
|
+
host.jsDocParsingMode = typescript_1.default.JSDocParsingMode.ParseForTypeErrors;
|
|
36
|
+
}
|
|
31
37
|
// The AOT compiler currently requires this hook to allow for a transformResource hook.
|
|
32
38
|
// Once the AOT compiler allows only a transformResource hook, this can be reevaluated.
|
|
33
39
|
host.readResource = async function (filename) {
|
|
@@ -308,7 +308,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
308
308
|
}));
|
|
309
309
|
// Setup bundling of component templates and stylesheets when in JIT mode
|
|
310
310
|
if (pluginOptions.jit) {
|
|
311
|
-
(0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, styleOptions.inlineStyleLanguage);
|
|
311
|
+
(0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, styleOptions.inlineStyleLanguage, pluginOptions.loadResultCache);
|
|
312
312
|
}
|
|
313
313
|
build.onEnd((result) => {
|
|
314
314
|
// Ensure other compilations are unblocked if the main compilation throws during start
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import type { Metafile, OutputFile, PluginBuild } from 'esbuild';
|
|
9
|
+
import { LoadResultCache } from '../load-result-cache';
|
|
9
10
|
import { ComponentStylesheetBundler } from './component-stylesheets';
|
|
10
11
|
/**
|
|
11
12
|
* Sets up esbuild resolve and load callbacks to support Angular JIT mode processing
|
|
@@ -19,4 +20,4 @@ import { ComponentStylesheetBundler } from './component-stylesheets';
|
|
|
19
20
|
export declare function setupJitPluginCallbacks(build: PluginBuild, stylesheetBundler: ComponentStylesheetBundler, additionalResultFiles: Map<string, {
|
|
20
21
|
outputFiles?: OutputFile[];
|
|
21
22
|
metafile?: Metafile;
|
|
22
|
-
}>, inlineStyleLanguage: string): void;
|
|
23
|
+
}>, inlineStyleLanguage: string, loadCache?: LoadResultCache): void;
|