Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 97a6f2f

Browse files
committed
refactor(deep-linking): add support for ionic serve/watch builds
add support for ionic serve/watch builds
1 parent f537767 commit 97a6f2f

File tree

3 files changed

+63
-33
lines changed

3 files changed

+63
-33
lines changed

src/deep-linking.ts

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@ import { BuildContext, ChangedFile, DeepLinkConfigEntry } from './util/interface
77

88
import { convertDeepLinkConfigEntriesToString, getDeepLinkData, hasExistingDeepLinkConfig, updateAppNgModuleAndFactoryWithDeepLinkConfig } from './deep-linking/util';
99

10+
/*
11+
* We want to cache a local, in-memory copy of the App's main NgModule file content.
12+
* Each time we do a build, a new DeepLinkConfig is generated and inserted into the
13+
* app's main NgModule. By keeping a copy of the original and using it to determine
14+
* if the developer had an existing config, we will get an accurate answer where
15+
* as the cached version of the App's main NgModule content will basically always
16+
* have a generated deep likn config in it.
17+
*/
18+
let cachedUnmodifiedAppNgModuleFileContent: string = null;
1019

1120
export function deepLinking(context: BuildContext) {
12-
const logger = new Logger(`deep links`);
21+
const logger = new Logger(`deeplinks`);
1322
return deepLinkingWorker(context).then((deepLinkConfigEntries: DeepLinkConfigEntry[]) => {
1423
setParsedDeepLinkConfig(deepLinkConfigEntries);
1524
logger.finish();
@@ -23,31 +32,36 @@ export function deepLinking(context: BuildContext) {
2332

2433

2534
function deepLinkingWorker(context: BuildContext) {
35+
return deepLinkingWorkerImpl(context, null);
36+
}
37+
38+
function deepLinkingWorkerImpl(context: BuildContext, changedFiles: ChangedFile[]) {
2639
return Promise.resolve().then(() => {
2740
const appNgModulePath = getStringPropertyValue(Constants.ENV_APP_NG_MODULE_PATH);
2841
const appNgModuleFile = context.fileCache.get(appNgModulePath);
42+
if (!cachedUnmodifiedAppNgModuleFileContent) {
43+
cachedUnmodifiedAppNgModuleFileContent = appNgModuleFile.content;
44+
}
2945
const deepLinkConfigEntries = getDeepLinkData(appNgModulePath, context.fileCache, context.runAot);
30-
const hasExisting = hasExistingDeepLinkConfig(appNgModulePath, appNgModuleFile.content);
46+
const hasExisting = hasExistingDeepLinkConfig(appNgModulePath, cachedUnmodifiedAppNgModuleFileContent);
3147
if (!hasExisting) {
3248
// only update the app's main ngModule if there isn't an existing config
3349
const deepLinkString = convertDeepLinkConfigEntriesToString(deepLinkConfigEntries);
34-
updateAppNgModuleAndFactoryWithDeepLinkConfig(context, deepLinkString);
50+
updateAppNgModuleAndFactoryWithDeepLinkConfig(context, deepLinkString, changedFiles, context.runAot);
3551
}
3652
return deepLinkConfigEntries;
3753
});
3854
}
3955

40-
41-
4256
export function deepLinkingUpdate(changedFiles: ChangedFile[], context: BuildContext) {
43-
/*const appNgModuleChangedFiles = changedFiles.filter(changedFile => changedFile.filePath === process.env[Constants.ENV_APP_NG_MODULE_PATH]);
44-
if (appNgModuleChangedFiles.length) {
45-
const fileContent = context.fileCache.get(appNgModuleChangedFiles[0].filePath).content;
46-
const hydratedDeepLinkEntries = extractDeepLinkData(appNgModuleChangedFiles[0].filePath, fileContent, context.runAot);
47-
setParsedDeepLinkConfig(hydratedDeepLinkEntries);
48-
}
49-
return Promise.resolve();
50-
*/
51-
return Promise.resolve();
57+
// TODO, consider optimizing later
58+
const logger = new Logger('deeplinks update');
59+
return deepLinkingWorkerImpl(context, changedFiles).then((deepLinkConfigEntries: DeepLinkConfigEntry[]) => {
60+
setParsedDeepLinkConfig(deepLinkConfigEntries);
61+
logger.finish();
62+
}).catch((err: Error) => {
63+
const error = new BuildError(err.message);
64+
throw logger.fail(error);
65+
});
5266
}
5367

src/deep-linking/util.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Logger } from '../logger/logger';
1818
import * as Constants from '../util/constants';
1919
import { FileCache } from '../util/file-cache';
2020
import { changeExtension, getStringPropertyValue, replaceAll } from '../util/helpers';
21-
import { BuildContext, DeepLinkConfigEntry, DeepLinkDecoratorAndClass, DeepLinkPathInfo } from '../util/interfaces';
21+
import { BuildContext, ChangedFile, DeepLinkConfigEntry, DeepLinkDecoratorAndClass, DeepLinkPathInfo } from '../util/interfaces';
2222
import { appendAfter, getClassDeclarations, getTypescriptSourceFile, getNodeStringContent, replaceNode } from '../util/typescript-utils';
2323

2424
import { transpileTsString } from '../transpile';
@@ -299,41 +299,55 @@ export function convertDeepLinkEntryToJsObjectString(entry: DeepLinkConfigEntry)
299299
return `{ loadChildren: '${entry.userlandModulePath}${LOAD_CHILDREN_SEPARATOR}${entry.className}', name: '${entry.name}', segment: ${segmentString}, priority: '${entry.priority}', defaultHistory: [${defaultHistoryWithQuotes.join(', ')}] }`;
300300
}
301301

302-
export function updateAppNgModuleAndFactoryWithDeepLinkConfig(context: BuildContext, deepLinkString: string) {
302+
export function updateAppNgModuleAndFactoryWithDeepLinkConfig(context: BuildContext, deepLinkString: string, changedFiles: ChangedFile[], isAot: boolean) {
303303
const appNgModulePath = getStringPropertyValue(Constants.ENV_APP_NG_MODULE_PATH);
304-
const appNgModuleFactoryPath = changeExtension(appNgModulePath, '.ngfactory.ts');
305304
const appNgModuleFile = context.fileCache.get(appNgModulePath);
306-
const appNgModuleFactoryFile = context.fileCache.get(appNgModuleFactoryPath);
305+
307306
if (!appNgModuleFile) {
308307
throw new Error(`App NgModule ${appNgModulePath} not found in cache`);
309308
}
310-
if (!appNgModuleFactoryFile) {
311-
throw new Error(`App NgModule Factory ${appNgModuleFactoryPath} not found in cache`);
312-
}
313309

314310
const updatedAppNgModuleContent = getUpdatedAppNgModuleContentWithDeepLinkConfig(appNgModulePath, appNgModuleFile.content, deepLinkString);
315-
const updatedAppNgModuleFactoryContent = getUpdatedAppNgModuleFactoryContentWithDeepLinksConfig(appNgModuleFactoryFile.content, deepLinkString);
316311

317-
// update the typescript files in cache
318312
context.fileCache.set(appNgModulePath, { path: appNgModulePath, content: updatedAppNgModuleContent});
319-
context.fileCache.set(appNgModuleFactoryPath, { path: appNgModuleFactoryPath, content: updatedAppNgModuleFactoryContent});
320313

321-
// transpile the ts to js, and then update the cache
322314
const appNgModuleOutput = transpileTsString(context, appNgModulePath, updatedAppNgModuleContent);
323-
const appNgModuleFactoryOutput = transpileTsString(context, appNgModuleFactoryPath, updatedAppNgModuleFactoryContent);
324-
325315
const appNgModuleSourceMapPath = changeExtension(appNgModulePath, '.js.map');
326316
const appNgModulePathJsFile = changeExtension(appNgModulePath, '.js');
327317
context.fileCache.set(appNgModuleSourceMapPath, { path: appNgModuleSourceMapPath, content: appNgModuleOutput.sourceMapText});
328318
context.fileCache.set(appNgModulePathJsFile, { path: appNgModulePathJsFile, content: appNgModuleOutput.outputText});
329319

330-
const appNgModuleFactorySourceMapPath = changeExtension(appNgModuleFactoryPath, '.js.map');
331-
const appNgModuleFactoryPathJsFile = changeExtension(appNgModuleFactoryPath, '.js');
332-
context.fileCache.set(appNgModuleFactorySourceMapPath, { path: appNgModuleFactorySourceMapPath, content: appNgModuleFactoryOutput.sourceMapText});
333-
context.fileCache.set(appNgModuleFactoryPathJsFile, { path: appNgModuleFactoryPathJsFile, content: appNgModuleFactoryOutput.outputText});
320+
if (changedFiles) {
321+
changedFiles.push({
322+
event: 'change',
323+
filePath: appNgModulePath,
324+
ext: extname(appNgModulePath).toLowerCase()
325+
});
326+
}
334327

335-
const appNgModuleFileDan = context.fileCache.get(appNgModulePath);
336-
const appNgModuleFactoryFileDan = context.fileCache.get(appNgModuleFactoryPath);
328+
if (isAot) {
329+
const appNgModuleFactoryPath = changeExtension(appNgModulePath, '.ngfactory.ts');
330+
const appNgModuleFactoryFile = context.fileCache.get(appNgModuleFactoryPath);
331+
if (!appNgModuleFactoryFile) {
332+
throw new Error(`App NgModule Factory ${appNgModuleFactoryPath} not found in cache`);
333+
}
334+
const updatedAppNgModuleFactoryContent = getUpdatedAppNgModuleFactoryContentWithDeepLinksConfig(appNgModuleFactoryFile.content, deepLinkString);
335+
context.fileCache.set(appNgModuleFactoryPath, { path: appNgModuleFactoryPath, content: updatedAppNgModuleFactoryContent});
336+
const appNgModuleFactoryOutput = transpileTsString(context, appNgModuleFactoryPath, updatedAppNgModuleFactoryContent);
337+
338+
const appNgModuleFactorySourceMapPath = changeExtension(appNgModuleFactoryPath, '.js.map');
339+
const appNgModuleFactoryPathJsFile = changeExtension(appNgModuleFactoryPath, '.js');
340+
context.fileCache.set(appNgModuleFactorySourceMapPath, { path: appNgModuleFactorySourceMapPath, content: appNgModuleFactoryOutput.sourceMapText});
341+
context.fileCache.set(appNgModuleFactoryPathJsFile, { path: appNgModuleFactoryPathJsFile, content: appNgModuleFactoryOutput.outputText});
342+
343+
if (changedFiles) {
344+
changedFiles.push({
345+
event: 'change',
346+
filePath: appNgModuleFactoryPath,
347+
ext: extname(appNgModuleFactoryPath).toLowerCase()
348+
});
349+
}
350+
}
337351
}
338352

339353
export function getUpdatedAppNgModuleContentWithDeepLinkConfig(appNgModuleFilePath: string, appNgModuleFileContent: string, deepLinkStringContent: string) {

src/webpack/ionic-environment-plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { BuildContext , DeepLinkConfigEntry} from '../util/interfaces';
33
import { Logger } from '../logger/logger';
44
import { getInstance } from '../util/hybrid-file-system-factory';
55
import { createResolveDependenciesFromContextMap } from './util';
6+
import { WatchMemorySystem } from './watch-memory-system';
67

78
export class IonicEnvironmentPlugin {
89
constructor(private context: BuildContext) {
@@ -30,6 +31,7 @@ export class IonicEnvironmentPlugin {
3031
const hybridFileSystem = getInstance();
3132
hybridFileSystem.setFileSystem(compiler.inputFileSystem);
3233
compiler.inputFileSystem = hybridFileSystem;
34+
compiler.watchFileSystem = new WatchMemorySystem(this.context.fileCache);
3335

3436
// do a bunch of webpack specific stuff here, so cast to an any
3537
// populate the content of the file system with any virtual files

0 commit comments

Comments
 (0)