Skip to content

Commit 7f739a0

Browse files
committed
fix(monorepos): do not lazy require missing dependencies
- Do not auto-install any missing dev dependencies, like jest or puppeteer - If a dev dep is missing, print out an error what needs to be installed - addWatchDir / addWatchFile to compilerCtx - Watch for changes in global styles and global style imports
1 parent 43c5d98 commit 7f739a0

12 files changed

+223
-347
lines changed

src/cli/task-test.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ export const taskTest = async (config: Config) => {
3636
}
3737

3838
// ensure we've got the required modules installed
39-
// jest and puppeteer are quite large, so this
40-
// is an experiment to lazy install these
41-
// modules only when you need them
42-
await config.sys.lazyRequire.ensure(config.logger, config.rootDir, ensureModuleIds);
39+
const diagnostics = await config.sys.lazyRequire.ensure(config.rootDir, ensureModuleIds);
40+
if (diagnostics.length > 0) {
41+
config.logger.printDiagnostics(diagnostics);
42+
return config.sys.exit(1);
43+
}
4344

4445
// let's test!
4546
const { createTesting } = await import('@stencil/core/testing');

src/compiler/build/compiler-ctx.ts

+7-14
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type * as d from '../../declarations';
22
import { basename, dirname, extname, join } from 'path';
33
import { buildEvents } from '../events';
4-
import { normalizePath } from '@utils';
4+
import { noop, normalizePath } from '@utils';
55

66
/**
77
* The CompilerCtx is a persistent object that's reused throughout
@@ -17,33 +17,28 @@ export class CompilerContext implements d.CompilerCtx {
1717
activeFilesUpdated: string[] = [];
1818
activeDirsAdded: string[] = [];
1919
activeDirsDeleted: string[] = [];
20+
addWatchDir: (path: string) => void = noop;
21+
addWatchFile: (path: string) => void = noop;
2022
cache: d.Cache;
2123
cachedStyleMeta = new Map<string, d.StyleCompiler>();
24+
changedFiles = new Set<string>();
25+
changedModules = new Set<string>();
2226
collections: d.CollectionCompilerMeta[] = [];
2327
compilerOptions: any = null;
2428
events = buildEvents();
2529
fs: d.InMemoryFileSystem;
26-
fsWatcher: d.FsWatcher = null;
27-
hasFsWatcherEvents = false;
28-
hasLoggedServerUrl = false;
2930
hasSuccessfulBuild = false;
3031
isActivelyBuilding = false;
3132
lastBuildResults: d.CompilerBuildResults = null;
32-
lastBuildStyles = new Map<string, string>();
33-
lastComponentStyleInput = new Map<string, string>();
3433
moduleMap: d.ModuleMap = new Map();
3534
nodeMap = new WeakMap();
3635
resolvedCollections = new Set<string>();
36+
rollupCache = new Map();
3737
rollupCacheHydrate: any = null;
3838
rollupCacheLazy: any = null;
3939
rollupCacheNative: any = null;
40-
rootTsFiles: string[] = [];
41-
tsService: d.TsService = null;
4240
cachedGlobalStyle: string;
4341
styleModeNames = new Set<string>();
44-
rollupCache = new Map();
45-
changedModules = new Set<string>();
46-
changedFiles = new Set<string>();
4742
worker: d.CompilerWorkerContext = null;
4843

4944
reset() {
@@ -52,14 +47,12 @@ export class CompilerContext implements d.CompilerCtx {
5247
this.cachedGlobalStyle = null;
5348
this.collections.length = 0;
5449
this.compilerOptions = null;
55-
this.lastComponentStyleInput.clear();
50+
this.hasSuccessfulBuild = false;
5651
this.rollupCacheHydrate = null;
5752
this.rollupCacheLazy = null;
5853
this.rollupCacheNative = null;
5954
this.moduleMap.clear();
6055
this.resolvedCollections.clear();
61-
this.rootTsFiles.length = 0;
62-
this.tsService = null;
6356

6457
if (this.fs != null) {
6558
this.fs.clearCache();

src/compiler/build/watch-build.ts

+99-108
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,24 @@ import { BuildContext } from './build-ctx';
44
import { compilerRequest } from '../bundle/dev-module';
55
import { createTsWatchProgram } from '../transpile/create-watch-program';
66
import { dirname, resolve } from 'path';
7-
import { filesChanged, hasHtmlChanges, hasScriptChanges, hasStyleChanges, scriptsAdded, scriptsDeleted } from '../fs-watch/fs-watch-rebuild';
7+
import {
8+
filesChanged,
9+
hasHtmlChanges,
10+
hasScriptChanges,
11+
hasStyleChanges,
12+
scriptsAdded,
13+
scriptsDeleted,
14+
} from '../fs-watch/fs-watch-rebuild';
815
import { hasServiceWorkerChanges } from '../service-worker/generate-sw';
16+
import { isString } from '@utils';
917
import type ts from 'typescript';
1018

1119
export const createWatchBuild = async (config: d.Config, compilerCtx: d.CompilerCtx): Promise<d.CompilerWatcher> => {
1220
let isRebuild = false;
13-
let tsWatchProgram: { program: ts.WatchOfConfigFile<ts.EmitAndSemanticDiagnosticsBuilderProgram>; rebuild: () => void };
14-
let srcFileWatchCloser: () => void;
15-
let otherFileWatchCloser: () => void;
16-
21+
let tsWatchProgram: {
22+
program: ts.WatchOfConfigFile<ts.EmitAndSemanticDiagnosticsBuilderProgram>;
23+
rebuild: () => void;
24+
};
1725
let closeResolver: Function;
1826
const watchWaiter = new Promise<d.WatcherCloseResults>(resolve => (closeResolver = resolve));
1927

@@ -23,31 +31,6 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
2331
const filesUpdated = new Set<string>();
2432
const filesDeleted = new Set<string>();
2533

26-
const onSrcFileChange: d.CompilerFileWatcherCallback = (p, eventKind) => {
27-
updateCompilerCtxCache(config, compilerCtx, p, eventKind);
28-
29-
switch (eventKind) {
30-
case 'dirAdd':
31-
dirsAdded.add(p);
32-
break;
33-
case 'dirDelete':
34-
dirsDeleted.add(p);
35-
break;
36-
case 'fileAdd':
37-
filesAdded.add(p);
38-
break;
39-
case 'fileUpdate':
40-
filesUpdated.add(p);
41-
break;
42-
case 'fileDelete':
43-
filesDeleted.add(p);
44-
break;
45-
}
46-
47-
config.logger.debug(`${eventKind}: ${p}`);
48-
tsWatchProgram.rebuild();
49-
};
50-
5134
const onBuild = async (tsBuilder: ts.BuilderProgram) => {
5235
const buildCtx = new BuildContext(config, compilerCtx);
5336
buildCtx.isRebuild = isRebuild;
@@ -83,27 +66,61 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
8366
};
8467

8568
const start = async () => {
86-
const srcRead = watchSrcDirectory(config, compilerCtx, onSrcFileChange);
87-
const otherRead = watchOtherFiles(config, compilerCtx);
88-
srcFileWatchCloser = await srcRead;
89-
otherFileWatchCloser = await otherRead;
69+
const srcRead = watchSrcDirectory(config, compilerCtx);
70+
const otherRead = watchRootFiles(config, compilerCtx);
71+
await srcRead;
72+
await otherRead;
9073
tsWatchProgram = await createTsWatchProgram(config, onBuild);
9174
return watchWaiter;
9275
};
9376

94-
const close = async () => {
95-
if (srcFileWatchCloser) {
96-
srcFileWatchCloser();
77+
const watchingDirs = new Map<string, d.CompilerFileWatcher>();
78+
const watchingFiles = new Map<string, d.CompilerFileWatcher>();
79+
80+
const onFsChange: d.CompilerFileWatcherCallback = (p, eventKind) => {
81+
if (tsWatchProgram) {
82+
updateCompilerCtxCache(config, compilerCtx, p, eventKind);
83+
84+
switch (eventKind) {
85+
case 'dirAdd':
86+
dirsAdded.add(p);
87+
break;
88+
case 'dirDelete':
89+
dirsDeleted.add(p);
90+
break;
91+
case 'fileAdd':
92+
filesAdded.add(p);
93+
break;
94+
case 'fileUpdate':
95+
filesUpdated.add(p);
96+
break;
97+
case 'fileDelete':
98+
filesDeleted.add(p);
99+
break;
100+
}
101+
102+
config.logger.debug(`onFsChange ${eventKind}: ${p}`);
103+
tsWatchProgram.rebuild();
97104
}
98-
if (otherFileWatchCloser) {
99-
otherFileWatchCloser();
105+
};
106+
107+
const onDirChange: d.CompilerFileWatcherCallback = (p, eventKind) => {
108+
if (eventKind != null) {
109+
onFsChange(p, eventKind);
100110
}
111+
};
112+
113+
const close = async () => {
114+
watchingDirs.forEach(w => w.close());
115+
watchingFiles.forEach(w => w.close());
116+
watchingDirs.clear();
117+
watchingFiles.clear();
118+
101119
if (tsWatchProgram) {
102120
tsWatchProgram.program.close();
121+
tsWatchProgram = null;
103122
}
104123

105-
srcFileWatchCloser = otherFileWatchCloser = tsWatchProgram = null;
106-
107124
const watcherCloseResults: d.WatcherCloseResults = {
108125
exitCode: 0,
109126
};
@@ -113,6 +130,18 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
113130

114131
const request = async (data: d.CompilerRequest) => compilerRequest(config, compilerCtx, data);
115132

133+
compilerCtx.addWatchFile = filePath => {
134+
if (isString(filePath) && !watchingFiles.has(filePath)) {
135+
watchingFiles.set(filePath, config.sys.watchFile(filePath, onFsChange));
136+
}
137+
};
138+
139+
compilerCtx.addWatchDir = (dirPath, recursive) => {
140+
if (isString(dirPath) && !watchingDirs.has(dirPath)) {
141+
watchingDirs.set(dirPath, config.sys.watchDirectory(dirPath, onDirChange, recursive));
142+
}
143+
};
144+
116145
config.sys.addDestory(close);
117146

118147
return {
@@ -123,90 +152,47 @@ export const createWatchBuild = async (config: d.Config, compilerCtx: d.Compiler
123152
};
124153
};
125154

126-
const watchSrcDirectory = async (config: d.Config, compilerCtx: d.CompilerCtx, callback: d.CompilerFileWatcherCallback) => {
127-
const watching = new Map();
128-
const watchFile = (path: string) => {
129-
if (!watching.has(path)) {
130-
watching.set(path, config.sys.watchFile(path, callback));
131-
}
132-
};
133-
155+
const watchSrcDirectory = async (config: d.Config, compilerCtx: d.CompilerCtx) => {
134156
const srcFiles = await compilerCtx.fs.readdir(config.srcDir, {
135157
recursive: true,
136158
excludeDirNames: ['.cache', '.git', '.github', '.stencil', '.vscode', 'node_modules'],
137-
excludeExtensions: ['.md', '.markdown', '.txt', '.spec.ts', '.spec.tsx', '.e2e.ts', '.e2e.tsx', '.gitignore', '.editorconfig'],
159+
excludeExtensions: [
160+
'.md',
161+
'.markdown',
162+
'.txt',
163+
'.spec.ts',
164+
'.spec.tsx',
165+
'.e2e.ts',
166+
'.e2e.tsx',
167+
'.gitignore',
168+
'.editorconfig',
169+
],
138170
});
139171

140-
srcFiles.filter(({ isFile }) => isFile).forEach(({ absPath }) => watchFile(absPath));
141-
142-
watching.set(
143-
config.srcDir,
144-
config.sys.watchDirectory(config.srcDir, (filename, kind) => {
145-
if (kind != null) {
146-
watchFile(filename);
147-
callback(filename, kind);
148-
}
149-
}),
150-
);
172+
srcFiles.filter(({ isFile }) => isFile).forEach(({ absPath }) => compilerCtx.addWatchFile(absPath));
151173

152-
return () => {
153-
watching.forEach(w => w.close());
154-
};
174+
compilerCtx.addWatchDir(config.srcDir, true);
155175
};
156176

157-
const watchOtherFiles = async (config: d.Config, compilerCtx: d.CompilerCtx) => {
177+
const watchRootFiles = async (config: d.Config, compilerCtx: d.CompilerCtx) => {
158178
// non-src files that cause a rebuild
159179
// mainly for root level config files, and getting an event when they change
160-
const onFileChange: d.CompilerFileWatcherCallback = (p, eventKind) => {
161-
const data: d.FsWatchResults = {
162-
dirsAdded: [],
163-
dirsDeleted: [],
164-
filesUpdated: [],
165-
filesAdded: [],
166-
filesDeleted: [],
167-
};
168-
169-
switch (eventKind) {
170-
case 'dirAdd':
171-
data.dirsAdded.push(p);
172-
break;
173-
case 'dirDelete':
174-
data.dirsDeleted.push(p);
175-
break;
176-
case 'fileAdd':
177-
data.filesAdded.push(p);
178-
break;
179-
case 'fileUpdate':
180-
data.filesUpdated.push(p);
181-
break;
182-
case 'fileDelete':
183-
data.filesDeleted.push(p);
184-
break;
185-
}
186-
187-
compilerCtx.events.emit('fsChange', data);
188-
};
189-
const watching = new Map();
190-
const watchFile = (path: string) => {
191-
if (!watching.has(path)) {
192-
watching.set(path, config.sys.watchFile(path, onFileChange));
193-
}
194-
};
195-
196180
const rootFiles = await compilerCtx.fs.readdir(config.rootDir, {
197181
recursive: false,
198182
excludeDirNames: ['.cache', '.git', '.github', '.stencil', '.vscode', 'node_modules'],
199183
});
200184

201-
rootFiles.filter(({ isFile }) => isFile).forEach(({ absPath }) => watchFile(absPath));
202-
203-
return () => {
204-
watching.forEach(w => w.close());
205-
};
185+
rootFiles.filter(({ isFile }) => isFile).forEach(({ absPath }) => compilerCtx.addWatchFile(absPath));
206186
};
207187

208188
const emitFsChange = (compilerCtx: d.CompilerCtx, buildCtx: BuildContext) => {
209-
if (buildCtx.dirsAdded.length > 0 || buildCtx.dirsDeleted.length > 0 || buildCtx.filesUpdated.length > 0 || buildCtx.filesAdded.length > 0 || buildCtx.filesDeleted.length > 0) {
189+
if (
190+
buildCtx.dirsAdded.length > 0 ||
191+
buildCtx.dirsDeleted.length > 0 ||
192+
buildCtx.filesUpdated.length > 0 ||
193+
buildCtx.filesAdded.length > 0 ||
194+
buildCtx.filesDeleted.length > 0
195+
) {
210196
compilerCtx.events.emit('fsChange', {
211197
dirsAdded: buildCtx.dirsAdded.slice(),
212198
dirsDeleted: buildCtx.dirsDeleted.slice(),
@@ -217,7 +203,12 @@ const emitFsChange = (compilerCtx: d.CompilerCtx, buildCtx: BuildContext) => {
217203
}
218204
};
219205

220-
const updateCompilerCtxCache = (config: d.Config, compilerCtx: d.CompilerCtx, path: string, kind: d.CompilerFileWatcherEvent) => {
206+
const updateCompilerCtxCache = (
207+
config: d.Config,
208+
compilerCtx: d.CompilerCtx,
209+
path: string,
210+
kind: d.CompilerFileWatcherEvent,
211+
) => {
221212
compilerCtx.fs.clearFileCache(path);
222213
compilerCtx.changedFiles.add(path);
223214

src/compiler/bundle/ext-transforms-plugin.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import { parseImportPath } from '../transformers/stencil-import-path';
77
import type { Plugin } from 'rollup';
88
import { runPluginTransformsEsmImports } from '../plugin/plugin';
99

10-
export const extTransformsPlugin = (config: d.Config, compilerCtx: d.CompilerCtx, buildCtx: d.BuildCtx, bundleOpts: BundleOptions): Plugin => {
10+
export const extTransformsPlugin = (
11+
config: d.Config,
12+
compilerCtx: d.CompilerCtx,
13+
buildCtx: d.BuildCtx,
14+
bundleOpts: BundleOptions,
15+
): Plugin => {
1116
return {
1217
name: 'extTransformsPlugin',
1318

@@ -67,6 +72,7 @@ export const extTransformsPlugin = (config: d.Config, compilerCtx: d.CompilerCtx
6772
// Track dependencies
6873
for (const dep of pluginTransforms.dependencies) {
6974
this.addWatchFile(dep);
75+
compilerCtx.addWatchFile(dep);
7076
}
7177

7278
buildCtx.diagnostics.push(...pluginTransforms.diagnostics);

0 commit comments

Comments
 (0)