@angular-devkit/build-angular 17.1.0-next.1 → 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 +16 -16
- package/src/builders/application/build-action.js +18 -11
- 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 +11 -4
- 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/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/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.js +56 -121
- 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/tools/esbuild/normalize-path.d.ts +0 -8
- package/src/tools/esbuild/normalize-path.js +0 -22
package/package.json
CHANGED
|
@@ -1,37 +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
|
-
"chokidar": "3.5.3",
|
|
31
30
|
"copy-webpack-plugin": "11.0.0",
|
|
32
31
|
"critters": "0.0.20",
|
|
33
32
|
"css-loader": "6.8.1",
|
|
34
|
-
"esbuild-wasm": "0.19.
|
|
33
|
+
"esbuild-wasm": "0.19.9",
|
|
35
34
|
"fast-glob": "3.3.2",
|
|
36
35
|
"https-proxy-agent": "7.0.2",
|
|
37
36
|
"http-proxy-middleware": "2.0.6",
|
|
@@ -49,7 +48,7 @@
|
|
|
49
48
|
"ora": "5.4.1",
|
|
50
49
|
"parse5-html-rewriting-stream": "7.0.0",
|
|
51
50
|
"picomatch": "3.0.1",
|
|
52
|
-
"piscina": "4.2.
|
|
51
|
+
"piscina": "4.2.1",
|
|
53
52
|
"postcss": "8.4.32",
|
|
54
53
|
"postcss-loader": "7.3.3",
|
|
55
54
|
"resolve-url-loader": "5.0.0",
|
|
@@ -59,12 +58,13 @@
|
|
|
59
58
|
"semver": "7.5.4",
|
|
60
59
|
"source-map-loader": "4.0.1",
|
|
61
60
|
"source-map-support": "0.5.21",
|
|
62
|
-
"terser": "5.
|
|
61
|
+
"terser": "5.26.0",
|
|
63
62
|
"text-table": "0.2.0",
|
|
64
63
|
"tree-kill": "1.2.2",
|
|
65
64
|
"tslib": "2.6.2",
|
|
66
65
|
"undici": "6.0.1",
|
|
67
|
-
"vite": "5.0.
|
|
66
|
+
"vite": "5.0.7",
|
|
67
|
+
"watchpack": "2.4.0",
|
|
68
68
|
"webpack": "5.89.0",
|
|
69
69
|
"webpack-dev-middleware": "6.1.1",
|
|
70
70
|
"webpack-dev-server": "4.15.1",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"webpack-subresource-integrity": "5.1.0"
|
|
73
73
|
},
|
|
74
74
|
"optionalDependencies": {
|
|
75
|
-
"esbuild": "0.19.
|
|
75
|
+
"esbuild": "0.19.9"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
78
|
"@angular/compiler-cli": "^17.0.0 || ^17.1.0-next.0",
|
|
@@ -34,6 +34,7 @@ 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");
|
|
@@ -42,7 +43,7 @@ const environment_options_1 = require("../../utils/environment-options");
|
|
|
42
43
|
async function* runEsBuildBuildAction(action, options) {
|
|
43
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,21 +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
83
|
followSymlinks: preserveSymlinks,
|
|
71
|
-
ignored
|
|
72
|
-
// Ignore the output and cache paths to avoid infinite rebuild cycles
|
|
73
|
-
outputPath,
|
|
74
|
-
cacheOptions.basePath,
|
|
75
|
-
// Ignore all node modules directories to avoid excessive file watchers.
|
|
76
|
-
// Package changes are handled below by watching manifest and lock files.
|
|
77
|
-
'**/node_modules/**',
|
|
78
|
-
`${workspaceRoot.replace(/\\/g, '/')}/**/.*/**`,
|
|
79
|
-
],
|
|
84
|
+
ignored,
|
|
80
85
|
});
|
|
81
86
|
// Setup abort support
|
|
82
87
|
options.signal?.addEventListener('abort', () => void watcher?.close());
|
|
@@ -97,7 +102,9 @@ async function* runEsBuildBuildAction(action, options) {
|
|
|
97
102
|
'.pnp.cjs',
|
|
98
103
|
'.pnp.data.json',
|
|
99
104
|
];
|
|
100
|
-
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)));
|
|
101
108
|
// Watch locations provided by the initial build result
|
|
102
109
|
watcher.add(result.watchFiles);
|
|
103
110
|
}
|
|
@@ -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.
|
|
@@ -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",
|
|
@@ -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;
|
|
@@ -6,13 +6,11 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
-
};
|
|
12
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
10
|
exports.setupJitPluginCallbacks = void 0;
|
|
14
11
|
const promises_1 = require("node:fs/promises");
|
|
15
|
-
const node_path_1 =
|
|
12
|
+
const node_path_1 = require("node:path");
|
|
13
|
+
const load_result_cache_1 = require("../load-result-cache");
|
|
16
14
|
const uri_1 = require("./uri");
|
|
17
15
|
/**
|
|
18
16
|
* Loads/extracts the contents from a load callback Angular JIT entry.
|
|
@@ -27,7 +25,7 @@ const uri_1 = require("./uri");
|
|
|
27
25
|
*/
|
|
28
26
|
async function loadEntry(entry, root, skipRead) {
|
|
29
27
|
if (entry.startsWith('file:')) {
|
|
30
|
-
const specifier = node_path_1.
|
|
28
|
+
const specifier = (0, node_path_1.join)(root, entry.slice(5));
|
|
31
29
|
return {
|
|
32
30
|
path: specifier,
|
|
33
31
|
contents: skipRead ? undefined : await (0, promises_1.readFile)(specifier, 'utf-8'),
|
|
@@ -36,7 +34,7 @@ async function loadEntry(entry, root, skipRead) {
|
|
|
36
34
|
else if (entry.startsWith('inline:')) {
|
|
37
35
|
const [importer, data] = entry.slice(7).split(';', 2);
|
|
38
36
|
return {
|
|
39
|
-
path: node_path_1.
|
|
37
|
+
path: (0, node_path_1.join)(root, importer),
|
|
40
38
|
contents: Buffer.from(data, 'base64').toString(),
|
|
41
39
|
};
|
|
42
40
|
}
|
|
@@ -53,7 +51,7 @@ async function loadEntry(entry, root, skipRead) {
|
|
|
53
51
|
* @param styleOptions The options to use when bundling stylesheets.
|
|
54
52
|
* @param additionalResultFiles A Map where stylesheet resources will be added.
|
|
55
53
|
*/
|
|
56
|
-
function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles, inlineStyleLanguage) {
|
|
54
|
+
function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles, inlineStyleLanguage, loadCache) {
|
|
57
55
|
const root = build.initialOptions.absWorkingDir ?? '';
|
|
58
56
|
// Add a resolve callback to capture and parse any JIT URIs that were added by the
|
|
59
57
|
// JIT resource TypeScript transformer.
|
|
@@ -68,13 +66,13 @@ function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles
|
|
|
68
66
|
return {
|
|
69
67
|
// Use a relative path to prevent fully resolved paths in the metafile (JSON stats file).
|
|
70
68
|
// This is only necessary for custom namespaces. esbuild will handle the file namespace.
|
|
71
|
-
path: 'file:' + node_path_1.
|
|
69
|
+
path: 'file:' + (0, node_path_1.relative)(root, (0, node_path_1.join)((0, node_path_1.dirname)(args.importer), specifier)),
|
|
72
70
|
namespace,
|
|
73
71
|
};
|
|
74
72
|
}
|
|
75
73
|
else {
|
|
76
74
|
// Inline data may need the importer to resolve imports/references within the content
|
|
77
|
-
const importer = node_path_1.
|
|
75
|
+
const importer = (0, node_path_1.relative)(root, args.importer);
|
|
78
76
|
return {
|
|
79
77
|
path: `inline:${importer};${specifier}`,
|
|
80
78
|
namespace,
|
|
@@ -82,7 +80,7 @@ function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles
|
|
|
82
80
|
}
|
|
83
81
|
});
|
|
84
82
|
// Add a load callback to handle Component stylesheets (both inline and external)
|
|
85
|
-
build.onLoad({ filter: /./, namespace: uri_1.JIT_STYLE_NAMESPACE }, async (args) => {
|
|
83
|
+
build.onLoad({ filter: /./, namespace: uri_1.JIT_STYLE_NAMESPACE }, (0, load_result_cache_1.createCachedLoad)(loadCache, async (args) => {
|
|
86
84
|
// skipRead is used here because the stylesheet bundling will read a file stylesheet
|
|
87
85
|
// directly either via a preprocessor or esbuild itself.
|
|
88
86
|
const entry = await loadEntry(args.path, root, true /* skipRead */);
|
|
@@ -94,24 +92,26 @@ function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles
|
|
|
94
92
|
else {
|
|
95
93
|
stylesheetResult = await stylesheetBundler.bundleInline(entry.contents, entry.path, inlineStyleLanguage);
|
|
96
94
|
}
|
|
97
|
-
const { contents, resourceFiles, errors, warnings, metafile } = stylesheetResult;
|
|
95
|
+
const { contents, resourceFiles, errors, warnings, metafile, referencedFiles } = stylesheetResult;
|
|
98
96
|
additionalResultFiles.set(entry.path, { outputFiles: resourceFiles, metafile });
|
|
99
97
|
return {
|
|
100
98
|
errors,
|
|
101
99
|
warnings,
|
|
102
100
|
contents,
|
|
103
101
|
loader: 'text',
|
|
102
|
+
watchFiles: referencedFiles && [...referencedFiles],
|
|
104
103
|
};
|
|
105
|
-
});
|
|
104
|
+
}));
|
|
106
105
|
// Add a load callback to handle Component templates
|
|
107
106
|
// NOTE: While this callback supports both inline and external templates, the transformer
|
|
108
107
|
// currently only supports generating URIs for external templates.
|
|
109
|
-
build.onLoad({ filter: /./, namespace: uri_1.JIT_TEMPLATE_NAMESPACE }, async (args) => {
|
|
110
|
-
const { contents } = await loadEntry(args.path, root);
|
|
108
|
+
build.onLoad({ filter: /./, namespace: uri_1.JIT_TEMPLATE_NAMESPACE }, (0, load_result_cache_1.createCachedLoad)(loadCache, async (args) => {
|
|
109
|
+
const { contents, path } = await loadEntry(args.path, root);
|
|
111
110
|
return {
|
|
112
111
|
contents,
|
|
113
112
|
loader: 'text',
|
|
113
|
+
watchFiles: [path],
|
|
114
114
|
};
|
|
115
|
-
});
|
|
115
|
+
}));
|
|
116
116
|
}
|
|
117
117
|
exports.setupJitPluginCallbacks = setupJitPluginCallbacks;
|
|
@@ -52,7 +52,6 @@ class SourceFileCache extends Map {
|
|
|
52
52
|
}
|
|
53
53
|
for (let file of files) {
|
|
54
54
|
file = path.normalize(file);
|
|
55
|
-
this.typeScriptFileCache.delete(file);
|
|
56
55
|
this.loadResultCache.invalidate(file);
|
|
57
56
|
// Normalize separators to allow matching TypeScript Host paths
|
|
58
57
|
if (USING_WINDOWS) {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.createCompilerPluginOptions = void 0;
|
|
11
11
|
function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
12
|
-
const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, tailwindConfiguration, } = options;
|
|
12
|
+
const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, publicPath, } = options;
|
|
13
13
|
return {
|
|
14
14
|
// JS/TS options
|
|
15
15
|
pluginOptions: {
|
|
@@ -26,6 +26,7 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
|
26
26
|
// Component stylesheet options
|
|
27
27
|
styleOptions: {
|
|
28
28
|
workspaceRoot,
|
|
29
|
+
inlineFonts: !!optimizationOptions.fonts.inline,
|
|
29
30
|
optimization: !!optimizationOptions.styles.minify,
|
|
30
31
|
sourcemap:
|
|
31
32
|
// Hidden component stylesheet sourcemaps are inaccessible which is effectively
|
|
@@ -39,7 +40,8 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
|
39
40
|
inlineStyleLanguage,
|
|
40
41
|
preserveSymlinks,
|
|
41
42
|
tailwindConfiguration,
|
|
42
|
-
|
|
43
|
+
cacheOptions,
|
|
44
|
+
publicPath,
|
|
43
45
|
},
|
|
44
46
|
};
|
|
45
47
|
}
|
|
@@ -15,7 +15,7 @@ const node_assert_1 = __importDefault(require("node:assert"));
|
|
|
15
15
|
const bundle_options_1 = require("./stylesheets/bundle-options");
|
|
16
16
|
const virtual_module_plugin_1 = require("./virtual-module-plugin");
|
|
17
17
|
function createGlobalStylesBundleOptions(options, target, initial) {
|
|
18
|
-
const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, tailwindConfiguration, } = options;
|
|
18
|
+
const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, tailwindConfiguration, cacheOptions, publicPath, } = options;
|
|
19
19
|
const namespace = 'angular:styles/global';
|
|
20
20
|
const entryPoints = {};
|
|
21
21
|
let found = false;
|
|
@@ -33,6 +33,7 @@ function createGlobalStylesBundleOptions(options, target, initial) {
|
|
|
33
33
|
const buildOptions = (0, bundle_options_1.createStylesheetBundleOptions)({
|
|
34
34
|
workspaceRoot,
|
|
35
35
|
optimization: !!optimizationOptions.styles.minify,
|
|
36
|
+
inlineFonts: !!optimizationOptions.fonts.inline,
|
|
36
37
|
sourcemap: !!sourcemapOptions.styles,
|
|
37
38
|
preserveSymlinks,
|
|
38
39
|
target,
|
|
@@ -45,7 +46,8 @@ function createGlobalStylesBundleOptions(options, target, initial) {
|
|
|
45
46
|
},
|
|
46
47
|
includePaths: stylePreprocessorOptions?.includePaths,
|
|
47
48
|
tailwindConfiguration,
|
|
48
|
-
|
|
49
|
+
cacheOptions,
|
|
50
|
+
publicPath,
|
|
49
51
|
}, loadCache);
|
|
50
52
|
// Keep special CSS comments `/*! comment */` in place when `removeSpecialComments` is disabled.
|
|
51
53
|
// These comments are special for a number of CSS tools such as Critters and PurgeCSS.
|
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import type { BuildOptions } from 'esbuild';
|
|
9
|
+
import { NormalizedCachedOptions } from '../../../utils/normalize-cache';
|
|
9
10
|
import { LoadResultCache } from '../load-result-cache';
|
|
10
11
|
export interface BundleStylesheetOptions {
|
|
11
12
|
workspaceRoot: string;
|
|
12
13
|
optimization: boolean;
|
|
14
|
+
inlineFonts: boolean;
|
|
13
15
|
preserveSymlinks?: boolean;
|
|
14
16
|
sourcemap: boolean | 'external' | 'inline';
|
|
15
17
|
outputNames: {
|
|
@@ -24,6 +26,7 @@ export interface BundleStylesheetOptions {
|
|
|
24
26
|
package: string;
|
|
25
27
|
};
|
|
26
28
|
publicPath?: string;
|
|
29
|
+
cacheOptions: NormalizedCachedOptions;
|
|
27
30
|
}
|
|
28
31
|
export declare function createStylesheetBundleOptions(options: BundleStylesheetOptions, cache?: LoadResultCache, inlineComponentData?: Record<string, string>): BuildOptions & {
|
|
29
32
|
plugins: NonNullable<BuildOptions['plugins']>;
|
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
13
|
exports.createStylesheetBundleOptions = void 0;
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
|
+
const css_inline_fonts_plugin_1 = require("./css-inline-fonts-plugin");
|
|
15
16
|
const css_language_1 = require("./css-language");
|
|
16
17
|
const css_resource_plugin_1 = require("./css-resource-plugin");
|
|
17
18
|
const less_language_1 = require("./less-language");
|
|
@@ -26,6 +27,15 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
|
|
|
26
27
|
inlineComponentData,
|
|
27
28
|
tailwindConfiguration: options.tailwindConfiguration,
|
|
28
29
|
}, cache);
|
|
30
|
+
const plugins = [
|
|
31
|
+
pluginFactory.create(sass_language_1.SassStylesheetLanguage),
|
|
32
|
+
pluginFactory.create(less_language_1.LessStylesheetLanguage),
|
|
33
|
+
pluginFactory.create(css_language_1.CssStylesheetLanguage),
|
|
34
|
+
(0, css_resource_plugin_1.createCssResourcePlugin)(cache),
|
|
35
|
+
];
|
|
36
|
+
if (options.inlineFonts) {
|
|
37
|
+
plugins.push((0, css_inline_fonts_plugin_1.createCssInlineFontsPlugin)({ cache, cacheOptions: options.cacheOptions }));
|
|
38
|
+
}
|
|
29
39
|
return {
|
|
30
40
|
absWorkingDir: options.workspaceRoot,
|
|
31
41
|
bundle: true,
|
|
@@ -44,12 +54,7 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
|
|
|
44
54
|
publicPath: options.publicPath,
|
|
45
55
|
conditions: ['style', 'sass', 'less'],
|
|
46
56
|
mainFields: ['style', 'sass'],
|
|
47
|
-
plugins
|
|
48
|
-
pluginFactory.create(sass_language_1.SassStylesheetLanguage),
|
|
49
|
-
pluginFactory.create(less_language_1.LessStylesheetLanguage),
|
|
50
|
-
pluginFactory.create(css_language_1.CssStylesheetLanguage),
|
|
51
|
-
(0, css_resource_plugin_1.createCssResourcePlugin)(cache),
|
|
52
|
-
],
|
|
57
|
+
plugins,
|
|
53
58
|
};
|
|
54
59
|
}
|
|
55
60
|
exports.createStylesheetBundleOptions = createStylesheetBundleOptions;
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
import type { Plugin } from 'esbuild';
|
|
9
|
+
import { NormalizedCachedOptions } from '../../../utils/normalize-cache';
|
|
10
|
+
import { LoadResultCache } from '../load-result-cache';
|
|
11
|
+
/**
|
|
12
|
+
* Options for the createCssInlineFontsPlugin
|
|
13
|
+
* @see createCssInlineFontsPlugin
|
|
14
|
+
*/
|
|
15
|
+
export interface CssInlineFontsPluginOptions {
|
|
16
|
+
/** Disk cache normalized options */
|
|
17
|
+
cacheOptions?: NormalizedCachedOptions;
|
|
18
|
+
/** Load results cache. */
|
|
19
|
+
cache?: LoadResultCache;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates an esbuild {@link Plugin} that inlines fonts imported via import-rule.
|
|
23
|
+
* within the build configuration.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createCssInlineFontsPlugin({ cache, cacheOptions, }: CssInlineFontsPluginOptions): Plugin;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.createCssInlineFontsPlugin = void 0;
|
|
11
|
+
const inline_fonts_1 = require("../../../utils/index-file/inline-fonts");
|
|
12
|
+
const load_result_cache_1 = require("../load-result-cache");
|
|
13
|
+
/**
|
|
14
|
+
* Creates an esbuild {@link Plugin} that inlines fonts imported via import-rule.
|
|
15
|
+
* within the build configuration.
|
|
16
|
+
*/
|
|
17
|
+
function createCssInlineFontsPlugin({ cache, cacheOptions, }) {
|
|
18
|
+
return {
|
|
19
|
+
name: 'angular-css-inline-fonts-plugin',
|
|
20
|
+
setup(build) {
|
|
21
|
+
const inlineFontsProcessor = new inline_fonts_1.InlineFontsProcessor({ cache: cacheOptions, minify: false });
|
|
22
|
+
build.onResolve({ filter: /fonts\.googleapis\.com|use\.typekit\.net/ }, (args) => {
|
|
23
|
+
// Only attempt to resolve import-rule tokens which only exist inside CSS.
|
|
24
|
+
if (args.kind !== 'import-rule') {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
if (!inlineFontsProcessor.canInlineRequest(args.path)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
path: args.path,
|
|
32
|
+
namespace: 'css-inline-fonts',
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
build.onLoad({ filter: /./, namespace: 'css-inline-fonts' }, (0, load_result_cache_1.createCachedLoad)(cache, async (args) => {
|
|
36
|
+
try {
|
|
37
|
+
return {
|
|
38
|
+
contents: await inlineFontsProcessor.processURL(args.path),
|
|
39
|
+
loader: 'css',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
return {
|
|
44
|
+
loader: 'css',
|
|
45
|
+
errors: [
|
|
46
|
+
{
|
|
47
|
+
text: `Failed to inline external stylesheet '${args.path}'.`,
|
|
48
|
+
detail: error,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
exports.createCssInlineFontsPlugin = createCssInlineFontsPlugin;
|
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
|
+
};
|
|
9
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
13
|
exports.createWatcher = exports.ChangedFiles = void 0;
|
|
11
|
-
const
|
|
12
|
-
const node_path_1 = require("node:path");
|
|
14
|
+
const watchpack_1 = __importDefault(require("watchpack"));
|
|
13
15
|
class ChangedFiles {
|
|
14
16
|
added = new Set();
|
|
15
17
|
modified = new Set();
|
|
@@ -28,87 +30,40 @@ class ChangedFiles {
|
|
|
28
30
|
}
|
|
29
31
|
exports.ChangedFiles = ChangedFiles;
|
|
30
32
|
function createWatcher(options) {
|
|
31
|
-
const watcher = new
|
|
32
|
-
|
|
33
|
-
interval: options?.interval,
|
|
33
|
+
const watcher = new watchpack_1.default({
|
|
34
|
+
poll: options?.polling ? options?.interval ?? true : false,
|
|
34
35
|
ignored: options?.ignored,
|
|
35
36
|
followSymlinks: options?.followSymlinks,
|
|
36
|
-
|
|
37
|
-
ignoreInitial: true,
|
|
37
|
+
aggregateTimeout: 250,
|
|
38
38
|
});
|
|
39
|
+
const watchedFiles = new Set();
|
|
39
40
|
const nextQueue = [];
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
* Example:
|
|
46
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
47
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
48
|
-
* change | 'C:/../src/app/app.component.css'
|
|
49
|
-
*
|
|
50
|
-
*/
|
|
51
|
-
let currentEvents;
|
|
52
|
-
/**
|
|
53
|
-
* Using `watcher.on('all')` does not capture some of events fired when using Visual studio and this does not happen all the time,
|
|
54
|
-
* but only after a file has been changed 3 or more times.
|
|
55
|
-
*
|
|
56
|
-
* Also, some IDEs such as Visual Studio (not VS Code) will fire a rename event instead of unlink when a file is renamed or changed.
|
|
57
|
-
*
|
|
58
|
-
* Example:
|
|
59
|
-
* ```
|
|
60
|
-
* watcher.on('raw')
|
|
61
|
-
* Change 1
|
|
62
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
63
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
64
|
-
* change | 'C:/../src/app/app.component.css'
|
|
65
|
-
*
|
|
66
|
-
* Change 2
|
|
67
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
68
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
69
|
-
* change | 'C:/../src/app/app.component.css'
|
|
70
|
-
*
|
|
71
|
-
* Change 3
|
|
72
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
73
|
-
* rename | 'C:/../src/app/app.component.css'
|
|
74
|
-
* change | 'C:/../src/app/app.component.css'
|
|
75
|
-
*
|
|
76
|
-
* watcher.on('all')
|
|
77
|
-
* Change 1
|
|
78
|
-
* change | 'C:\\..\\src\\app\\app.component.css'
|
|
79
|
-
*
|
|
80
|
-
* Change 2
|
|
81
|
-
* unlink | 'C:\\..\\src\\app\\app.component.css'
|
|
82
|
-
*
|
|
83
|
-
* Change 3
|
|
84
|
-
* ... (Nothing)
|
|
85
|
-
* ```
|
|
86
|
-
*/
|
|
87
|
-
watcher
|
|
88
|
-
.on('raw', (event, path, { watchedPath }) => {
|
|
89
|
-
if (watchedPath && !(0, node_path_1.extname)(watchedPath)) {
|
|
90
|
-
// Ignore directories, file changes in directories will be fired seperatly.
|
|
91
|
-
return;
|
|
41
|
+
let currentChangedFiles;
|
|
42
|
+
watcher.on('aggregated', (changes, removals) => {
|
|
43
|
+
const changedFiles = currentChangedFiles ?? new ChangedFiles();
|
|
44
|
+
for (const file of changes) {
|
|
45
|
+
changedFiles.modified.add(file);
|
|
92
46
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
case 'change':
|
|
96
|
-
// When polling is enabled `watchedPath` can be undefined.
|
|
97
|
-
// `path` is always normalized unlike `watchedPath`.
|
|
98
|
-
const changedPath = watchedPath ? (0, node_path_1.normalize)(watchedPath) : path;
|
|
99
|
-
handleFileChange(event, changedPath);
|
|
100
|
-
break;
|
|
47
|
+
for (const file of removals) {
|
|
48
|
+
changedFiles.removed.add(file);
|
|
101
49
|
}
|
|
102
|
-
|
|
103
|
-
|
|
50
|
+
const next = nextQueue.shift();
|
|
51
|
+
if (next) {
|
|
52
|
+
currentChangedFiles = undefined;
|
|
53
|
+
next(changedFiles);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
currentChangedFiles = changedFiles;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
104
59
|
return {
|
|
105
60
|
[Symbol.asyncIterator]() {
|
|
106
61
|
return this;
|
|
107
62
|
},
|
|
108
63
|
async next() {
|
|
109
|
-
if (
|
|
110
|
-
const result = { value:
|
|
111
|
-
|
|
64
|
+
if (currentChangedFiles && nextQueue.length === 0) {
|
|
65
|
+
const result = { value: currentChangedFiles };
|
|
66
|
+
currentChangedFiles = undefined;
|
|
112
67
|
return result;
|
|
113
68
|
}
|
|
114
69
|
return new Promise((resolve) => {
|
|
@@ -116,17 +71,40 @@ function createWatcher(options) {
|
|
|
116
71
|
});
|
|
117
72
|
},
|
|
118
73
|
add(paths) {
|
|
119
|
-
|
|
74
|
+
const previousSize = watchedFiles.size;
|
|
75
|
+
if (typeof paths === 'string') {
|
|
76
|
+
watchedFiles.add(paths);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
for (const file of paths) {
|
|
80
|
+
watchedFiles.add(file);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (previousSize !== watchedFiles.size) {
|
|
84
|
+
watcher.watch({
|
|
85
|
+
files: watchedFiles,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
120
88
|
},
|
|
121
89
|
remove(paths) {
|
|
122
|
-
|
|
90
|
+
const previousSize = watchedFiles.size;
|
|
91
|
+
if (typeof paths === 'string') {
|
|
92
|
+
watchedFiles.delete(paths);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
for (const file of paths) {
|
|
96
|
+
watchedFiles.delete(file);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (previousSize !== watchedFiles.size) {
|
|
100
|
+
watcher.watch({
|
|
101
|
+
files: watchedFiles,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
123
104
|
},
|
|
124
105
|
async close() {
|
|
125
106
|
try {
|
|
126
|
-
|
|
127
|
-
if (nextWaitTimeout) {
|
|
128
|
-
clearTimeout(nextWaitTimeout);
|
|
129
|
-
}
|
|
107
|
+
watcher.close();
|
|
130
108
|
}
|
|
131
109
|
finally {
|
|
132
110
|
let next;
|
|
@@ -136,48 +114,5 @@ function createWatcher(options) {
|
|
|
136
114
|
}
|
|
137
115
|
},
|
|
138
116
|
};
|
|
139
|
-
function handleFileChange(event, path) {
|
|
140
|
-
switch (event) {
|
|
141
|
-
case 'add':
|
|
142
|
-
case 'change':
|
|
143
|
-
// When using Visual Studio the rename event is fired before a change event when the contents of the file changed
|
|
144
|
-
// or instead of `unlink` when the file has been renamed.
|
|
145
|
-
case 'unlink':
|
|
146
|
-
case 'rename':
|
|
147
|
-
currentEvents ??= new Map();
|
|
148
|
-
currentEvents.set(path, event);
|
|
149
|
-
break;
|
|
150
|
-
default:
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
// Wait 250ms from next change to better capture groups of file save operations.
|
|
154
|
-
if (!nextWaitTimeout) {
|
|
155
|
-
nextWaitTimeout = setTimeout(() => {
|
|
156
|
-
nextWaitTimeout = undefined;
|
|
157
|
-
const next = nextQueue.shift();
|
|
158
|
-
if (next && currentEvents) {
|
|
159
|
-
const events = currentEvents;
|
|
160
|
-
currentEvents = undefined;
|
|
161
|
-
const currentChanges = new ChangedFiles();
|
|
162
|
-
for (const [path, event] of events) {
|
|
163
|
-
switch (event) {
|
|
164
|
-
case 'add':
|
|
165
|
-
currentChanges.added.add(path);
|
|
166
|
-
break;
|
|
167
|
-
case 'change':
|
|
168
|
-
currentChanges.modified.add(path);
|
|
169
|
-
break;
|
|
170
|
-
case 'unlink':
|
|
171
|
-
case 'rename':
|
|
172
|
-
currentChanges.removed.add(path);
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
next(currentChanges);
|
|
177
|
-
}
|
|
178
|
-
}, 250);
|
|
179
|
-
nextWaitTimeout?.unref();
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
117
|
}
|
|
183
118
|
exports.createWatcher = createWatcher;
|
package/src/utils/check-port.js
CHANGED
|
@@ -6,43 +6,26 @@
|
|
|
6
6
|
* Use of this source code is governed by an MIT-style license that can be
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
13
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
14
|
-
}
|
|
15
|
-
Object.defineProperty(o, k2, desc);
|
|
16
|
-
}) : (function(o, m, k, k2) {
|
|
17
|
-
if (k2 === undefined) k2 = k;
|
|
18
|
-
o[k2] = m[k];
|
|
19
|
-
}));
|
|
20
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
21
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
22
|
-
}) : function(o, v) {
|
|
23
|
-
o["default"] = v;
|
|
24
|
-
});
|
|
25
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
26
|
-
if (mod && mod.__esModule) return mod;
|
|
27
|
-
var result = {};
|
|
28
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
29
|
-
__setModuleDefault(result, mod);
|
|
30
|
-
return result;
|
|
9
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
31
11
|
};
|
|
32
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
13
|
exports.checkPort = void 0;
|
|
34
|
-
const
|
|
14
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
15
|
+
const node_net_1 = require("node:net");
|
|
35
16
|
const load_esm_1 = require("./load-esm");
|
|
36
17
|
const tty_1 = require("./tty");
|
|
37
18
|
function createInUseError(port) {
|
|
38
19
|
return new Error(`Port ${port} is already in use. Use '--port' to specify a different port.`);
|
|
39
20
|
}
|
|
40
21
|
async function checkPort(port, host) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
22
|
+
// Disabled due to Vite not handling port 0 and instead always using the default value (5173)
|
|
23
|
+
// TODO: Enable this again once Vite is fixed
|
|
24
|
+
// if (port === 0) {
|
|
25
|
+
// return 0;
|
|
26
|
+
// }
|
|
44
27
|
return new Promise((resolve, reject) => {
|
|
45
|
-
const server =
|
|
28
|
+
const server = (0, node_net_1.createServer)();
|
|
46
29
|
server
|
|
47
30
|
.once('error', (err) => {
|
|
48
31
|
if (err.code !== 'EADDRINUSE') {
|
|
@@ -60,11 +43,14 @@ async function checkPort(port, host) {
|
|
|
60
43
|
message: `Port ${port} is already in use.\nWould you like to use a different port?`,
|
|
61
44
|
default: true,
|
|
62
45
|
}))
|
|
63
|
-
.then((answers) =>
|
|
46
|
+
.then((answers) => answers.useDifferent ? resolve(checkPort(0, host)) : reject(createInUseError(port)), () => reject(createInUseError(port)));
|
|
64
47
|
})
|
|
65
48
|
.once('listening', () => {
|
|
49
|
+
// Get the actual address from the listening server instance
|
|
50
|
+
const address = server.address();
|
|
51
|
+
(0, node_assert_1.default)(address && typeof address !== 'string', 'Port check server address should always be an object.');
|
|
66
52
|
server.close();
|
|
67
|
-
resolve(port);
|
|
53
|
+
resolve(address.port);
|
|
68
54
|
})
|
|
69
55
|
.listen(port, host);
|
|
70
56
|
});
|
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
/**
|
|
9
9
|
* Delete an output directory, but error out if it's the root of the project.
|
|
10
10
|
*/
|
|
11
|
-
export declare function deleteOutputDir(root: string, outputPath: string): Promise<void>;
|
|
11
|
+
export declare function deleteOutputDir(root: string, outputPath: string, emptyOnlyDirectories?: string[]): Promise<void>;
|
|
@@ -13,11 +13,14 @@ const node_path_1 = require("node:path");
|
|
|
13
13
|
/**
|
|
14
14
|
* Delete an output directory, but error out if it's the root of the project.
|
|
15
15
|
*/
|
|
16
|
-
async function deleteOutputDir(root, outputPath) {
|
|
16
|
+
async function deleteOutputDir(root, outputPath, emptyOnlyDirectories) {
|
|
17
17
|
const resolvedOutputPath = (0, node_path_1.resolve)(root, outputPath);
|
|
18
18
|
if (resolvedOutputPath === root) {
|
|
19
19
|
throw new Error('Output path MUST not be project root directory!');
|
|
20
20
|
}
|
|
21
|
+
const directoriesToEmpty = emptyOnlyDirectories
|
|
22
|
+
? new Set(emptyOnlyDirectories.map((directory) => (0, node_path_1.join)(resolvedOutputPath, directory)))
|
|
23
|
+
: undefined;
|
|
21
24
|
// Avoid removing the actual directory to avoid errors in cases where the output
|
|
22
25
|
// directory is mounted or symlinked. Instead the contents are removed.
|
|
23
26
|
let entries;
|
|
@@ -31,7 +34,13 @@ async function deleteOutputDir(root, outputPath) {
|
|
|
31
34
|
throw error;
|
|
32
35
|
}
|
|
33
36
|
for (const entry of entries) {
|
|
34
|
-
|
|
37
|
+
const fullEntry = (0, node_path_1.join)(resolvedOutputPath, entry);
|
|
38
|
+
// Leave requested directories. This allows symlinks to continue to function.
|
|
39
|
+
if (directoriesToEmpty?.has(fullEntry)) {
|
|
40
|
+
await deleteOutputDir(resolvedOutputPath, fullEntry);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
await (0, promises_1.rm)(fullEntry, { force: true, recursive: true, maxRetries: 3 });
|
|
35
44
|
}
|
|
36
45
|
}
|
|
37
46
|
exports.deleteOutputDir = deleteOutputDir;
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
+
/// <reference types="node" />
|
|
9
|
+
/// <reference types="@types/node/url" />
|
|
10
|
+
/// <reference types="@types/node/ts4.8/url" />
|
|
11
|
+
import { URL } from 'node:url';
|
|
8
12
|
import { NormalizedCachedOptions } from '../normalize-cache';
|
|
9
13
|
export interface InlineFontsOptions {
|
|
10
14
|
minify?: boolean;
|
|
@@ -16,7 +20,8 @@ export declare class InlineFontsProcessor {
|
|
|
16
20
|
constructor(options: InlineFontsOptions);
|
|
17
21
|
process(content: string): Promise<string>;
|
|
18
22
|
private getResponse;
|
|
19
|
-
|
|
23
|
+
processURL(url: string | URL): Promise<string | undefined>;
|
|
24
|
+
canInlineRequest(url: string): boolean;
|
|
20
25
|
private getFontProviderDetails;
|
|
21
26
|
private createNormalizedUrl;
|
|
22
27
|
}
|
|
@@ -114,7 +114,7 @@ class InlineFontsProcessor {
|
|
|
114
114
|
if (!url) {
|
|
115
115
|
continue;
|
|
116
116
|
}
|
|
117
|
-
const content = await this.
|
|
117
|
+
const content = await this.processURL(url);
|
|
118
118
|
if (content === undefined) {
|
|
119
119
|
continue;
|
|
120
120
|
}
|
|
@@ -195,7 +195,16 @@ class InlineFontsProcessor {
|
|
|
195
195
|
.get(url, {
|
|
196
196
|
agent,
|
|
197
197
|
headers: {
|
|
198
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Always use a Windows UA. This is because Google fonts will including hinting in fonts for Windows.
|
|
200
|
+
* Hinting is a technique used with Windows files to improve appearance however
|
|
201
|
+
* results in 20-50% larger file sizes.
|
|
202
|
+
*
|
|
203
|
+
* @see http://google3/java/com/google/fonts/css/OpenSansWebFontsCssBuilder.java?l=22
|
|
204
|
+
* @see https://fonts.google.com/knowledge/glossary/hinting (short)
|
|
205
|
+
* @see https://glyphsapp.com/learn/hinting-manual-truetype-hinting (deep dive)
|
|
206
|
+
*/
|
|
207
|
+
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
199
208
|
},
|
|
200
209
|
}, (res) => {
|
|
201
210
|
if (res.statusCode !== 200) {
|
|
@@ -216,12 +225,16 @@ class InlineFontsProcessor {
|
|
|
216
225
|
}
|
|
217
226
|
return data;
|
|
218
227
|
}
|
|
219
|
-
async
|
|
220
|
-
const
|
|
228
|
+
async processURL(url) {
|
|
229
|
+
const normalizedURL = url instanceof node_url_1.URL ? url : this.createNormalizedUrl(url);
|
|
230
|
+
if (!normalizedURL) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const provider = this.getFontProviderDetails(normalizedURL);
|
|
221
234
|
if (!provider) {
|
|
222
235
|
return undefined;
|
|
223
236
|
}
|
|
224
|
-
let cssContent = await this.getResponse(
|
|
237
|
+
let cssContent = await this.getResponse(normalizedURL);
|
|
225
238
|
if (this.options.minify) {
|
|
226
239
|
cssContent = cssContent
|
|
227
240
|
// Comments.
|
|
@@ -233,21 +246,24 @@ class InlineFontsProcessor {
|
|
|
233
246
|
}
|
|
234
247
|
return cssContent;
|
|
235
248
|
}
|
|
249
|
+
canInlineRequest(url) {
|
|
250
|
+
const normalizedUrl = this.createNormalizedUrl(url);
|
|
251
|
+
return normalizedUrl ? !!this.getFontProviderDetails(normalizedUrl) : false;
|
|
252
|
+
}
|
|
236
253
|
getFontProviderDetails(url) {
|
|
237
254
|
return SUPPORTED_PROVIDERS[url.hostname];
|
|
238
255
|
}
|
|
239
256
|
createNormalizedUrl(value) {
|
|
240
257
|
// Need to convert '//' to 'https://' because the URL parser will fail with '//'.
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
258
|
+
const url = new node_url_1.URL(value.startsWith('//') ? `https:${value}` : value, 'resolve://');
|
|
259
|
+
switch (url.protocol) {
|
|
260
|
+
case 'http:':
|
|
261
|
+
case 'https:':
|
|
262
|
+
url.protocol = 'https:';
|
|
263
|
+
return url;
|
|
264
|
+
default:
|
|
265
|
+
return undefined;
|
|
246
266
|
}
|
|
247
|
-
const url = new node_url_1.URL(normalizedHref);
|
|
248
|
-
// Force HTTPS protocol
|
|
249
|
-
url.protocol = 'https:';
|
|
250
|
-
return url;
|
|
251
267
|
}
|
|
252
268
|
}
|
|
253
269
|
exports.InlineFontsProcessor = InlineFontsProcessor;
|
|
@@ -11,19 +11,20 @@ exports.getESMLoaderArgs = exports.callInitializeIfNeeded = void 0;
|
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
12
|
const node_url_1 = require("node:url");
|
|
13
13
|
const node_worker_threads_1 = require("node:worker_threads");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const semver_1 = require("semver");
|
|
15
|
+
let SUPPORTS_IMPORT_FLAG;
|
|
16
|
+
function supportsImportFlag() {
|
|
17
|
+
return (SUPPORTS_IMPORT_FLAG ??= (0, semver_1.satisfies)(process.versions.node, '>= 18.19'));
|
|
17
18
|
}
|
|
18
19
|
/** Call the initialize hook when running on Node.js 18 */
|
|
19
20
|
function callInitializeIfNeeded(initialize) {
|
|
20
|
-
if (
|
|
21
|
+
if (!supportsImportFlag()) {
|
|
21
22
|
initialize(node_worker_threads_1.workerData);
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
exports.callInitializeIfNeeded = callInitializeIfNeeded;
|
|
25
26
|
function getESMLoaderArgs() {
|
|
26
|
-
if (
|
|
27
|
+
if (!supportsImportFlag()) {
|
|
27
28
|
return [
|
|
28
29
|
'--no-warnings', // Suppress `ExperimentalWarning: Custom ESM Loaders is an experimental feature...`.
|
|
29
30
|
'--loader',
|
|
@@ -1,8 +0,0 @@
|
|
|
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
|
-
export declare function normalizePath(path: string): string;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @license
|
|
4
|
-
* Copyright Google LLC All Rights Reserved.
|
|
5
|
-
*
|
|
6
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
-
* found in the LICENSE file at https://angular.io/license
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.normalizePath = void 0;
|
|
11
|
-
const node_os_1 = require("node:os");
|
|
12
|
-
const node_path_1 = require("node:path");
|
|
13
|
-
const USING_WINDOWS = (0, node_os_1.platform)() === 'win32';
|
|
14
|
-
function normalizePath(path) {
|
|
15
|
-
if (USING_WINDOWS) {
|
|
16
|
-
return (0, node_path_1.normalize)(path).toLowerCase();
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
return (0, node_path_1.normalize)(path);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.normalizePath = normalizePath;
|