Skip to content

Commit

Permalink
(refactor): Completely detached angular compiling logic from plugin
Browse files Browse the repository at this point in the history
- minimal logging
  • Loading branch information
SilverMira committed Jan 3, 2021
1 parent fdbe93f commit c04d38d
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 450 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
"execa": "^5.0.0"
},
"devDependencies": {
"@angular/compiler": "^11.0.5",
"@angular/compiler-cli": "^11.0.5",
"snowpack": "^2.18.5",
"typescript": "4.0"
Expand Down
13 changes: 2 additions & 11 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

186 changes: 22 additions & 164 deletions src/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,149 +16,14 @@ export interface CacheEntry {
content?: string;
}

export interface WatchCompilationResult extends ng.PerformCompilationResult {
export interface RecompileResult extends ng.PerformCompilationResult {
recompiledFiles: string[];
}

export type RecompileFunction = (
fileName: string,
src: string
) => WatchCompilationResult | null;

export type RecompileFunctionAsync = (
fileName: string,
src: string
) => Promise<WatchCompilationResult | null>;

export const compile = ({
rootNames,
compilerHost,
compilerOptions,
}: CompileArgs): ng.PerformCompilationResult => {
const compilationResult = ng.performCompilation({
rootNames,
host: compilerHost,
options: compilerOptions,
});
return compilationResult;
};

export const watchCompile = ({
rootNames,
compilerHost,
compilerOptions,
}: CompileArgs) => {
const compiledFiles = new Set<string>();
const fileCache = new Map<string, CacheEntry>();
const modifiedFile = new Set<string>();
let cachedProgram: ng.Program | undefined;

const getCacheEntry = (fileName: string) => {
fileName = path.normalize(fileName);
let entry = fileCache.get(fileName);
if (!entry) {
entry = {};
fileCache.set(fileName, entry);
}
return entry;
};

// Setup compilerHost to use cache
const oriWriteFile = compilerHost.writeFile;
compilerHost.writeFile = (
fileName,
data,
writeByteOrderMark,
onError,
sourceFiles
) => {
const srcRelativePath = path.relative(
path.resolve(compilerOptions.outDir!),
path.resolve(fileName)
);
compiledFiles.add(srcRelativePath);
return oriWriteFile(
fileName,
data,
writeByteOrderMark,
onError,
sourceFiles
);
};
const oriFileExists = compilerHost.fileExists;
compilerHost.fileExists = (fileName) => {
const cache = getCacheEntry(fileName);
if (cache.exists === null || cache.exists === undefined)
cache.exists = oriFileExists(fileName);
return cache.exists;
};
const oriGetSourceFile = compilerHost.getSourceFile;
compilerHost.getSourceFile = (fileName, languageVersion) => {
const cache = getCacheEntry(fileName);
if (!cache.sf) cache.sf = oriGetSourceFile(fileName, languageVersion);
return cache.sf;
};
const oriReadFile = compilerHost.readFile;
compilerHost.readFile = (fileName) => {
const cache = getCacheEntry(fileName);
if (!cache.content) cache.content = oriReadFile(fileName);
return cache.content;
};
// Read resource is a optional function,
// it has priority over readFile when loading resources (html/css),
// async file processing will require a custom performCompilation to run `program.loadNgStuctureAsync()`
const oriReadResource = compilerHost.readResource;
if (oriReadResource)
compilerHost.readResource = (fileName) => {
const cache = getCacheEntry(fileName);
if (!cache.content) cache.content = oriReadResource(fileName) as string;
return cache.content;
};

compilerHost.getModifiedResourceFiles = () => {
return modifiedFile;
};

// Do first compile
const firstCompilation = compile({
rootNames,
compilerHost,
compilerOptions,
});
cachedProgram = firstCompilation.program;

const recompile: RecompileFunction = (fileName: string, src: string) => {
// perhaps this function need debouncing like in perform_watch.ts
fileName = path.normalize(fileName);
fileCache.delete(fileName);
const compiledFilePath = path.relative(
path.resolve(src),
path.resolve(fileName)
);
if (!compiledFiles.has(compiledFilePath)) {
modifiedFile.add(fileName);
compiledFiles.clear();
const oldProgram = cachedProgram;
cachedProgram = undefined;
const recompileResult = ng.performCompilation({
rootNames,
host: compilerHost,
options: compilerOptions,
oldProgram,
});
cachedProgram = recompileResult.program;
modifiedFile.clear();
return {
program: recompileResult.program,
emitResult: recompileResult.emitResult,
recompiledFiles: [...compiledFiles],
diagnostics: recompileResult.diagnostics,
};
}
return null;
};
return { firstCompilation, recompile };
};
) => Promise<RecompileResult>;

/**
* Based on `@angular/compiler-cli.performCompilation()`
Expand Down Expand Up @@ -289,34 +154,27 @@ export const watchCompileAsync = async ({
// perhaps this function need debouncing like in perform_watch.ts
fileName = path.normalize(fileName);
fileCache.delete(fileName);
const compiledFilePath = path.relative(
path.resolve(src),
path.resolve(fileName)
modifiedFile.add(fileName);
compiledFiles.clear();
const oldProgram = cachedProgram;
cachedProgram = undefined;
const recompileResult = await performCompilationAsync(
{
rootNames,
compilerHost,
compilerOptions,
oldProgram,
},
false
);
if (!compiledFiles.has(compiledFilePath)) {
modifiedFile.add(fileName);
compiledFiles.clear();
const oldProgram = cachedProgram;
cachedProgram = undefined;
const recompileResult = await performCompilationAsync(
{
rootNames,
compilerHost,
compilerOptions,
oldProgram,
},
false
);
cachedProgram = recompileResult.program;
modifiedFile.clear();
return {
program: recompileResult.program,
emitResult: recompileResult.emitResult,
recompiledFiles: [...compiledFiles],
diagnostics: recompileResult.diagnostics,
};
}
return null;
cachedProgram = recompileResult.program;
modifiedFile.clear();
return {
program: recompileResult.program,
emitResult: recompileResult.emitResult,
recompiledFiles: [...compiledFiles],
diagnostics: recompileResult.diagnostics,
};
};
return { firstCompilation, recompile };
};
Loading

0 comments on commit c04d38d

Please sign in to comment.