@angular-devkit/build-angular 17.1.2 → 17.2.0-next.1
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 +31 -32
- package/src/builders/application/build-action.js +0 -4
- package/src/builders/application/execute-build.js +8 -15
- package/src/builders/application/index.js +19 -3
- package/src/builders/application/options.d.ts +3 -0
- package/src/builders/application/options.js +12 -1
- package/src/builders/application/setup-bundling.js +2 -2
- package/src/builders/dev-server/options.js +3 -2
- package/src/builders/dev-server/schema.json +1 -1
- package/src/builders/extract-i18n/options.js +3 -2
- package/src/builders/extract-i18n/schema.json +1 -1
- package/src/builders/jest/index.js +44 -5
- package/src/builders/jest/jest.config.mjs +11 -0
- package/src/tools/babel/plugins/elide-angular-metadata.d.ts +1 -1
- package/src/tools/babel/plugins/elide-angular-metadata.js +38 -30
- package/src/tools/babel/plugins/pure-toplevel-functions.d.ts +1 -1
- package/src/tools/babel/plugins/pure-toplevel-functions.js +3 -4
- package/src/tools/esbuild/angular/compilation/angular-compilation.d.ts +9 -2
- package/src/tools/esbuild/angular/compilation/angular-compilation.js +11 -3
- package/src/tools/esbuild/angular/compilation/aot-compilation.d.ts +2 -2
- package/src/tools/esbuild/angular/compilation/aot-compilation.js +19 -8
- package/src/tools/esbuild/angular/compilation/index.d.ts +1 -1
- package/src/tools/esbuild/angular/compilation/index.js +2 -1
- package/src/tools/esbuild/angular/compilation/jit-compilation.d.ts +2 -2
- package/src/tools/esbuild/angular/compilation/jit-compilation.js +12 -6
- package/src/tools/esbuild/angular/compilation/parallel-compilation.d.ts +2 -2
- package/src/tools/esbuild/angular/compilation/parallel-compilation.js +2 -2
- package/src/tools/esbuild/angular/compilation/parallel-worker.d.ts +2 -1
- package/src/tools/esbuild/angular/compilation/parallel-worker.js +2 -2
- package/src/tools/esbuild/angular/compiler-plugin.js +7 -7
- package/src/tools/esbuild/application-code-bundle.js +2 -2
- package/src/tools/esbuild/budget-stats.js +5 -0
- package/src/tools/esbuild/bundler-context.js +6 -0
- package/src/tools/esbuild/bundler-execution-result.d.ts +2 -0
- package/src/tools/esbuild/bundler-execution-result.js +6 -0
- package/src/tools/esbuild/compiler-plugin-options.js +2 -1
- package/src/tools/esbuild/global-scripts.js +3 -4
- package/src/tools/esbuild/global-styles.js +2 -1
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
- package/src/tools/esbuild/stylesheets/bundle-options.js +1 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +7 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +24 -8
- package/src/tools/esbuild/utils.d.ts +5 -8
- package/src/tools/esbuild/utils.js +64 -31
- package/src/tools/vite/angular-memory-plugin.js +6 -5
- package/src/tools/webpack/utils/stats.d.ts +1 -0
- package/src/tools/webpack/utils/stats.js +98 -47
- package/src/utils/environment-options.d.ts +2 -0
- package/src/utils/environment-options.js +5 -1
- package/src/utils/postcss-configuration.d.ts +11 -0
- package/src/utils/postcss-configuration.js +77 -0
package/package.json
CHANGED
|
@@ -1,90 +1,89 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "17.1
|
|
3
|
+
"version": "17.2.0-next.1",
|
|
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.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.
|
|
12
|
-
"@angular-devkit/core": "17.1
|
|
13
|
-
"@babel/core": "7.23.
|
|
10
|
+
"@angular-devkit/architect": "0.1702.0-next.1",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1702.0-next.1",
|
|
12
|
+
"@angular-devkit/core": "17.2.0-next.1",
|
|
13
|
+
"@babel/core": "7.23.9",
|
|
14
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
|
-
"@babel/plugin-transform-async-generator-functions": "7.23.
|
|
17
|
+
"@babel/plugin-transform-async-generator-functions": "7.23.9",
|
|
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.9",
|
|
20
|
+
"@babel/preset-env": "7.23.9",
|
|
21
|
+
"@babel/runtime": "7.23.9",
|
|
22
22
|
"@discoveryjs/json-ext": "0.5.7",
|
|
23
|
-
"@ngtools/webpack": "17.1
|
|
24
|
-
"@vitejs/plugin-basic-ssl": "1.0
|
|
23
|
+
"@ngtools/webpack": "17.2.0-next.1",
|
|
24
|
+
"@vitejs/plugin-basic-ssl": "1.1.0",
|
|
25
25
|
"ansi-colors": "4.1.3",
|
|
26
|
-
"autoprefixer": "10.4.
|
|
26
|
+
"autoprefixer": "10.4.17",
|
|
27
27
|
"babel-loader": "9.1.3",
|
|
28
28
|
"babel-plugin-istanbul": "6.1.1",
|
|
29
29
|
"browserslist": "^4.21.5",
|
|
30
|
-
"copy-webpack-plugin": "
|
|
30
|
+
"copy-webpack-plugin": "12.0.2",
|
|
31
31
|
"critters": "0.0.20",
|
|
32
|
-
"css-loader": "6.
|
|
33
|
-
"esbuild-wasm": "0.
|
|
32
|
+
"css-loader": "6.10.0",
|
|
33
|
+
"esbuild-wasm": "0.20.0",
|
|
34
34
|
"fast-glob": "3.3.2",
|
|
35
35
|
"https-proxy-agent": "7.0.2",
|
|
36
36
|
"http-proxy-middleware": "2.0.6",
|
|
37
|
-
"inquirer": "9.2.
|
|
38
|
-
"jsonc-parser": "3.2.
|
|
37
|
+
"inquirer": "9.2.13",
|
|
38
|
+
"jsonc-parser": "3.2.1",
|
|
39
39
|
"karma-source-map-support": "1.4.0",
|
|
40
40
|
"less": "4.2.0",
|
|
41
41
|
"less-loader": "11.1.0",
|
|
42
42
|
"license-webpack-plugin": "4.0.2",
|
|
43
43
|
"loader-utils": "3.2.1",
|
|
44
44
|
"magic-string": "0.30.5",
|
|
45
|
-
"mini-css-extract-plugin": "2.7.
|
|
45
|
+
"mini-css-extract-plugin": "2.7.7",
|
|
46
46
|
"mrmime": "2.0.0",
|
|
47
47
|
"open": "8.4.2",
|
|
48
48
|
"ora": "5.4.1",
|
|
49
49
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
50
50
|
"picomatch": "3.0.1",
|
|
51
|
-
"piscina": "4.
|
|
51
|
+
"piscina": "4.3.1",
|
|
52
52
|
"postcss": "8.4.33",
|
|
53
|
-
"postcss-loader": "
|
|
53
|
+
"postcss-loader": "8.1.0",
|
|
54
54
|
"resolve-url-loader": "5.0.0",
|
|
55
55
|
"rxjs": "7.8.1",
|
|
56
|
-
"sass": "1.
|
|
57
|
-
"sass-loader": "
|
|
56
|
+
"sass": "1.70.0",
|
|
57
|
+
"sass-loader": "14.1.0",
|
|
58
58
|
"semver": "7.5.4",
|
|
59
59
|
"source-map-loader": "5.0.0",
|
|
60
60
|
"source-map-support": "0.5.21",
|
|
61
|
-
"terser": "5.
|
|
62
|
-
"text-table": "0.2.0",
|
|
61
|
+
"terser": "5.27.0",
|
|
63
62
|
"tree-kill": "1.2.2",
|
|
64
63
|
"tslib": "2.6.2",
|
|
65
|
-
"undici": "6.
|
|
64
|
+
"undici": "6.5.0",
|
|
66
65
|
"vite": "5.0.12",
|
|
67
66
|
"watchpack": "2.4.0",
|
|
68
|
-
"webpack": "5.
|
|
67
|
+
"webpack": "5.90.0",
|
|
69
68
|
"webpack-dev-middleware": "6.1.1",
|
|
70
69
|
"webpack-dev-server": "4.15.1",
|
|
71
70
|
"webpack-merge": "5.10.0",
|
|
72
71
|
"webpack-subresource-integrity": "5.1.0"
|
|
73
72
|
},
|
|
74
73
|
"optionalDependencies": {
|
|
75
|
-
"esbuild": "0.
|
|
74
|
+
"esbuild": "0.20.0"
|
|
76
75
|
},
|
|
77
76
|
"peerDependencies": {
|
|
78
|
-
"@angular/compiler-cli": "^17.0.0",
|
|
79
|
-
"@angular/localize": "^17.0.0",
|
|
80
|
-
"@angular/platform-server": "^17.0.0",
|
|
81
|
-
"@angular/service-worker": "^17.0.0",
|
|
77
|
+
"@angular/compiler-cli": "^17.0.0 || ^17.2.0-next.0",
|
|
78
|
+
"@angular/localize": "^17.0.0 || ^17.2.0-next.0",
|
|
79
|
+
"@angular/platform-server": "^17.0.0 || ^17.2.0-next.0",
|
|
80
|
+
"@angular/service-worker": "^17.0.0 || ^17.2.0-next.0",
|
|
82
81
|
"@web/test-runner": "^0.18.0",
|
|
83
82
|
"browser-sync": "^3.0.2",
|
|
84
83
|
"jest": "^29.5.0",
|
|
85
84
|
"jest-environment-jsdom": "^29.5.0",
|
|
86
85
|
"karma": "^6.3.0",
|
|
87
|
-
"ng-packagr": "^17.0.0",
|
|
86
|
+
"ng-packagr": "^17.0.0 || ^17.2.0-next.0",
|
|
88
87
|
"protractor": "^7.0.0",
|
|
89
88
|
"tailwindcss": "^2.0.0 || ^3.0.0",
|
|
90
89
|
"typescript": ">=5.2 <5.4"
|
|
@@ -54,8 +54,6 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
54
54
|
try {
|
|
55
55
|
// Perform the build action
|
|
56
56
|
result = await withProgress('Building...', () => action());
|
|
57
|
-
// Log all diagnostic (error/warning) messages from the build
|
|
58
|
-
await (0, utils_1.logMessages)(logger, result);
|
|
59
57
|
}
|
|
60
58
|
finally {
|
|
61
59
|
// Ensure Sass workers are shutdown if not watching
|
|
@@ -142,8 +140,6 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
142
140
|
logger.info(changes.toDebugString());
|
|
143
141
|
}
|
|
144
142
|
result = await withProgress('Changes detected. Rebuilding...', () => action(result.createRebuildState(changes)));
|
|
145
|
-
// Log all diagnostic (error/warning) messages from the rebuild
|
|
146
|
-
await (0, utils_1.logMessages)(logger, result);
|
|
147
143
|
// Update watched locations provided by the new build result.
|
|
148
144
|
// Keep watching all previous files if there are any errors; otherwise consider all
|
|
149
145
|
// files stale until confirmed present in the new result's watch files.
|
|
@@ -16,14 +16,13 @@ const commonjs_checker_1 = require("../../tools/esbuild/commonjs-checker");
|
|
|
16
16
|
const license_extractor_1 = require("../../tools/esbuild/license-extractor");
|
|
17
17
|
const utils_1 = require("../../tools/esbuild/utils");
|
|
18
18
|
const bundle_calculator_1 = require("../../utils/bundle-calculator");
|
|
19
|
-
const color_1 = require("../../utils/color");
|
|
20
19
|
const copy_assets_1 = require("../../utils/copy-assets");
|
|
21
20
|
const supported_browsers_1 = require("../../utils/supported-browsers");
|
|
22
21
|
const execute_post_bundle_1 = require("./execute-post-bundle");
|
|
23
22
|
const i18n_1 = require("./i18n");
|
|
24
23
|
const setup_bundling_1 = require("./setup-bundling");
|
|
25
24
|
async function executeBuild(options, context, rebuildState) {
|
|
26
|
-
const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, prerenderOptions, } = options;
|
|
25
|
+
const { projectRoot, workspaceRoot, i18nOptions, optimizationOptions, assets, cacheOptions, prerenderOptions, ssrOptions, verbose, colors, jsonLogs, } = options;
|
|
27
26
|
// TODO: Consider integrating into watch mode. Would require full rebuild on target changes.
|
|
28
27
|
const browsers = (0, supported_browsers_1.getSupportedBrowsers)(projectRoot, context.logger);
|
|
29
28
|
// Load active translations if inlining
|
|
@@ -96,12 +95,11 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
96
95
|
executionResult.addOutputFile('3rdpartylicenses.txt', await (0, license_extractor_1.extractLicenses)(metafile, workspaceRoot), bundler_context_1.BuildOutputFileType.Root);
|
|
97
96
|
}
|
|
98
97
|
// Perform i18n translation inlining if enabled
|
|
99
|
-
let prerenderedRoutes;
|
|
100
98
|
if (i18nOptions.shouldInline) {
|
|
101
99
|
const result = await (0, i18n_1.inlineI18n)(options, executionResult, initialFiles);
|
|
102
100
|
executionResult.addErrors(result.errors);
|
|
103
101
|
executionResult.addWarnings(result.warnings);
|
|
104
|
-
|
|
102
|
+
executionResult.addPrerenderedRoutes(result.prerenderedRoutes);
|
|
105
103
|
}
|
|
106
104
|
else {
|
|
107
105
|
const result = await (0, execute_post_bundle_1.executePostBundleSteps)(options, executionResult.outputFiles, executionResult.assetFiles, initialFiles,
|
|
@@ -109,26 +107,21 @@ async function executeBuild(options, context, rebuildState) {
|
|
|
109
107
|
i18nOptions.hasDefinedSourceLocale ? i18nOptions.sourceLocale : undefined);
|
|
110
108
|
executionResult.addErrors(result.errors);
|
|
111
109
|
executionResult.addWarnings(result.warnings);
|
|
112
|
-
|
|
110
|
+
executionResult.addPrerenderedRoutes(result.prerenderedRoutes);
|
|
113
111
|
executionResult.outputFiles.push(...result.additionalOutputFiles);
|
|
114
112
|
executionResult.assetFiles.push(...result.additionalAssets);
|
|
115
113
|
}
|
|
116
114
|
if (prerenderOptions) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (prerenderedRoutes.length > 1) {
|
|
120
|
-
prerenderMsg += 's.';
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
prerenderMsg += '.';
|
|
124
|
-
}
|
|
125
|
-
context.logger.info(color_1.colors.magenta(prerenderMsg) + '\n');
|
|
115
|
+
const prerenderedRoutes = executionResult.prerenderedRoutes;
|
|
116
|
+
executionResult.addOutputFile('prerendered-routes.json', JSON.stringify({ routes: prerenderedRoutes }, null, 2), bundler_context_1.BuildOutputFileType.Root);
|
|
126
117
|
}
|
|
127
|
-
(0, utils_1.logBuildStats)(context.logger, metafile, initialFiles, budgetFailures, changedFiles, estimatedTransferSizes);
|
|
128
118
|
// Write metafile if stats option is enabled
|
|
129
119
|
if (options.stats) {
|
|
130
120
|
executionResult.addOutputFile('stats.json', JSON.stringify(metafile, null, 2), bundler_context_1.BuildOutputFileType.Root);
|
|
131
121
|
}
|
|
122
|
+
if (!jsonLogs) {
|
|
123
|
+
context.logger.info((0, utils_1.logBuildStats)(metafile, initialFiles, budgetFailures, colors, changedFiles, estimatedTransferSizes, !!ssrOptions, verbose));
|
|
124
|
+
}
|
|
132
125
|
return executionResult;
|
|
133
126
|
}
|
|
134
127
|
exports.executeBuild = executeBuild;
|
|
@@ -10,6 +10,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.buildApplication = exports.buildApplicationInternal = void 0;
|
|
11
11
|
const architect_1 = require("@angular-devkit/architect");
|
|
12
12
|
const bundler_context_1 = require("../../tools/esbuild/bundler-context");
|
|
13
|
+
const utils_1 = require("../../tools/esbuild/utils");
|
|
14
|
+
const color_1 = require("../../utils/color");
|
|
13
15
|
const purge_cache_1 = require("../../utils/purge-cache");
|
|
14
16
|
const version_1 = require("../../utils/version");
|
|
15
17
|
const build_action_1 = require("./build-action");
|
|
@@ -57,11 +59,25 @@ context, infrastructureSettings, extensions) {
|
|
|
57
59
|
context.addTeardown(() => controller.abort('builder-teardown'));
|
|
58
60
|
}
|
|
59
61
|
yield* (0, build_action_1.runEsBuildBuildAction)(async (rebuildState) => {
|
|
62
|
+
const { prerenderOptions, outputOptions, jsonLogs } = normalizedOptions;
|
|
60
63
|
const startTime = process.hrtime.bigint();
|
|
61
64
|
const result = await (0, execute_build_1.executeBuild)(normalizedOptions, context, rebuildState);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
if (!jsonLogs) {
|
|
66
|
+
if (prerenderOptions) {
|
|
67
|
+
const prerenderedRoutesLength = result.prerenderedRoutes.length;
|
|
68
|
+
let prerenderMsg = `Prerendered ${prerenderedRoutesLength} static route`;
|
|
69
|
+
prerenderMsg += prerenderedRoutesLength !== 1 ? 's.' : '.';
|
|
70
|
+
logger.info(color_1.colors.magenta(prerenderMsg));
|
|
71
|
+
}
|
|
72
|
+
const buildTime = Number(process.hrtime.bigint() - startTime) / 10 ** 9;
|
|
73
|
+
const hasError = result.errors.length > 0;
|
|
74
|
+
if (writeToFileSystem && !hasError) {
|
|
75
|
+
logger.info(`Output location: ${outputOptions.base}\n`);
|
|
76
|
+
}
|
|
77
|
+
logger.info(`Application bundle generation ${hasError ? 'failed' : 'complete'}. [${buildTime.toFixed(3)} seconds]`);
|
|
78
|
+
}
|
|
79
|
+
// Log all diagnostic (error/warning) messages
|
|
80
|
+
await (0, utils_1.logMessages)(logger, result, normalizedOptions);
|
|
65
81
|
return result;
|
|
66
82
|
}, {
|
|
67
83
|
watch: normalizedOptions.watch,
|
|
@@ -127,6 +127,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
127
127
|
file: string;
|
|
128
128
|
package: string;
|
|
129
129
|
} | undefined;
|
|
130
|
+
postcssConfiguration: import("../../utils/postcss-configuration").PostcssConfiguration | undefined;
|
|
130
131
|
i18nOptions: I18nOptions & {
|
|
131
132
|
duplicateTranslationBehavior?: I18NTranslation | undefined;
|
|
132
133
|
missingTranslationBehavior?: I18NTranslation | undefined;
|
|
@@ -136,5 +137,7 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
|
|
|
136
137
|
publicPath: string | undefined;
|
|
137
138
|
plugins: Plugin[] | undefined;
|
|
138
139
|
loaderExtensions: Record<string, "binary" | "file" | "text"> | undefined;
|
|
140
|
+
jsonLogs: boolean;
|
|
141
|
+
colors: boolean;
|
|
139
142
|
}>;
|
|
140
143
|
export {};
|
|
@@ -17,9 +17,12 @@ const node_module_1 = require("node:module");
|
|
|
17
17
|
const node_path_1 = __importDefault(require("node:path"));
|
|
18
18
|
const helpers_1 = require("../../tools/webpack/utils/helpers");
|
|
19
19
|
const utils_1 = require("../../utils");
|
|
20
|
+
const color_1 = require("../../utils/color");
|
|
21
|
+
const environment_options_1 = require("../../utils/environment-options");
|
|
20
22
|
const i18n_options_1 = require("../../utils/i18n-options");
|
|
21
23
|
const normalize_cache_1 = require("../../utils/normalize-cache");
|
|
22
24
|
const package_chunk_sort_1 = require("../../utils/package-chunk-sort");
|
|
25
|
+
const postcss_configuration_1 = require("../../utils/postcss-configuration");
|
|
23
26
|
const tailwind_1 = require("../../utils/tailwind");
|
|
24
27
|
const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
|
|
25
28
|
const schema_1 = require("./schema");
|
|
@@ -108,6 +111,11 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
108
111
|
loaderExtensions[extension] = value;
|
|
109
112
|
}
|
|
110
113
|
}
|
|
114
|
+
const postcssConfiguration = await (0, postcss_configuration_1.loadPostcssConfiguration)(workspaceRoot, projectRoot);
|
|
115
|
+
// Skip tailwind configuration if postcss is customized
|
|
116
|
+
const tailwindConfiguration = postcssConfiguration
|
|
117
|
+
? undefined
|
|
118
|
+
: await getTailwindConfig(workspaceRoot, projectRoot, context);
|
|
111
119
|
const globalStyles = [];
|
|
112
120
|
if (options.styles?.length) {
|
|
113
121
|
const { entryPoints: stylesheetEntrypoints, noInjectNames } = (0, helpers_1.normalizeGlobalStyles)(options.styles || []);
|
|
@@ -212,13 +220,16 @@ async function normalizeOptions(context, projectName, options, extensions) {
|
|
|
212
220
|
globalScripts,
|
|
213
221
|
serviceWorker: typeof serviceWorker === 'string' ? node_path_1.default.join(workspaceRoot, serviceWorker) : undefined,
|
|
214
222
|
indexHtmlOptions,
|
|
215
|
-
tailwindConfiguration
|
|
223
|
+
tailwindConfiguration,
|
|
224
|
+
postcssConfiguration,
|
|
216
225
|
i18nOptions,
|
|
217
226
|
namedChunks,
|
|
218
227
|
budgets: budgets?.length ? budgets : undefined,
|
|
219
228
|
publicPath: deployUrl ? deployUrl : undefined,
|
|
220
229
|
plugins: extensions?.codePlugins?.length ? extensions?.codePlugins : undefined,
|
|
221
230
|
loaderExtensions,
|
|
231
|
+
jsonLogs: environment_options_1.useJSONBuildLogs,
|
|
232
|
+
colors: color_1.colors.enabled,
|
|
222
233
|
};
|
|
223
234
|
}
|
|
224
235
|
exports.normalizeOptions = normalizeOptions;
|
|
@@ -59,11 +59,11 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
|
|
|
59
59
|
// Disable external deps for server bundles.
|
|
60
60
|
// This is because it breaks Vite 'optimizeDeps' for SSR.
|
|
61
61
|
externalPackages: false,
|
|
62
|
-
}, nodeTargets, codeBundleCache)
|
|
62
|
+
}, nodeTargets, codeBundleCache)));
|
|
63
63
|
// Server polyfills code
|
|
64
64
|
const serverPolyfillBundleOptions = (0, application_code_bundle_1.createServerPolyfillBundleOptions)(options, nodeTargets, codeBundleCache);
|
|
65
65
|
if (serverPolyfillBundleOptions) {
|
|
66
|
-
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, serverPolyfillBundleOptions
|
|
66
|
+
bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, !!options.watch, serverPolyfillBundleOptions));
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
return bundlerContexts;
|
|
@@ -29,8 +29,9 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
29
29
|
const projectMetadata = await context.getProjectMetadata(projectName);
|
|
30
30
|
const projectRoot = node_path_1.default.join(workspaceRoot, projectMetadata.root ?? '');
|
|
31
31
|
const cacheOptions = (0, normalize_cache_1.normalizeCacheOptions)(projectMetadata, workspaceRoot);
|
|
32
|
-
//
|
|
33
|
-
const
|
|
32
|
+
// Target specifier defaults to the current project's build target using a development configuration
|
|
33
|
+
const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? `::development`;
|
|
34
|
+
const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
|
|
34
35
|
// Initial options to keep
|
|
35
36
|
const { host, port, poll, open, verbose, watch, allowedHosts, disableHostCheck, liveReload, hmr, headers, proxyConfig, servePath, publicHost, ssl, sslCert, sslKey, forceEsbuild, } = options;
|
|
36
37
|
// Return all the normalized options
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"buildTarget": {
|
|
14
14
|
"type": "string",
|
|
15
15
|
"description": "A build builder target to serve in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.",
|
|
16
|
-
"pattern": "^[^:\\s]
|
|
16
|
+
"pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$"
|
|
17
17
|
},
|
|
18
18
|
"port": {
|
|
19
19
|
"type": "number",
|
|
@@ -30,8 +30,9 @@ async function normalizeOptions(context, projectName, options) {
|
|
|
30
30
|
const workspaceRoot = context.workspaceRoot;
|
|
31
31
|
const projectMetadata = await context.getProjectMetadata(projectName);
|
|
32
32
|
const projectRoot = node_path_1.default.join(workspaceRoot, projectMetadata.root ?? '');
|
|
33
|
-
//
|
|
34
|
-
const
|
|
33
|
+
// Target specifier defaults to the current project's build target with no specified configuration
|
|
34
|
+
const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? ':';
|
|
35
|
+
const buildTarget = (0, architect_1.targetFromTargetString)(buildTargetSpecifier, projectName, 'build');
|
|
35
36
|
const i18nOptions = (0, i18n_options_1.createI18nOptions)(projectMetadata);
|
|
36
37
|
// Normalize xliff format extensions
|
|
37
38
|
let format = options.format;
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"buildTarget": {
|
|
14
14
|
"type": "string",
|
|
15
15
|
"description": "A builder target to extract i18n messages in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.",
|
|
16
|
-
"pattern": "^[^:\\s]
|
|
16
|
+
"pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$"
|
|
17
17
|
},
|
|
18
18
|
"format": {
|
|
19
19
|
"type": "string",
|
|
@@ -31,15 +31,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
31
31
|
};
|
|
32
32
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
33
|
const architect_1 = require("@angular-devkit/architect");
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
34
|
+
const node_child_process_1 = require("node:child_process");
|
|
35
|
+
const fs = __importStar(require("node:fs/promises"));
|
|
36
|
+
const path = __importStar(require("node:path"));
|
|
37
|
+
const node_util_1 = require("node:util");
|
|
37
38
|
const color_1 = require("../../utils/color");
|
|
38
39
|
const test_files_1 = require("../../utils/test-files");
|
|
39
40
|
const application_1 = require("../application");
|
|
40
41
|
const schema_1 = require("../browser-esbuild/schema");
|
|
41
42
|
const options_1 = require("./options");
|
|
42
|
-
const execFile = (0,
|
|
43
|
+
const execFile = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
43
44
|
/** Main execution function for the Jest builder. */
|
|
44
45
|
exports.default = (0, architect_1.createBuilder)(async (schema, context) => {
|
|
45
46
|
context.logger.warn('NOTE: The Jest builder is currently EXPERIMENTAL and not ready for production use.');
|
|
@@ -65,8 +66,21 @@ exports.default = (0, architect_1.createBuilder)(async (schema, context) => {
|
|
|
65
66
|
error: '`jest-environment-jsdom` is not installed. Install it with `npm install jest-environment-jsdom --save-dev`.',
|
|
66
67
|
};
|
|
67
68
|
}
|
|
69
|
+
const [testFiles, customConfig] = await Promise.all([
|
|
70
|
+
(0, test_files_1.findTestFiles)(options.include, options.exclude, context.workspaceRoot),
|
|
71
|
+
findCustomJestConfig(context.workspaceRoot),
|
|
72
|
+
]);
|
|
73
|
+
// Warn if a custom Jest configuration is found. We won't use it, so if a developer is trying to use a custom config, this hopefully
|
|
74
|
+
// makes a better experience than silently ignoring the configuration.
|
|
75
|
+
// Ideally, this would be a hard error. However a Jest config could exist for testing other files in the workspace outside of Angular
|
|
76
|
+
// CLI, so we likely can't produce a hard error in this situation without an opt-out.
|
|
77
|
+
if (customConfig) {
|
|
78
|
+
context.logger.warn('A custom Jest config was found, but this is not supported by `@angular-devkit/build-angular:jest` and will be' +
|
|
79
|
+
` ignored: ${customConfig}. This is an experiment to see if completely abstracting away Jest's configuration is viable. Please` +
|
|
80
|
+
` consider if your use case can be met without directly modifying the Jest config. If this is a major obstacle for your use` +
|
|
81
|
+
` case, please post it in this issue so we can collect feedback and evaluate: https://github.com/angular/angular-cli/issues/25434.`);
|
|
82
|
+
}
|
|
68
83
|
// Build all the test files.
|
|
69
|
-
const testFiles = await (0, test_files_1.findTestFiles)(options.include, options.exclude, context.workspaceRoot);
|
|
70
84
|
const jestGlobal = path.join(__dirname, 'jest-global.mjs');
|
|
71
85
|
const initTestBed = path.join(__dirname, 'init-test-bed.mjs');
|
|
72
86
|
const buildResult = await build(context, {
|
|
@@ -94,6 +108,7 @@ exports.default = (0, architect_1.createBuilder)(async (schema, context) => {
|
|
|
94
108
|
'--experimental-vm-modules',
|
|
95
109
|
jest,
|
|
96
110
|
`--rootDir="${path.join(testOut, 'browser')}"`,
|
|
111
|
+
`--config=${path.join(__dirname, 'jest.config.mjs')}`,
|
|
97
112
|
'--testEnvironment=jsdom',
|
|
98
113
|
// TODO(dgp1130): Enable cache once we have a mechanism for properly clearing / disabling it.
|
|
99
114
|
'--no-cache',
|
|
@@ -158,3 +173,27 @@ function resolveModule(module) {
|
|
|
158
173
|
return undefined;
|
|
159
174
|
}
|
|
160
175
|
}
|
|
176
|
+
/** Returns whether or not the provided directory includes a Jest configuration file. */
|
|
177
|
+
async function findCustomJestConfig(dir) {
|
|
178
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
179
|
+
// Jest supports many file extensions (`js`, `ts`, `cjs`, `cts`, `json`, etc.) Just look
|
|
180
|
+
// for anything with that prefix.
|
|
181
|
+
const config = entries.find((entry) => entry.isFile() && entry.name.startsWith('jest.config.'));
|
|
182
|
+
if (config) {
|
|
183
|
+
return path.join(dir, config.name);
|
|
184
|
+
}
|
|
185
|
+
// Jest also supports a `jest` key in `package.json`, look for a config there.
|
|
186
|
+
const packageJsonPath = path.join(dir, 'package.json');
|
|
187
|
+
let packageJson;
|
|
188
|
+
try {
|
|
189
|
+
packageJson = await fs.readFile(packageJsonPath, 'utf8');
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return undefined; // No package.json, therefore no Jest configuration in it.
|
|
193
|
+
}
|
|
194
|
+
const json = JSON.parse(packageJson);
|
|
195
|
+
if ('jest' in json) {
|
|
196
|
+
return packageJsonPath;
|
|
197
|
+
}
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Empty config file, everything is specified via CLI options right now.
|
|
10
|
+
// This file is used just so Jest doesn't accidentally inherit a custom user-specified Jest config.
|
|
11
|
+
export default {};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference path="../../../../../../../../../../packages/angular_devkit/build_angular/src/babel-bazel.d.ts" />
|
|
9
9
|
/// <reference types="@angular/compiler-cli/private/babel" />
|
|
10
|
-
import { PluginObj } from '@babel/core';
|
|
10
|
+
import type { PluginObj } from '@babel/core';
|
|
11
11
|
/**
|
|
12
12
|
* Provides one or more keywords that if found within the content of a source file indicate
|
|
13
13
|
* that this plugin should be used with a source file.
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.getKeywords = void 0;
|
|
11
|
-
const core_1 = require("@babel/core");
|
|
12
11
|
/**
|
|
13
12
|
* The name of the Angular class metadata function created by the Angular compiler.
|
|
14
13
|
*/
|
|
@@ -28,9 +27,18 @@ const SET_CLASS_DEBUG_INFO_NAME = 'ɵsetClassDebugInfo';
|
|
|
28
27
|
* @returns An a string iterable containing one or more keywords.
|
|
29
28
|
*/
|
|
30
29
|
function getKeywords() {
|
|
31
|
-
return
|
|
30
|
+
return Object.keys(angularMetadataFunctions);
|
|
32
31
|
}
|
|
33
32
|
exports.getKeywords = getKeywords;
|
|
33
|
+
/**
|
|
34
|
+
* An object map of function names and related value checks for discovery of Angular generated
|
|
35
|
+
* metadata calls.
|
|
36
|
+
*/
|
|
37
|
+
const angularMetadataFunctions = {
|
|
38
|
+
[SET_CLASS_METADATA_NAME]: isSetClassMetadataCall,
|
|
39
|
+
[SET_CLASS_METADATA_ASYNC_NAME]: isSetClassMetadataAsyncCall,
|
|
40
|
+
[SET_CLASS_DEBUG_INFO_NAME]: isSetClassDebugInfoCall,
|
|
41
|
+
};
|
|
34
42
|
/**
|
|
35
43
|
* A babel plugin factory function for eliding the Angular class metadata function (`ɵsetClassMetadata`).
|
|
36
44
|
*
|
|
@@ -40,20 +48,23 @@ function default_1() {
|
|
|
40
48
|
return {
|
|
41
49
|
visitor: {
|
|
42
50
|
CallExpression(path) {
|
|
43
|
-
const callee = path.
|
|
44
|
-
const callArguments = path.node.arguments;
|
|
51
|
+
const callee = path.get('callee');
|
|
45
52
|
// The function being called must be the metadata function name
|
|
46
53
|
let calleeName;
|
|
47
|
-
if (
|
|
48
|
-
|
|
54
|
+
if (callee.isMemberExpression()) {
|
|
55
|
+
const calleeProperty = callee.get('property');
|
|
56
|
+
if (calleeProperty.isIdentifier()) {
|
|
57
|
+
calleeName = calleeProperty.node.name;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (callee.isIdentifier()) {
|
|
61
|
+
calleeName = callee.node.name;
|
|
49
62
|
}
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
if (!calleeName) {
|
|
64
|
+
return;
|
|
52
65
|
}
|
|
53
|
-
if (calleeName
|
|
54
|
-
(
|
|
55
|
-
isRemoveClassmetadataAsyncCall(calleeName, callArguments) ||
|
|
56
|
-
isSetClassDebugInfoCall(calleeName, callArguments))) {
|
|
66
|
+
if (Object.hasOwn(angularMetadataFunctions, calleeName) &&
|
|
67
|
+
angularMetadataFunctions[calleeName](path.get('arguments'))) {
|
|
57
68
|
// The metadata function is always emitted inside a function expression
|
|
58
69
|
const parent = path.getFunctionParent();
|
|
59
70
|
if (parent && (parent.isFunctionExpression() || parent.isArrowFunctionExpression())) {
|
|
@@ -68,35 +79,32 @@ function default_1() {
|
|
|
68
79
|
}
|
|
69
80
|
exports.default = default_1;
|
|
70
81
|
/** Determines if a function call is a call to `setClassMetadata`. */
|
|
71
|
-
function
|
|
82
|
+
function isSetClassMetadataCall(callArguments) {
|
|
72
83
|
// `setClassMetadata` calls have to meet the following criteria:
|
|
73
84
|
// * First must be an identifier
|
|
74
85
|
// * Second must be an array literal
|
|
75
|
-
return (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
core_1.types.isArrayExpression(args[1]));
|
|
86
|
+
return (callArguments.length === 4 &&
|
|
87
|
+
callArguments[0].isIdentifier() &&
|
|
88
|
+
callArguments[1].isArrayExpression());
|
|
79
89
|
}
|
|
80
90
|
/** Determines if a function call is a call to `setClassMetadataAsync`. */
|
|
81
|
-
function
|
|
91
|
+
function isSetClassMetadataAsyncCall(callArguments) {
|
|
82
92
|
// `setClassMetadataAsync` calls have to meet the following criteria:
|
|
83
93
|
// * First argument must be an identifier.
|
|
84
94
|
// * Second argument must be an inline function.
|
|
85
95
|
// * Third argument must be an inline function.
|
|
86
|
-
return (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
isInlineFunction(
|
|
90
|
-
isInlineFunction(args[2]));
|
|
96
|
+
return (callArguments.length === 3 &&
|
|
97
|
+
callArguments[0].isIdentifier() &&
|
|
98
|
+
isInlineFunction(callArguments[1]) &&
|
|
99
|
+
isInlineFunction(callArguments[2]));
|
|
91
100
|
}
|
|
92
101
|
/** Determines if a function call is a call to `setClassDebugInfo`. */
|
|
93
|
-
function isSetClassDebugInfoCall(
|
|
94
|
-
return (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
core_1.types.isObjectExpression(args[1]));
|
|
102
|
+
function isSetClassDebugInfoCall(callArguments) {
|
|
103
|
+
return (callArguments.length === 2 &&
|
|
104
|
+
callArguments[0].isIdentifier() &&
|
|
105
|
+
callArguments[1].isObjectExpression());
|
|
98
106
|
}
|
|
99
107
|
/** Determines if a node is an inline function expression. */
|
|
100
|
-
function isInlineFunction(
|
|
101
|
-
return
|
|
108
|
+
function isInlineFunction(path) {
|
|
109
|
+
return path.isFunctionExpression() || path.isArrowFunctionExpression();
|
|
102
110
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference path="../../../../../../../../../../packages/angular_devkit/build_angular/src/babel-bazel.d.ts" />
|
|
9
9
|
/// <reference types="@angular/compiler-cli/private/babel" />
|
|
10
|
-
import { PluginObj } from '@babel/core';
|
|
10
|
+
import type { PluginObj } from '@babel/core';
|
|
11
11
|
/**
|
|
12
12
|
* A babel plugin factory function for adding the PURE annotation to top-level new and call expressions.
|
|
13
13
|
*
|
|
@@ -33,7 +33,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
33
33
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
34
34
|
};
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const core_1 = require("@babel/core");
|
|
37
36
|
const helper_annotate_as_pure_1 = __importDefault(require("@babel/helper-annotate-as-pure"));
|
|
38
37
|
const tslib = __importStar(require("tslib"));
|
|
39
38
|
/**
|
|
@@ -67,14 +66,14 @@ function default_1() {
|
|
|
67
66
|
if (path.getFunctionParent()) {
|
|
68
67
|
return;
|
|
69
68
|
}
|
|
70
|
-
const callee = path.
|
|
71
|
-
if ((
|
|
69
|
+
const callee = path.get('callee');
|
|
70
|
+
if ((callee.isFunctionExpression() || callee.isArrowFunctionExpression()) &&
|
|
72
71
|
path.node.arguments.length !== 0) {
|
|
73
72
|
return;
|
|
74
73
|
}
|
|
75
74
|
// Do not annotate TypeScript helpers emitted by the TypeScript compiler.
|
|
76
75
|
// TypeScript helpers are intended to cause side effects.
|
|
77
|
-
if (
|
|
76
|
+
if (callee.isIdentifier() && isTslibHelperName(callee.node.name)) {
|
|
78
77
|
return;
|
|
79
78
|
}
|
|
80
79
|
(0, helper_annotate_as_pure_1.default)(path);
|