Modern Build Tools
Modern build tool configuration for Aurelia 2, featuring Vite, Webpack, and Parcel with official plugins and optimal development experience.
Aurelia 2 provides official support for modern build tools that offer fast development servers, optimized builds, and excellent developer experience. Choose the tool that best fits your project needs and team preferences.
Quick Start Recommendations
🚀 New Projects: Use Vite for fastest development and modern features
🏢 Enterprise/Existing: Use Webpack for maximum configurability and ecosystem
⚡ Simple Projects: Use Parcel for zero-config builds
Vite (Recommended)
Vite provides lightning-fast development with instant hot module replacement and optimized production builds. Recommended for new projects.
Why Vite?
⚡ Instant server start and HMR
🎯 Modern ES modules in development
📦 Optimized Rollup builds for production
🔧 Minimal configuration required
Installation
npm install -D @aurelia/vite-plugin vite
Configuration
Create vite.config.js
:
import { defineConfig } from 'vite';
import aurelia from '@aurelia/vite-plugin';
export default defineConfig({
plugins: [aurelia()],
server: {
port: 9000, // Optional: custom dev server port
open: true // Optional: auto-open browser
},
build: {
target: 'es2020', // Modern browser support
sourcemap: true // Source maps for production debugging
}
});
TypeScript Support
For TypeScript projects, add this type declaration file:
src/html.d.ts
(auto-generated by Aurelia CLI):
declare module '*.html' {
import { IContainer } from '@aurelia/kernel';
import { BindableDefinition } from '@aurelia/runtime';
export const name: string;
export const template: string;
export default template;
export const dependencies: string[];
export const containerless: boolean | undefined;
export const bindables: Record<string, BindableDefinition>;
export const shadowOptions: { mode: 'open' | 'closed'} | undefined;
export function register(container: IContainer);
}
Advanced Vite Configuration
import { defineConfig } from 'vite';
import aurelia from '@aurelia/vite-plugin';
export default defineConfig({
plugins: [
aurelia({
useDev: true, // Force dev bundles (useful for debugging)
})
],
resolve: {
alias: {
'@': '/src', // Path aliasing
}
},
css: {
modules: {
localsConvention: 'camelCase' // CSS Modules support
}
}
});
Webpack
Webpack offers maximum configurability and is well-suited for complex applications with specific build requirements.
Installation
npm install -D webpack webpack-cli webpack-dev-server
npm install -D @aurelia/webpack-loader ts-loader
Basic Configuration
Create webpack.config.js
:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/main.ts',
resolve: {
extensions: ['.ts', '.js', '.html'],
modules: [path.resolve(__dirname, 'src'), 'node_modules']
},
module: {
rules: [
// TypeScript files
{
test: /\.ts$/i,
use: ['ts-loader', '@aurelia/webpack-loader'],
exclude: /node_modules/
},
// HTML templates
{
test: /\.html$/i,
use: '@aurelia/webpack-loader',
exclude: /node_modules/
},
// CSS files
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
})
],
devServer: {
port: 9000,
historyApiFallback: true, // SPA routing support
open: true
}
};
Production Configuration
Create webpack.prod.js
for optimized builds:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
module.exports = {
mode: 'production',
entry: './src/main.ts',
resolve: {
extensions: ['.ts', '.js', '.html'],
modules: [path.resolve(__dirname, 'src'), 'node_modules']
},
module: {
rules: [
{
test: /\.ts$/i,
use: ['ts-loader', '@aurelia/webpack-loader'],
exclude: /node_modules/
},
{
test: /\.html$/i,
use: {
loader: '@aurelia/webpack-loader',
options: {
defaultShadowOptions: { mode: 'open' }, // Optional: Shadow DOM
useCSSModule: false // Optional: CSS Modules
}
},
exclude: /node_modules/
}
]
},
optimization: {
splitChunks: {
chunks: 'all'
}
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
minify: true
}),
// Uncomment to analyze bundle size
// new BundleAnalyzerPlugin()
]
};
Parcel
Parcel offers zero-configuration bundling with excellent performance and modern features out of the box.
Installation
npm install -D @aurelia/parcel-transformer parcel
Configuration
Create .parcelrc
:
{
"extends": "@parcel/config-default",
"transformers": {
"*.ts": ["@aurelia/parcel-transformer", "..."],
"*.html": ["@aurelia/parcel-transformer", "..."]
}
}
Optional Package.json Configuration
Add Aurelia-specific options to package.json
:
{
"aurelia": {
"defaultShadowOptions": { "mode": "open" },
"useCSSModule": false
},
"scripts": {
"dev": "parcel index.html",
"build": "parcel build index.html"
}
}
TypeScript Support
Add the same html.d.ts
file as shown in the Vite section.
Tool Comparison
Development Speed
⚡ Fastest
🟡 Moderate
⚡ Fast
Production Builds
🎯 Excellent
🎯 Excellent
🎯 Good
Configuration
🟢 Minimal
🔴 Complex
🟢 Zero-config
Ecosystem
🟡 Growing
🎯 Mature
🟡 Good
Hot Reload
⚡ Instant
🟡 Good
⚡ Fast
Bundle Analysis
🟢 Built-in
🎯 Excellent
🟡 Basic
Learning Curve
🟢 Easy
🔴 Steep
🟢 Easy
Common Development Patterns
Environment Variables
Vite:
// vite.config.js
export default defineConfig({
define: {
__DEV__: JSON.stringify(process.env.NODE_ENV === 'development')
}
});
Webpack:
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
]
};
CSS Processing
Vite with PostCSS:
// vite.config.js
export default defineConfig({
css: {
postcss: {
plugins: [
require('autoprefixer'),
require('cssnano')
]
}
}
});
Webpack with PostCSS:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
}
]
}
};
Asset Handling
All bundlers automatically handle common assets:
// Import images, fonts, etc.
import logo from './assets/logo.svg';
import styles from './component.module.css';
// Use in templates
export class MyComponent {
logoUrl = logo;
styles = styles;
}
Performance Optimization
Bundle Splitting
Vite:
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['@aurelia/kernel', '@aurelia/runtime'],
ui: ['./src/components/index']
}
}
}
}
});
Webpack:
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};
Tree Shaking
All modern bundlers automatically tree-shake unused code. Ensure your imports are ES module compatible:
// ✅ Good - allows tree shaking
import { DI } from '@aurelia/kernel';
// ❌ Avoid - imports entire module
import * as Aurelia from 'aurelia';
Migration Between Tools
From Create React App to Vite
Install Vite and Aurelia plugin
Move
public/index.html
to project rootUpdate imports to use
/src
instead of relative pathsReplace
react-scripts
commands with Vite commands
From Webpack to Vite
Replace webpack configs with
vite.config.js
Update dev scripts to use
vite
instead ofwebpack-dev-server
Convert webpack-specific features to Vite equivalents
Test that all dynamic imports still work
Troubleshooting
Common Issues
Vite: "Failed to resolve import"
// Add to vite.config.js
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
});
Webpack: "Module not found"
// Add to webpack.config.js
module.exports = {
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules']
}
};
Parcel: "Cannot resolve dependency"
// Add to package.json
{
"alias": {
"@/*": "./src/*"
}
}
Development vs Production Differences
Development: Use source maps, hot reload, and unminified code
Production: Enable minification, tree shaking, and bundle splitting
Testing: Consider using the same bundler for tests to catch bundler-specific issues
Next Steps
Choose your preferred build tool and start building amazing Aurelia applications! const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = function(env, { mode }) { const production = mode === 'production';
return { target: 'web', mode: production ? 'production' : 'development', devtool: production ? 'source-map' : 'eval-cheap-source-map', entry: { app: './src/main.ts' }, output: { path: path.resolve(__dirname, 'dist'), filename: production ? '[name].[contenthash].bundle.js' : '[name].bundle.js' }, resolve: { extensions: ['.ts', '.js'], modules: [path.resolve(__dirname, 'src'), 'node_modules'] }, devServer: { historyApiFallback: true, open: !process.env.CI, port: 9000 }, module: { rules: [ // Asset loaders { test: /.(png|gif|jpg|cur)$/i, loader: 'url-loader', options: { limit: 8192 } }, { test: /.woff2(?v=[0-9].[0-9].[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff2' } }, { test: /.woff(?v=[0-9].[0-9].[0-9])?$/i, loader: 'url-loader', options: { limit: 10000, mimetype: 'application/font-woff' } }, { test: /.(ttf|eot|svg|otf)(?v=[0-9].[0-9].[0-9])?$/i, loader: 'file-loader' },
// CSS handling
{ test: /\.css$/i, use: ['style-loader', 'css-loader'] },
// TypeScript + Aurelia loader
{
test: /\.ts$/i,
use: ['ts-loader', '@aurelia/webpack-loader'],
exclude: /node_modules/
},
// Aurelia HTML templates
{
test: /\.html$/i,
use: '@aurelia/webpack-loader',
exclude: /node_modules/
}
]
},
plugins: [
new HtmlWebpackPlugin({ template: 'index.html' })
]
}; };
### Advanced Configuration Options
#### Development Aliases
For development, you can alias Aurelia packages to their development builds for better debugging:
```js
// In resolve.alias section
alias: {
...[
'aurelia',
'fetch-client',
'kernel',
'metadata',
'platform',
'platform-browser',
'route-recognizer',
'router',
'router',
'runtime',
'runtime-html',
'testing',
'state',
'ui-virtualization'
].reduce((map, pkg) => {
const name = pkg === 'aurelia' ? pkg : `@aurelia/${pkg}`;
map[name] = path.resolve(__dirname, 'node_modules', name, 'dist/esm/index.dev.mjs');
return map;
}, {})
}
Hot Module Replacement (HMR)
To enable HMR for Aurelia components:
// In devServer
devServer: {
hot: true,
historyApiFallback: true,
port: 9000
},
// In module rules for TypeScript
{
test: /\.ts$/i,
use: [
'ts-loader',
{
loader: '@aurelia/webpack-loader',
options: {
hmr: true // Enable HMR for Aurelia
}
}
],
exclude: /node_modules/
}
TypeScript Type Checking
For enhanced TypeScript support with template type checking:
{
test: /\.ts$/i,
use: [
'ts-loader',
{
loader: '@aurelia/webpack-loader',
options: {
experimentalTemplateTypeCheck: true
}
}
],
exclude: /node_modules/
}
Production Optimizations
Minification: Webpack 5+ includes Terser plugin by default for production builds
Code Splitting: Configure
optimization.splitChunks
for better cachingSource Maps: Use
'source-map'
for production debuggingContent Hashing: Use
[contenthash]
in filenames for long-term caching
Vite
Vite is a fast, modern bundler (and dev server) that works excellently with Aurelia. Its plugin system provides quick project startup, HMR (Hot Module Replacement), and speedy builds.
Installing
npm install --save-dev @aurelia/vite-plugin
Basic Usage
In vite.config.js
:
import { defineConfig } from 'vite';
import aurelia from '@aurelia/vite-plugin';
export default defineConfig({
plugins: [aurelia()],
});
TypeScript Support
For TypeScript apps, add this declaration file to your project (usually generated by the Aurelia CLI):
html.d.ts
declare module '*.html' {
import { IContainer } from '@aurelia/kernel';
import { BindableDefinition } from '@aurelia/runtime';
export const name: string;
export const template: string;
export default template;
export const dependencies: string[];
export const containerless: boolean | undefined;
export const bindables: Record<string, BindableDefinition>;
export const shadowOptions: { mode: 'open' | 'closed'} | undefined;
export function register(container: IContainer);
}
Plugin Configuration Options
The Aurelia Vite plugin accepts several configuration options:
import { defineConfig } from 'vite';
import aurelia from '@aurelia/vite-plugin';
export default defineConfig({
plugins: [
aurelia({
// Always use development bundles
useDev: true,
// File inclusion/exclusion patterns
include: 'src/**/*.{ts,js,html}',
exclude: 'node_modules/**',
// Plugin execution order
pre: true,
// Enable/disable conventions
enableConventions: true,
// HMR configuration
hmr: true
})
]
});
Development Configuration
By default, the Aurelia Vite plugin automatically uses development bundles when in development mode:
export default defineConfig({
plugins: [
aurelia({
useDev: true // Force development bundles regardless of mode
})
]
});
Production & Code Splitting
Vite automatically optimizes for production. You can customize chunk splitting:
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor': ['aurelia'],
'router': ['@aurelia/router-direct', '@aurelia/router']
}
}
}
},
plugins: [aurelia()]
});
Source Maps and Debugging
export default defineConfig({
build: {
sourcemap: true // Enable source maps in production
},
plugins: [aurelia()]
});
Parcel
Parcel is a zero-configuration bundler that works well with Aurelia 2 through the official transformer.
Installing
npm install --save-dev @aurelia/parcel-transformer
npm install --save-dev @parcel/transformer-typescript-tsc # For TypeScript projects
Configuration
Create a .parcelrc
file in your project root:
{
"extends": "@parcel/config-default",
"transformers": {
"*.ts": ["@aurelia/parcel-transformer", "@parcel/transformer-typescript-tsc"],
"*.html": ["@aurelia/parcel-transformer", "..."]
}
}
For JavaScript projects:
{
"extends": "@parcel/config-default",
"transformers": {
"*.js": ["@aurelia/parcel-transformer", "..."],
"*.html": ["@aurelia/parcel-transformer", "..."]
}
}
Package.json Configuration
You can configure Aurelia-specific options in your package.json
:
{
"aurelia": {
"hmr": true,
"defaultShadowOptions": { "mode": "open" },
"useCSSModule": false
}
}
TypeScript Support
For TypeScript projects, add the same html.d.ts
declaration file mentioned in the Vite section.
CSS and Styling
CSS Modules
Aurelia supports CSS modules with proper bundler configuration:
// Webpack
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
// Vite (built-in support)
// Just name your files with .module.css extension
SCSS/SASS Support
Add SASS loaders for SCSS support:
npm install --save-dev sass sass-loader # Webpack
npm install --save-dev sass # Vite (built-in)
Troubleshooting
Common Issues
"Cannot resolve module" errors
Ensure file extensions are properly configured in bundler resolve settings
Check that Aurelia loaders are properly configured for HTML and TypeScript files
Slow development builds
For Webpack: Enable
experiments.lazyCompilation
and proper development aliasesFor Vite: Ensure
useDev: true
is set in the Aurelia plugin options
HMR not working
Verify HMR is enabled in both bundler and Aurelia loader configurations
Check browser console for HMR-related warnings
TypeScript template errors
Ensure proper HTML type definitions are included
Consider enabling
experimentalTemplateTypeCheck
in webpack loader options
Performance Tips
Use development bundles: Always alias to
.dev.mjs
files during developmentEnable code splitting: Configure manual chunks for better loading performance
Optimize assets: Use appropriate loaders for images, fonts, and other assets
Source map strategy: Use
eval-cheap-source-map
for development,source-map
for production
Conclusion
Aurelia 2 provides excellent bundler flexibility through dedicated loaders and plugins. Vite offers the fastest development experience with minimal configuration, while Webpack provides maximum customization options. Parcel offers a good middle ground with zero-configuration setup.
Key points to remember:
Always use the official Aurelia bundler plugins/loaders
Configure proper TypeScript declarations for HTML modules
Use development bundles during development for better debugging
Enable HMR for the best development experience
For advanced configurations and bundler-specific optimizations, refer to the official documentation of your chosen bundler alongside Aurelia's guides.
Last updated
Was this helpful?