Skip to content

Commit a511d66

Browse files
authored
feat: significantly improve CLI startup times (#42)
Move a few heavier modules from static imports to lazy `require()`s. Also remove support for globally installed addons via yarn *and* npm. If Yarn is detected, Denali will search Yarn for global addons, otherwise it wills search npm, but not both. This lets Yarn users avoid the delays that npm forces (because we need to shell out for `npm root`, which eats 500ms). We could make this behavior configurable in the future, once we have a ~/.denali config file
1 parent 54f2573 commit a511d66

File tree

2 files changed

+18
-15
lines changed

2 files changed

+18
-15
lines changed

lib/find-addons.ts

+12-11
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,7 @@ export default function findAddons(isLocal: boolean): AddonSummary[] {
3838
return finalizeAddons(addons);
3939
}
4040

41-
let npmRoot = execSync('npm root -g').toString().trim();
42-
debug(`searching for addons globally in npm root: ${ npmRoot }`);
43-
let addons = findPlugins(merge({
44-
dir: npmRoot,
45-
scanAllDirs: true
46-
}, findOptions));
41+
let addons;
4742

4843
// Because yarn stores it's global modules separately, and doesn't yet support the `root` command,
4944
// we have to double check yarn's global installs for any denali addons. The easiest way of
@@ -52,13 +47,12 @@ export default function findAddons(isLocal: boolean): AddonSummary[] {
5247
// development of global addons (like denali itself)
5348
// TODO shell out to `yarn root` once yarnpkg/yarn#2388 is fixed
5449
if (commandExists('yarn')) {
55-
let yarnGlobalInstalls = path.join(YarnConstants.GLOBAL_MODULE_DIRECTORY, 'node_modules');
50+
let yarnGlobalInstalls = YarnConstants.GLOBAL_MODULE_DIRECTORY;
5651
debug(`searching for addons globally in yarn global installs: ${ yarnGlobalInstalls }`);
5752
if (fs.existsSync(yarnGlobalInstalls)) {
58-
addons = addons.concat(findPlugins(merge({
59-
dir: yarnGlobalInstalls,
60-
scanAllDirs: true
61-
}, findOptions)));
53+
addons = findPlugins(merge({
54+
dir: yarnGlobalInstalls
55+
}, findOptions));
6256
} else {
6357
debug(`Tried to load globally installed addons from yarn, but ${ yarnGlobalInstalls } doesn't exist, skipping ...`);
6458
}
@@ -72,6 +66,13 @@ export default function findAddons(isLocal: boolean): AddonSummary[] {
7266
} else {
7367
debug(`Tried to load globally linked addons from yarn, but ${ yarnGlobalLinks } doesn't exist, skipping ...`);
7468
}
69+
} else {
70+
let npmRoot = execSync('npm root -g').toString().trim();
71+
debug(`searching for addons globally in npm root: ${ npmRoot }`);
72+
addons = findPlugins(merge({
73+
dir: npmRoot,
74+
scanAllDirs: true
75+
}, findOptions));
7576
}
7677

7778
return finalizeAddons(addons);

lib/project.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as path from 'path';
2-
import { Tree, Builder as Broccoli, BuildResults } from 'broccoli';
2+
// import { Tree, Builder as Broccoli, BuildResults } from 'broccoli';
33
import * as rimraf from 'rimraf';
44
import printSlowNodes from 'broccoli-slow-trees';
55
import { sync as copyDereferenceSync } from 'copy-dereference';
@@ -81,11 +81,12 @@ export default class Project {
8181
}
8282

8383
// TODO build descriptions
84-
async _build(tree: Tree, destDir: string): Promise<void> {
84+
async _build(tree: any, destDir: string): Promise<void> {
8585
try {
8686
debug('building project');
8787
let timer = startTimer();
8888
spinner.start(`Building ...`);
89+
const Broccoli = require('broccoli').Builder;
8990
let broccoli = new Broccoli(tree);
9091
let results = await broccoli.build();
9192
await this.finishBuild(results, destDir);
@@ -116,9 +117,10 @@ export default class Project {
116117
/**
117118
* Build the project and start watching the source files for changes, rebuilding when they occur
118119
*/
119-
async _watch(tree: Tree, options: WatchOptions = {}) {
120+
async _watch(tree: any, options: WatchOptions = {}) {
120121
spinner.start(`Watching ...`);
121122
let timer = startTimer();
123+
const Broccoli = require('broccoli').Builder;
122124
let broccoli = new Broccoli(tree);
123125
let watcher = new Watcher(broccoli, { beforeRebuild: options.beforeRebuild, interval: 100 });
124126
let destDir = options.destDir || path.join(this.dir, 'dist');
@@ -192,7 +194,7 @@ export default class Project {
192194
* After a build completes, this method cleans up the result. It copies the results out of tmp and
193195
* into the output directory, and kicks off any optional behaviors post-build.
194196
*/
195-
finishBuild(results: BuildResults, destDir: string) {
197+
finishBuild(results: { directory: string, graph: any }, destDir: string) {
196198
debug(`copying broccoli build output to dist`);
197199
rimraf.sync(destDir);
198200
copyDereferenceSync(path.resolve(results.directory), destDir);

0 commit comments

Comments
 (0)