In Angular's @Component decorator, how do template and templateUrl differ from styles, styleUrl and styleUrls, and what rules does the compiler enforce?
answer
- inline string or file path
- exactly one template
- styleUrl vs styleUrls conflict
- files inlined at build time
basics
~20 stemplate holds an inline template and templateUrl points to an HTML file; styles holds inline CSS while styleUrl or styleUrls point to stylesheet files. The compiler requires one template, rejects styleUrl with styleUrls, and inlines files at build time.
solid answer
~40 sA component needs exactly one template: `template` as an inline string or `templateUrl` as a path relative to the component file; with neither, the compiler reports that the component is missing a template. Styles are optional: `styles` takes a string or an array, `styleUrl` one file and `styleUrls` several, and using both `styleUrl` and `styleUrls` is a compile error. The single-string `styles` and `styleUrl` forms arrived in v17. With AOT the compiler reads the files at build time and compiles them into the component definition, so the browser never fetches the HTML or CSS separately and the choice is about readability and editor support, not speed.
code
ts · 15 linesimport { Component } from '@angular/core';
@Component({
selector: 'app-badge',
template: `<span class="badge"><ng-content /></span>`,
styles: `.badge { padding: 0 4px; }`,
})
export class Badge {}
@Component({
selector: 'app-invoice-table',
templateUrl: './invoice-table.html',
styleUrl: './invoice-table.css',
})
export class InvoiceTable {}go deeper
Know the two template fields and three style fields, that exactly one template is required, and that paths are relative to the component file.
Explain that AOT inlines external resources at build time, so the inline-versus-file choice has no runtime cost, and name the compiler errors.
Set a project convention for inline versus external resources and clean up legacy metadata such as moduleId during upgrades.
Consider how file layout conventions affect review, tooling and code ownership across teams rather than treating them as a performance lever.
## Two ways to supply a template Every Angular component needs exactly one template, supplied through one of two `@Component` fields: - **`template`** — the template as an inline string, usually a TypeScript template literal so it can span lines. - **`templateUrl`** — a path to a separate `.html` file, **relative to the component's own file**. If a component has neither, the compiler stops with *@Component is missing a template. Add either a `template` or `templateUrl`*. The documentation for each field says not to supply the other, so pick one per component. ## Three ways to supply styles Styles are optional, and there are three fields: | Field | Type | Typical use | |---|---|---| | `styles` | a string, or an array of strings | short inline CSS | | `styleUrl` | one path | a single stylesheet file | | `styleUrls` | an array of paths | several stylesheet files | Rules the compiler enforces: 1. `styleUrl` and `styleUrls` cannot both be present: *@Component cannot define both `styleUrl` and `styleUrls`*. 2. `styleUrl` must be a string; `styleUrls` must be an array of strings. 3. Paths are resolved relative to the component file; a path that cannot be resolved is a build error rather than a runtime 404. `styles` accepting a single string and the singular `styleUrl` both arrived in **v17**; before that you wrote `styles: ['...']` and `styleUrls: ['...']` even for one entry. Both older forms still work. `styles` and a style file can be combined in one component; the CSS from both is applied. ## Build time, not request time A common misconception is that `templateUrl` makes the browser fetch the HTML file when the component first renders. With the AOT compiler that current Angular builds use, the compiler reads the file at build time and compiles it into the component's generated definition, the same as an inline template. The same happens to stylesheets. So: - there is **no runtime performance difference** between inline and external templates or styles; - a typo in a path fails the build, not the page; - the choice is about **readability and tooling**, not speed. Very old code sometimes carried `moduleId: module.id` so relative URLs would resolve. That field was deprecated long ago and **removed in v21**; the compiler resolves relative paths itself. ## How to choose Inline (`template` / `styles`) suits small components: a presentational button, a badge, a component in a test file. Everything lives in one file, which is easy to read in review. External files (`templateUrl` / `styleUrl`) suit larger components: - editors give full HTML and CSS language support, formatting and linting; - the file can be written in a preprocessor language such as SCSS when the build is configured for it; - the diff of a template change is not mixed with TypeScript. Teams usually pick a convention per project. Angular supports hot module replacement for both inline and file-based templates and styles in current CLI builds, so that is not a deciding factor either. ## Example of both styles side by side ```ts import { Component } from '@angular/core'; // Inline template and styles. @Component({ selector: 'app-badge', template: `<span class="badge"><ng-content /></span>`, styles: `.badge { padding: 0 4px; }`, }) export class Badge {} // External files, relative to this .ts file. @Component({ selector: 'app-invoice-table', templateUrl: './invoice-table.html', styleUrl: './invoice-table.css', }) export class InvoiceTable {} ``` ## What these fields do not decide The style fields say *where the CSS comes from*. How far that CSS reaches, that is whether it is scoped to the component's own template or leaks globally, is decided by the component's **view encapsulation** setting, a separate subject. By default the styles apply only to elements in that component's template.
- Does templateUrl make the app slower because the browser fetches the file?No. The AOT compiler reads the HTML file at build time and compiles it into the component's generated code, exactly as it does an inline template. Nothing is fetched at runtime, and a wrong path fails the build instead of the page.
- What does moduleId: module.id do in an old component?It once helped resolve relative `templateUrl` and `styleUrls` paths in some module setups. The compiler has resolved paths relative to the component file for years, the field was deprecated, and it was removed from component metadata in v21, so it should be deleted during an upgrade.
saying these in an interview costs you the question
- templateUrl makes the browser download the template the first time it renders.
- A component can have both styleUrl and styleUrls.
- Inline templates render faster than external template files.
- A component without a template compiles and renders an empty host.
- templateUrl paths are relative to the project root, not the component file.