Skip to content

Commit ab67988

Browse files
dgp1130AndrewKushnir
authored andcommitted
feat(platform-browser): resolve JIT resources in createApplication
Previously, `createApplication` didn't work with JIT components. This commit brings it closer to feature parity with `bootstrapApplication`.
1 parent 5af3372 commit ab67988

File tree

2 files changed

+72
-13
lines changed

2 files changed

+72
-13
lines changed

packages/platform-browser/src/browser.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export interface BootstrapContext {
124124
*
125125
* @publicApi
126126
*/
127-
export function bootstrapApplication(
127+
export async function bootstrapApplication(
128128
rootComponent: Type<unknown>,
129129
options?: ApplicationConfig,
130130
context?: BootstrapContext,
@@ -135,15 +135,8 @@ export function bootstrapApplication(
135135
...createProvidersConfig(options),
136136
};
137137

138-
// Attempt to resolve component resources before bootstrapping in JIT mode,
139-
// however don't interrupt the bootstrapping process.
140138
if ((typeof ngJitMode === 'undefined' || ngJitMode) && typeof fetch === 'function') {
141-
return resolveComponentResources(fetch)
142-
.catch((error) => {
143-
console.error(error);
144-
return Promise.resolve();
145-
})
146-
.then(() => internalCreateApplication(config));
139+
await resolveJitResources();
147140
}
148141

149142
return internalCreateApplication(config);
@@ -161,7 +154,11 @@ export function bootstrapApplication(
161154
*
162155
* @publicApi
163156
*/
164-
export function createApplication(options?: ApplicationConfig): Promise<ApplicationRef> {
157+
export async function createApplication(options?: ApplicationConfig): Promise<ApplicationRef> {
158+
if ((typeof ngJitMode === 'undefined' || ngJitMode) && typeof fetch === 'function') {
159+
await resolveJitResources();
160+
}
161+
165162
return internalCreateApplication(createProvidersConfig(options));
166163
}
167164

@@ -172,6 +169,17 @@ function createProvidersConfig(options?: ApplicationConfig) {
172169
};
173170
}
174171

172+
/** Attempt to resolve component resources before bootstrapping in JIT mode. */
173+
async function resolveJitResources(): Promise<void> {
174+
try {
175+
return await resolveComponentResources(fetch);
176+
} catch (error) {
177+
// Log, but don't block bootstrapping on error.
178+
// tslint:disable-next-line:no-console
179+
console.error(error);
180+
}
181+
}
182+
175183
/**
176184
* Returns a set of providers required to setup [Testability](api/core/Testability) for an
177185
* application bootstrapped using the `bootstrapApplication` function. The set of providers is

packages/platform-browser/test/browser/bootstrap_standalone_spec.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ import {
1919
ɵR3Injector as R3Injector,
2020
ɵNoopNgZone as NoopNgZone,
2121
APP_ID,
22+
signal,
2223
} from '@angular/core';
23-
import {withBody} from '@angular/private/testing';
24-
25-
import {bootstrapApplication, BrowserModule} from '../../src/browser';
24+
import {isNode, withBody} from '@angular/private/testing';
25+
import {bootstrapApplication, BrowserModule, createApplication} from '../../src/browser';
2626

2727
describe('bootstrapApplication for standalone components', () => {
2828
beforeEach(destroyPlatform);
@@ -271,3 +271,54 @@ describe('bootstrapApplication for standalone components', () => {
271271
});
272272
});
273273
});
274+
275+
describe('createApplication', () => {
276+
beforeEach(destroyPlatform);
277+
afterEach(destroyPlatform);
278+
279+
it(
280+
'creates an `ApplicationRef` which can bootstrap a component',
281+
withBody('<test-app></test-app>', async () => {
282+
@Component({
283+
selector: 'test-app',
284+
template: `Hello, {{ name() }}!`,
285+
})
286+
class TestComp {
287+
protected readonly name = signal('Dev');
288+
}
289+
290+
const appRef = await createApplication();
291+
appRef.bootstrap(TestComp);
292+
293+
expect(document.body.textContent.trim()).toBe('Hello, Dev!');
294+
}),
295+
);
296+
297+
it(
298+
'creates an `ApplicationRef` which can bootstrap a JIT component with an external resource',
299+
withBody('<test-app></test-app>', async () => {
300+
// Resolving resources only makes sense in the browser.
301+
if (isNode) {
302+
expect().nothing();
303+
return;
304+
}
305+
306+
const templateUrl = URL.createObjectURL(new Blob(['Hello, {{ name() }}!']));
307+
308+
@Component({
309+
selector: 'test-app',
310+
templateUrl,
311+
})
312+
class TestComp {
313+
protected readonly name = signal('Dev');
314+
}
315+
316+
const appRef = await createApplication();
317+
appRef.bootstrap(TestComp);
318+
319+
expect(document.body.textContent.trim()).toBe('Hello, Dev!');
320+
321+
URL.revokeObjectURL(templateUrl);
322+
}),
323+
);
324+
});

0 commit comments

Comments
 (0)