Integrating tshtml with Angular 21
January 22, 2026 · View on GitHub
This guide explains how to modify a standard Angular 21 application to use tshtml and tshtml-loader for TypeScript-first HTML templates.
What is tshtml?
tshtml is a TypeScript-first way to author Angular templates.
In Angular projects, .tshtml files are executed at build time (webpack + tshtml-loader) to produce a template string. That output typically contains Angular template syntax (bindings and directives), which Angular still evaluates at runtime.
In Angular projects, .tshtml typically emits Angular template syntax (bindings and directives) rather than rendering runtime data.
Key Point: TypeScript runs during compilation to generate the template string; Angular bindings still run at runtime.
Why Use tshtml with Angular?
tshtml solves key Angular limitations:
- Template Inheritance - Angular components inherit behavior but not templates. tshtml enables template inheritance through standard OOP class patterns.
- Reusable Markup Helpers - Build complex HTML structures with Angular directives programmatically.
- Lightweight Components - Replace components that only provide markup with faster build-time templates.
See detailed examples and use cases →
Prerequisites
- Node.js: 18+ recommended
- npm: 8+
- Angular CLI: 21.x
- Existing Angular 21 project or ability to create one with
ng new
Step 1: Install Dependencies
In your Angular project root, install the required packages:
npm install tshtml tshtml-loader
npm install --save-dev @angular-builders/custom-webpack
What these packages do:
tshtml: Core library providing thehtmltagged template and build-time template renderingtshtml-loader: Webpack loader that processes.tshtmlfiles during the build@angular-builders/custom-webpack: Allows Angular CLI to use custom webpack configurations
Note:
@angular-devkit/build-angular(the default Angular build system) is already included in Angular 21.
Step 2: Create Custom Webpack Configuration
Create a file named angular.webpack.js in your project root (same directory as angular.json):
// angular.webpack.js
module.exports = (config) => {
config.module.rules.push({
test: /\.tshtml($|\?)/,
use: ['tshtml-loader'],
enforce: 'pre'
});
return config;
};
Important details:
test: /\.tshtml($|\?)/: Matches both.tshtmlfiles and.tshtml?ngResource(with query parameters that Angular 21 appends)use: ['tshtml-loader']: Specifies the loader to useenforce: 'pre': Ensures the loader runs before other loaders (critical for proper processing)
Step 3: Update angular.json
Modify your angular.json to use the custom webpack configuration:
Find the build section (typically under projects > [your-app] > architect > build):
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "angular.webpack.js"
},
// ... rest of build options
}
}
Before (default Angular 21):
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
// ...
}
}
After (with custom webpack):
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "angular.webpack.js"
},
// Keep all existing options...
}
}
Also update the serve section if present:
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"customWebpackConfig": {
"path": "angular.webpack.js"
},
// ... rest of serve options
}
}
Step 4: Update tsconfig.json
Ensure your tsconfig.json has the correct module resolution settings:
{
"compilerOptions": {
"moduleResolution": "node",
// ... other options
}
}
Note: Most Angular 21 projects already include this. If your build fails with module resolution errors, add
"moduleResolution": "node"tocompilerOptions.
Step 5: Create Your First tshtml Template
Create a .tshtml file in your component directory:
// app.component.tshtml
import { html } from 'tshtml';
export default html`
<div class="container">
<h1>Welcome to tshtml!</h1>
<p>This template is authored in TypeScript but rendered by Angular.</p>
<p>Runtime (Angular binding): {{ now }}</p>
<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>
</div>
`;
Step 6: Reference tshtml in Your Component
Update your Angular component to use the tshtml template:
// app.component.ts
import { Component } from '@angular/core';
import template from './app.component.tshtml';
@Component({
selector: 'app-root',
template: template,
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'My App';
now = new Date().toISOString();
items = ['TypeScript-authored templates', 'Angular bindings', 'Template composition'];
}
Or using templateUrl:
@Component({
selector: 'app-root',
templateUrl: './app.component.tshtml',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'My App';
now = new Date().toISOString();
}
Note: Both approaches work. The loader processes both
templateimports andtemplateUrlreferences.
Step 7: Build and Run
Start the development server:
ng serve
# or
npm start
Your application will compile with tshtml support. Visit http://localhost:4200 to see your app.
Advanced: Template Composition
tshtml allows you to compose templates programmatically at build time.
Prefer emitting Angular directives (e.g. *ngFor) when the data is only available at runtime.
// shared-header.tshtml
import { html } from 'tshtml';
export default html`
<header>
<h1>My Application</h1>
</header>
`;
// app.component.tshtml
import { html } from 'tshtml';
import header from './shared-header.tshtml';
export default html`
<div>
${header}
<main>
<ul>
<li *ngFor="let item of items">{{ item }}</li>
</ul>
</main>
</div>
`;
Note: This emits Angular template code. At runtime, Angular will render items (a component field) via *ngFor.
Build-time HTML generation (advanced)
tshtml can also be used to generate static HTML at build time (for example: injecting build metadata, producing an exported .html file, or pre-rendering known-at-build-time content).
However, the Angular integration path in this repo focuses on emitting Angular template syntax. If you want full static-site/pre-render pipelines, you will typically need additional tooling and conventions beyond the basic Angular + loader setup.
Troubleshooting
"Cannot find module 'tshtml'"
- Ensure
tshtmlis installed:npm install tshtml - Check that
tsconfig.jsonhas"moduleResolution": "node"
Blank page or template not rendering
- Verify
angular.webpack.jsexists and the webpack rule is correct - Check that
angular.jsonuses@angular-builders/custom-webpack:browser - Ensure the webpack rule regex includes
($|\?)to match query parameters
"tshtml-loader not applied"
- Confirm
angular.webpack.jshasenforce: 'pre'in the rule - Verify the file path in
customWebpackConfig.pathis correct - Check webpack output for module processing (look for
.tshtmlfiles being processed)
Build performance slow
- Initial builds may be slower when using custom webpack; subsequent hot reloads are typically 2-5 seconds
Minimal Configuration Checklist
You've successfully integrated tshtml when:
- ✅
tshtmlandtshtml-loaderare inpackage.jsondependencies - ✅
@angular-builders/custom-webpackis in devDependencies - ✅
angular.webpack.jsexists with the webpack rule (7 lines) - ✅
angular.jsonuses@angular-builders/custom-webpack:browserbuilder - ✅
angular.jsonspecifiescustomWebpackConfig.path - ✅
tsconfig.jsonhas"moduleResolution": "node" - ✅ First
.tshtmlfile created and referenced in a component - ✅ Build succeeds:
ng buildorng serve
Performance Notes
- Build time: Templates are processed during webpack compilation
- First build: ~10-15 seconds
- Hot reloads: ~2-5 seconds
- Runtime performance: Zero overhead
- Templates are pre-rendered to static HTML at build time
- No template evaluation or processing happens at runtime
- Identical performance to hand-written HTML templates
- Bundle size: Minimal impact
- tshtml-loader runs only at build time and is not included in the bundle
- Only the generated HTML is included in your application
- The tshtml runtime API is not needed unless you use rendering functions at runtime (rare)
Next Steps
- Read the User Guide for advanced template features
- Check API Documentation for complete tshtml API
- See ../samples/tshtml-integration-guide for a working Angular 21 + tshtml example
Support
For issues or questions:
- Check the User Guide
- Review the
samples/directory for working examples - Open an issue on GitHub with your configuration and error messages