Skip to content

Commit

Permalink
fix(vite-plugin-angular): cache already resolved style and template U…
Browse files Browse the repository at this point in the history
…RLs (analogjs#566)
  • Loading branch information
arturovt authored and Villanuevand committed Sep 12, 2023
1 parent 8986362 commit 535df4a
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 41 deletions.
11 changes: 7 additions & 4 deletions packages/vite-plugin-angular/src/lib/angular-vite-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { createCompilerPlugin } from './compiler-plugin';
import {
hasStyleUrls,
hasTemplateUrl,
resolveStyleUrls,
resolveTemplateUrls,
StyleUrlsResolver,
TemplateUrlsResolver,
} from './component-resolvers';
import { augmentHostWithResources } from './host';
import { jitPlugin } from './angular-jit-plugin';
Expand Down Expand Up @@ -105,6 +105,9 @@ export function angular(options?: PluginOptions): Plugin[] {
let cssPlugin: Plugin | undefined;
let styleTransform: PluginContainer['transform'] | undefined;

const styleUrlsResolver = new StyleUrlsResolver();
const templateUrlsResolver = new TemplateUrlsResolver();

function angularPlugin(): Plugin {
const watchedFiles = new Set<string>();

Expand Down Expand Up @@ -262,11 +265,11 @@ export function angular(options?: PluginOptions): Plugin[] {
let styleUrls: string[] = [];

if (hasTemplateUrl(code)) {
templateUrls = resolveTemplateUrls(code, id);
templateUrls = templateUrlsResolver.resolve(code, id);
}

if (hasStyleUrls(code)) {
styleUrls = resolveStyleUrls(code, id);
styleUrls = styleUrlsResolver.resolve(code, id);
}

if (watchMode) {
Expand Down
22 changes: 14 additions & 8 deletions packages/vite-plugin-angular/src/lib/component-resolvers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { describe, it, expect } from 'vitest';

import {
hasTemplateUrl,
resolveStyleUrls,
resolveTemplateUrls,
StyleUrlsResolver,
TemplateUrlsResolver,
} from './component-resolvers';
import { normalizePath } from 'vite';
import { relative } from 'path';
Expand Down Expand Up @@ -49,7 +49,8 @@ describe('component-resolvers styleUrls', () => {
const actualPaths = [
'./app.component.css|/path/to/src/app.component.css',
];
const resolvedPaths = resolveStyleUrls(code, id);
const templateUrlsResolver = new TemplateUrlsResolver();
const resolvedPaths = templateUrlsResolver.resolve(code, id);

expect(thePathsAreEqual(resolvedPaths, actualPaths));
});
Expand All @@ -70,7 +71,8 @@ describe('component-resolvers styleUrls', () => {
'../styles.css|/path/to/styles.css',
];

const resolvedPaths = resolveStyleUrls(code, id);
const styleUrlsResolver = new StyleUrlsResolver();
const resolvedPaths = styleUrlsResolver.resolve(code, id);

expect(thePathsAreEqual(resolvedPaths, actualPaths));
});
Expand All @@ -92,7 +94,8 @@ describe('component-resolvers styleUrls', () => {
'../styles.css|/path/to/styles.css',
];

const resolvedPaths = resolveStyleUrls(code, id);
const styleUrlsResolver = new StyleUrlsResolver();
const resolvedPaths = styleUrlsResolver.resolve(code, id);

expect(thePathsAreEqual(resolvedPaths, actualPaths));
});
Expand All @@ -112,7 +115,8 @@ describe('component-resolvers styleUrls', () => {

const actualUrl =
'./app.component.html|/path/to/src/app.component.html';
const resolvedTemplateUrls = resolveTemplateUrls(code, id);
const templateUrlsResolver = new TemplateUrlsResolver();
const resolvedTemplateUrls = templateUrlsResolver.resolve(code, id);

expect(hasTemplateUrl(code)).toBeTruthy();
expect(thePathsAreEqual(resolvedTemplateUrls, [actualUrl]));
Expand All @@ -128,7 +132,8 @@ describe('component-resolvers styleUrls', () => {

const actualUrl =
'./app.component.html|/path/to/src/app.component.html';
const resolvedTemplateUrls = resolveTemplateUrls(code, id);
const templateUrlsResolver = new TemplateUrlsResolver();
const resolvedTemplateUrls = templateUrlsResolver.resolve(code, id);

expect(hasTemplateUrl(code)).toBeTruthy();
expect(thePathsAreEqual(resolvedTemplateUrls, [actualUrl]));
Expand All @@ -151,7 +156,8 @@ describe('component-resolvers styleUrls', () => {
'./app.component.html|/path/to/src/app.component.html';
const actualUrl2 =
'./app1.component.html|/path/to/src/app1.component.html';
const resolvedTemplateUrls = resolveTemplateUrls(code, id);
const templateUrlsResolver = new TemplateUrlsResolver();
const resolvedTemplateUrls = templateUrlsResolver.resolve(code, id);

expect(hasTemplateUrl(code)).toBeTruthy();
expect(
Expand Down
99 changes: 70 additions & 29 deletions packages/vite-plugin-angular/src/lib/component-resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,84 @@ export function hasStyleUrls(code: string) {
return styleUrlsRE.test(code);
}

export function resolveStyleUrls(code: string, id: string) {
const styleUrlsGroup = styleUrlsRE.exec(code);

if (Array.isArray(styleUrlsGroup) && styleUrlsGroup[0]) {
const styleUrls = styleUrlsGroup[0].replace(
/(styleUrls|\:|\s|\[|\]|"|')/g,
''
);
const styleUrlPaths = styleUrls?.split(',') || [];

return styleUrlPaths.map((styleUrlPath) => {
return `${styleUrlPath}|${resolve(dirname(id), styleUrlPath)}`;
});
}
interface StyleUrlsCacheEntry {
code: string;
styleUrls: string[];
}

export class StyleUrlsResolver {
// These resolvers may be called multiple times during the same
// compilation for the same files. Caching is required because these
// resolvers use synchronous system calls to the filesystem, which can
// degrade performance when running compilations for multiple files.
private readonly styleUrlsCache = new Map<string, StyleUrlsCacheEntry>();

resolve(code: string, id: string): string[] {
const entry = this.styleUrlsCache.get(id);
if (entry?.code === code) {
return entry.styleUrls;
}

const styleUrlsGroup = styleUrlsRE.exec(code);

if (Array.isArray(styleUrlsGroup) && styleUrlsGroup[0]) {
const styleUrls = styleUrlsGroup[0].replace(
/(styleUrls|\:|\s|\[|\]|"|')/g,
''
);
const styleUrlPaths = styleUrls?.split(',') || [];

const newEntry = {
code,
styleUrls: styleUrlPaths.map((styleUrlPath) => {
return `${styleUrlPath}|${resolve(dirname(id), styleUrlPath)}`;
}),
};

return [];
this.styleUrlsCache.set(id, newEntry);
return newEntry.styleUrls;
}

return [];
}
}

export function hasTemplateUrl(code: string) {
return code.includes('templateUrl:');
}

export function resolveTemplateUrls(code: string, id: string) {
const templateUrlGroup = Array.from(code.matchAll(templateUrlRE));
const templateUrlPaths: string[] = [];
interface TemplateUrlsCacheEntry {
code: string;
templateUrlPaths: string[];
}

if (Array.isArray(templateUrlGroup)) {
templateUrlGroup.forEach((trg) => {
const resolvedTemplatePath = trg[1].replace(
/templateUrl|\s|'|"|\:|,/g,
''
);
const templateUrlPath = resolve(dirname(id), resolvedTemplatePath);
export class TemplateUrlsResolver {
private readonly templateUrlsCache = new Map<
string,
TemplateUrlsCacheEntry
>();

templateUrlPaths.push(`${resolvedTemplatePath}|${templateUrlPath}`);
});
}
resolve(code: string, id: string): string[] {
const entry = this.templateUrlsCache.get(id);
if (entry?.code === code) {
return entry.templateUrlPaths;
}

const templateUrlGroup = Array.from(code.matchAll(templateUrlRE));
const templateUrlPaths: string[] = [];

return templateUrlPaths;
if (Array.isArray(templateUrlGroup)) {
templateUrlGroup.forEach((trg) => {
const resolvedTemplatePath = trg[1].replace(
/templateUrl|\s|'|"|\:|,/g,
''
);
const templateUrlPath = resolve(dirname(id), resolvedTemplatePath);
templateUrlPaths.push(`${resolvedTemplatePath}|${templateUrlPath}`);
});
}

this.templateUrlsCache.set(id, { code, templateUrlPaths });
return templateUrlPaths;
}
}

0 comments on commit 535df4a

Please sign in to comment.