Deployment
This guide covers deploying AngularDart applications to production.
Building for Production
Using build_runner
Build optimized JavaScript:
dart run build_runner build --release
This generates optimized files in the build/ directory.
Build Configuration
Configure build.yaml for production:
targets:
$default:
builders:
build_web_compilers|entrypoint:
generate_for:
- web/main.dart
options:
compiler: dart2js
dart2js_args:
- -O4
- --minify
- --no-source-maps
Build Options
| Option | Description |
|---|---|
-O4 |
Maximum optimization level |
--minify |
Minify JavaScript output |
--no-source-maps |
Exclude source maps |
--fast-startup |
Enable fast startup |
--trust-primitives |
Trust primitive types |
--trust-type-assertions |
Trust type assertions |
Output Structure
After building, the build/ directory contains:
build/
web/
main.dart.js # Compiled JavaScript
main.dart.js.map # Source map (optional)
index.html # Entry HTML
assets/ # Static assets
styles.css # Compiled styles
Deployment Options
Static Hosting
Deploy the build/web/ directory to any static hosting:
- Netlify: Drag and drop
build/web/ - Vercel: Connect repo, set build command
- GitHub Pages: Push
build/web/togh-pagesbranch - Firebase Hosting: Use
firebase deploy - AWS S3: Upload to S3 bucket with static hosting
Docker Deployment
# Build stage
FROM dart:stable AS build
WORKDIR /app
COPY . .
RUN dart pub get
RUN dart run build_runner build --release
# Serve stage
FROM nginx:alpine
COPY --from=build /app/build/web /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Nginx Configuration
server {
listen 80;
server_name yourdomain.com;
root /usr/share/nginx/html;
index index.html;
# Enable gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
}
Environment Configuration
Build-time Environment
Use different configurations for environments:
# build.yaml
targets:
$default:
builders:
build_web_compilers|entrypoint:
options:
compiler: dart2js
dart2js_args:
- -O4
- --minify
- -Denvironment=production
Access in Dart:
const environment = String.fromEnvironment('environment', defaultValue: 'development');
@Injectable()
class ConfigService {
String get apiUrl {
if (environment == 'production') {
return 'https://api.yourdomain.com';
}
return 'http://localhost:8080';
}
}
Runtime Configuration
For runtime configuration, use a config file:
<!-- index.html -->
<script>
window.APP_CONFIG = {
apiUrl: 'https://api.yourdomain.com',
features: {
darkMode: true,
analytics: true
}
};
</script>
@JS('APP_CONFIG')
external dynamic get appConfig;
@Injectable()
class ConfigService {
String get apiUrl => appConfig.apiUrl;
}
Performance Optimization
Code Splitting
Split your app into multiple files:
// Load feature modules on demand
Future<void> loadAdminModule() async {
await loadLibrary('package:my_app/admin_module.dart');
}
Lazy Loading Routes
routes = [
RouteDefinition(
path: '/admin',
loader: () async {
await loadLibrary('package:my_app/admin_component.dart');
return adminComponentFactory;
},
),
];
Image Optimization
- Use WebP format for better compression
- Implement responsive images with
srcset - Lazy load images below the fold
Preloading
Preload critical resources:
<link rel="preload" href="main.dart.js" as="script">
<link rel="preload" href="assets/logo.png" as="image">
Monitoring and Analytics
Error Tracking
@Injectable()
class ErrorService {
void reportError(dynamic error, StackTrace? stack) {
// Send to error tracking service
print('Error: $error');
}
}
void main() {
runZonedGuarded(() {
runApp(AppComponentNgFactory);
}, (error, stack) {
// Global error handler
print('Unhandled error: $error');
});
}
Analytics
@Injectable()
class AnalyticsService {
void trackPageView(String path) {
// Send to analytics service
}
void trackEvent(String category, String action, [String? label]) {
// Send event tracking
}
}
Security Checklist
- Enable HTTPS
- Set Content Security Policy headers
- Enable CORS only for trusted domains
- Remove source maps in production
- Minify and obfuscate JavaScript
- Set security headers (X-Frame-Options, X-Content-Type-Options)
- Use secure cookies with HttpOnly and Secure flags
- Validate all user input
- Sanitize HTML content
CI/CD Pipeline
GitHub Actions Example
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dart-lang/setup-dart@v1
with:
sdk: stable
- name: Install dependencies
run: dart pub get
- name: Build
run: dart run build_runner build --release
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v2
with:
publish-dir: ./build/web
production-branch: main
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
Troubleshooting
Build fails with out of memory
Increase Dart VM memory:
dart --enable-vm-service=8181 run build_runner build --release
Large bundle size
- Check for unused dependencies
- Use code splitting
- Enable tree shaking
- Analyze bundle with
source_map_explorer
Slow initial load
- Enable gzip compression
- Preload critical resources
- Use server-side rendering for initial content
- Implement service worker for offline support