Skip to content

Commit ee5763d

Browse files
committed
refactor(@angular-devkit/build-angular): use fast-glob for file searching support
The file searching within the build system (both Webpack and esbuild) now use the `fast-glob` package for globbing which provides a small performance improvement. Since the assets option in particular is within the critical path of the buil pipeline, the performance benefit from the switch will be most prevalent in asset heavy projects. As an example, the Angular Material documentation site saw the asset discovery time reduced by over half with the switch. `fast-glob` is also the package used by Vite which provides additional benefit by ensuring that the Angular CLI behavior matches that of the newly integrated Vite development server.
1 parent 50955db commit ee5763d

File tree

17 files changed

+50
-87
lines changed

17 files changed

+50
-87
lines changed

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@
9595
"@types/browserslist": "^4.15.0",
9696
"@types/cacache": "^15.0.0",
9797
"@types/express": "^4.16.0",
98-
"@types/glob": "^8.0.0",
9998
"@types/http-proxy": "^1.17.4",
10099
"@types/ini": "^1.3.31",
101100
"@types/inquirer": "^8.0.0",
@@ -143,7 +142,7 @@
143142
"eslint-plugin-header": "3.1.1",
144143
"eslint-plugin-import": "2.27.5",
145144
"express": "4.18.2",
146-
"glob": "8.1.0",
145+
"fast-glob": "3.2.12",
147146
"http-proxy": "^1.18.1",
148147
"https-proxy-agent": "5.0.1",
149148
"husky": "8.0.3",

packages/angular_devkit/build_angular/BUILD.bazel

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ ts_library(
130130
"@npm//@types/babel__template",
131131
"@npm//@types/browserslist",
132132
"@npm//@types/cacache",
133-
"@npm//@types/glob",
134133
"@npm//@types/inquirer",
135134
"@npm//@types/karma",
136135
"@npm//@types/less",
@@ -153,7 +152,7 @@ ts_library(
153152
"@npm//css-loader",
154153
"@npm//esbuild",
155154
"@npm//esbuild-wasm",
156-
"@npm//glob",
155+
"@npm//fast-glob",
157156
"@npm//https-proxy-agent",
158157
"@npm//inquirer",
159158
"@npm//jsonc-parser",
@@ -357,8 +356,7 @@ LARGE_SPECS = {
357356
},
358357
"jest": {
359358
"extra_deps": [
360-
"@npm//glob",
361-
"@npm//@types/glob",
359+
"@npm//fast-glob",
362360
],
363361
},
364362
}

packages/angular_devkit/build_angular/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"critters": "0.0.18",
3535
"css-loader": "6.8.1",
3636
"esbuild-wasm": "0.17.19",
37-
"glob": "8.1.0",
37+
"fast-glob": "3.2.12",
3838
"https-proxy-agent": "5.0.1",
3939
"inquirer": "8.2.4",
4040
"jsonc-parser": "3.2.0",

packages/angular_devkit/build_angular/src/builders/dev-server/load-proxy-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { hasMagic as isDynamicPattern } from 'glob';
9+
import { isDynamicPattern } from 'fast-glob';
1010
import { existsSync } from 'node:fs';
1111
import { readFile } from 'node:fs/promises';
1212
import { extname, resolve } from 'node:path';

packages/angular_devkit/build_angular/src/builders/jest/test-files.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { IOptions as GlobOptions, glob as globCb } from 'glob';
10-
import { promisify } from 'util';
9+
import fastGlob, { Options as GlobOptions } from 'fast-glob';
1110
import { JestBuilderOptions } from './options';
1211

13-
const globAsync = promisify(globCb);
14-
1512
/**
1613
* Finds all test files in the project.
1714
*
@@ -24,15 +21,13 @@ const globAsync = promisify(globCb);
2421
export async function findTestFiles(
2522
options: JestBuilderOptions,
2623
workspaceRoot: string,
27-
glob: typeof globAsync = globAsync,
24+
glob: typeof fastGlob = fastGlob,
2825
): Promise<Set<string>> {
2926
const globOptions: GlobOptions = {
3027
cwd: workspaceRoot,
3128
ignore: ['node_modules/**'].concat(options.exclude),
32-
strict: true, // Fail on an "unusual error" when reading the file system.
33-
nobrace: true, // Do not expand `a{b,c}` to `ab,ac`.
34-
noext: true, // Disable "extglob" patterns.
35-
nodir: true, // Match only files, don't care about directories.
29+
braceExpansion: false, // Do not expand `a{b,c}` to `ab,ac`.
30+
extglob: false, // Disable "extglob" patterns.
3631
};
3732

3833
const included = await Promise.all(options.include.map((pattern) => glob(pattern, globOptions)));

packages/angular_devkit/build_angular/src/builders/jest/tests/test-files_spec.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
// eslint-disable-next-line import/no-extraneous-dependencies
10+
import realGlob from 'fast-glob';
911
import { promises as fs } from 'fs';
10-
import { glob as globCb } from 'glob';
1112
import * as path from 'path';
12-
import { promisify } from 'util';
1313
import { findTestFiles } from '../test-files';
1414
import { BASE_OPTIONS } from './options';
1515

16-
const realGlob = promisify(globCb);
17-
1816
describe('test-files', () => {
1917
describe('findTestFiles()', () => {
2018
let tempDir!: string;
@@ -118,7 +116,8 @@ describe('test-files', () => {
118116
include: ['*.spec.ts', '*.stuff.ts', '*.test.ts'],
119117
},
120118
tempDir,
121-
glob,
119+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
120+
glob as any,
122121
),
123122
).toBeRejectedWith(err);
124123
});

packages/angular_devkit/build_angular/src/builders/karma/find-tests-plugin.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,12 @@
77
*/
88

99
import assert from 'assert';
10+
import glob, { isDynamicPattern } from 'fast-glob';
1011
import { PathLike, constants, promises as fs } from 'fs';
11-
import glob, { hasMagic } from 'glob';
1212
import { pluginName } from 'mini-css-extract-plugin';
1313
import { basename, dirname, extname, join, relative } from 'path';
14-
import { promisify } from 'util';
1514
import type { Compilation, Compiler } from 'webpack';
1615

17-
const globPromise = promisify(glob);
18-
1916
/**
2017
* The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
2118
*/
@@ -114,7 +111,7 @@ async function findMatchingTests(
114111
}
115112

116113
// special logic when pattern does not look like a glob
117-
if (!hasMagic(normalizedPattern)) {
114+
if (!isDynamicPattern(normalizedPattern)) {
118115
if (await isDirectory(join(projectSourceRoot, normalizedPattern))) {
119116
normalizedPattern = `${normalizedPattern}/**/*.spec.@(ts|tsx)`;
120117
} else {
@@ -133,10 +130,8 @@ async function findMatchingTests(
133130
}
134131
}
135132

136-
return globPromise(normalizedPattern, {
133+
return glob(normalizedPattern, {
137134
cwd: projectSourceRoot,
138-
root: projectSourceRoot,
139-
nomount: true,
140135
absolute: true,
141136
ignore: ['**/node_modules/**', ...ignore],
142137
});

packages/angular_devkit/build_angular/src/utils/copy-assets.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import * as fs from 'fs';
10-
import glob from 'glob';
11-
import * as path from 'path';
12-
import { promisify } from 'util';
13-
14-
const globPromise = promisify(glob);
9+
import glob from 'fast-glob';
10+
import fs from 'node:fs';
11+
import path from 'node:path';
1512

1613
export async function copyAssets(
1714
entries: {
@@ -32,14 +29,11 @@ export async function copyAssets(
3229

3330
for (const entry of entries) {
3431
const cwd = path.resolve(root, entry.input);
35-
const files = await globPromise(entry.glob, {
32+
const files = await glob(entry.glob, {
3633
cwd,
3734
dot: true,
38-
nodir: true,
39-
root: cwd,
40-
nomount: true,
4135
ignore: entry.ignore ? defaultIgnore.concat(entry.ignore) : defaultIgnore,
42-
follow: entry.followSymlinks,
36+
followSymbolicLinks: entry.followSymlinks,
4337
});
4438

4539
const directoryExists = new Set<string>();

packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import type { ObjectPattern } from 'copy-webpack-plugin';
1010
import { createHash } from 'crypto';
11-
import glob from 'glob';
11+
import glob from 'fast-glob';
1212
import * as path from 'path';
1313
import type { Configuration, WebpackOptionsNormalized } from 'webpack';
1414
import {
@@ -125,9 +125,8 @@ export function getInstrumentationExcludedPaths(
125125
const excluded = new Set<string>();
126126

127127
for (const excludeGlob of excludedPaths) {
128-
glob
129-
.sync(excludeGlob, { nodir: true, cwd: root, root, nomount: true })
130-
.forEach((p) => excluded.add(path.join(root, p)));
128+
const excludePath = excludeGlob[0] === '/' ? excludeGlob.slice(1) : excludeGlob;
129+
glob.sync(excludePath, { cwd: root }).forEach((p) => excluded.add(path.join(root, p)));
131130
}
132131

133132
return excluded;

scripts/validate-user-analytics.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88

99
import { logging } from '@angular-devkit/core';
1010
import assert from 'assert';
11+
import glob from 'fast-glob';
1112
import * as fs from 'fs';
12-
import { glob as globCb } from 'glob';
1313
import * as path from 'path';
14-
import { promisify } from 'util';
1514
import { packages } from '../lib/packages';
1615
import {
1716
EventCustomDimension,
@@ -80,7 +79,6 @@ async function _checkDimensions(dimensionsTable: string, logger: logging.Logger)
8079
}
8180
};
8281

83-
const glob = promisify(globCb);
8482
// Find all the schemas
8583
const packagesPaths = Object.values(packages).map(({ root }) => root);
8684
for (const packagePath of packagesPaths) {

0 commit comments

Comments
 (0)