--- description: This rule provides comprehensive guidelines for Angular development, covering coding standards, best practices, performance optimization, security considerations, and testing approaches to ensure maintainable, scalable, and high-performing applications. globs: *.ts,*.html,*.scss,*.css --- # Angular Best Practices and Coding Standards This document outlines comprehensive best practices and coding standards for developing Angular applications. Adhering to these guidelines will promote maintainability, scalability, performance, and security. ## 1. Code Organization and Structure ### 1.1. Directory Structure Best Practices - **Feature-based Modules:** Organize your application into feature modules, where each module encapsulates a specific feature or functionality. - **Shared Module:** Create a `shared` module for commonly used components, directives, pipes, and services. - **Core Module:** Create a `core` module for application-wide services and singleton instances (e.g., authentication service, configuration service). - **Lazy-loaded Modules:** Group related features into lazy-loaded modules to improve initial load time. - **Directory structure example:** src/ ├── app/ │ ├── core/ │ │ ├── core.module.ts │ │ └── auth.service.ts │ ├── shared/ │ │ ├── shared.module.ts │ │ └── components/ │ │ └── ... │ ├── features/ │ │ ├── dashboard/ │ │ │ ├── dashboard.module.ts │ │ │ ├── dashboard.component.ts │ │ │ └── dashboard.component.html │ │ ├── user-management/ │ │ │ ├── user-management.module.ts │ │ │ └── ... │ │ └── ... │ ├── app.component.ts │ └── app.module.ts └── ... ### 1.2. File Naming Conventions - **Consistent Naming:** Use a consistent naming pattern for all files and symbols, following the `feature.type.ts` convention (e.g., `user.component.ts`, `user.service.ts`). - **Type Abbreviations:** Use abbreviations for file types (e.g., `component.ts` -> `.component.ts`, `service.ts` -> `.service.ts`, `module.ts` -> `.module.ts`). - **Descriptive Names:** Use descriptive names that clearly indicate the purpose of the file. ### 1.3. Module Organization - **Single Responsibility:** Each module should have a single responsibility. - **Declarations:** Declare components, directives, and pipes within the appropriate module. - **Imports:** Import only the necessary modules in each module. - **Exports:** Export components, directives, and pipes that need to be used by other modules. - **forRoot() pattern:** Use the `forRoot()` pattern for modules that provide singleton services to ensure they are only instantiated once in the application. ### 1.4. Component Architecture - **Smart vs. Dumb Components:** Distinguish between smart (container) components that handle data and logic, and dumb (presentational) components that focus on rendering UI. - **Component Reusability:** Design components for reusability. - **Input and Output Properties:** Use `@Input()` and `@Output()` properties to pass data and events between components. - **Change Detection:** Be mindful of change detection strategies (e.g., `OnPush`) to optimize rendering performance. ### 1.5. Code Splitting Strategies - **Lazy Loading:** Implement lazy loading for modules to reduce the initial bundle size and improve load time. - **Route-based Code Splitting:** Split your application into modules based on routes. - **Feature-based Code Splitting:** Split your application into modules based on features. ## 2. Common Patterns and Anti-patterns ### 2.1. Design Patterns Specific to Angular - **Dependency Injection (DI):** Use DI to manage dependencies between components and services. - **Observables:** Use RxJS Observables for handling asynchronous data streams. - **Services:** Use services for encapsulating reusable business logic. - **Pipes:** Use pipes for transforming data in templates. - **Directives:** Use directives for manipulating the DOM. ### 2.2. Recommended Approaches for Common Tasks - **Data Binding:** Use data binding (`{{ }}`, `[]`, `()`) to synchronize data between the component and the template. - **Event Handling:** Use event binding (`()`) to handle user interactions. - **Form Handling:** Use reactive forms or template-driven forms to manage user input. - **HTTP Requests:** Use the `HttpClient` to make HTTP requests to backend APIs. ### 2.3. Anti-patterns and Code Smells to Avoid - **Deeply Nested Components:** Avoid deeply nested component hierarchies, which can make it difficult to manage state and events. - **Large Components:** Break large components into smaller, reusable components. - **Logic in Templates:** Avoid complex logic in templates; move it to the component class. - **Direct DOM Manipulation:** Avoid direct DOM manipulation; use Angular's data binding and directives instead. - **Unnecessary Subscriptions:** Unsubscribe from Observables to prevent memory leaks. Use the `async` pipe in templates to automatically handle subscriptions and unsubscriptions. ### 2.4. State Management Best Practices - **Choose a State Management Library:** Consider using a state management library like NgRx, Akita, or MobX for complex applications. - **Centralized State:** Store application state in a central store. - **Immutability:** Treat state as immutable to simplify change detection and debugging. - **Actions and Reducers:** Use actions to describe state changes and reducers to update the state. - **Selectors:** Use selectors to efficiently retrieve data from the store. ### 2.5. Error Handling Patterns - **Centralized Error Handling:** Implement a centralized error handling mechanism using an `ErrorHandler`. - **Error Interceptors:** Use HTTP interceptors to handle errors from backend APIs. - **User-Friendly Error Messages:** Display user-friendly error messages to the user. - **Logging:** Log errors to a central logging service for debugging and monitoring. - **Retry mechanism:** Implement retry mechanism for failed requests using RxJS retry operators. ## 3. Performance Considerations ### 3.1. Optimization Techniques - **Change Detection Optimization:** Use `OnPush` change detection strategy for components that only depend on their input properties. - **TrackBy Function:** Use the `trackBy` function with `ngFor` to optimize rendering of lists. - **Virtualization:** Use virtual scrolling for large lists to improve performance. - **Ahead-of-Time (AOT) Compilation:** Use AOT compilation to compile templates during the build process, improving startup time. - **Minification and Uglification:** Minify and uglify your code to reduce bundle size. ### 3.2. Memory Management - **Unsubscribe from Observables:** Unsubscribe from Observables when they are no longer needed to prevent memory leaks. - **Avoid Circular Dependencies:** Avoid circular dependencies, which can lead to memory leaks. - **Detach Event Listeners:** Detach event listeners when they are no longer needed. ### 3.3. Rendering Optimization - **Minimize DOM Manipulation:** Minimize DOM manipulation, as it can be expensive. - **Use CSS Transforms:** Use CSS transforms instead of modifying layout properties. - **Debouncing and Throttling:** Use debouncing and throttling to reduce the frequency of event handlers. ### 3.4. Bundle Size Optimization - **Lazy Loading:** Implement lazy loading for modules to reduce the initial bundle size. - **Tree Shaking:** Use tree shaking to remove unused code from your bundle. - **Code Splitting:** Split your application into smaller bundles to improve load time. - **Image Optimization:** Optimize images to reduce their file size. - **Vendor Libraries:** Use only necessary vendor libraries, and ensure they are up-to-date for optimized versions. ### 3.5. Lazy Loading Strategies - **Route-based Lazy Loading:** Load modules when navigating to a specific route. - **Feature-based Lazy Loading:** Load modules based on feature requirements. - **Preloading:** Preload modules in the background to improve perceived performance. ## 4. Security Best Practices ### 4.1. Common Vulnerabilities and How to Prevent Them - **Cross-Site Scripting (XSS):** Prevent XSS attacks by sanitizing user input and avoiding the use of `innerHTML`. - **Cross-Site Request Forgery (CSRF):** Prevent CSRF attacks by using anti-CSRF tokens. - **Injection Attacks:** Prevent injection attacks by validating user input and using parameterized queries. ### 4.2. Input Validation - **Client-Side Validation:** Perform client-side validation to provide immediate feedback to the user. - **Server-Side Validation:** Perform server-side validation to ensure data integrity. - **Whitelist Validation:** Use whitelist validation to allow only specific characters or patterns. ### 4.3. Authentication and Authorization Patterns - **Authentication:** Implement authentication to verify the user's identity. - **Authorization:** Implement authorization to control access to resources based on the user's roles and permissions. - **JSON Web Tokens (JWT):** Use JWTs for secure authentication and authorization. - **OAuth 2.0:** Use OAuth 2.0 for delegating authorization to third-party applications. ### 4.4. Data Protection Strategies - **Encryption:** Encrypt sensitive data at rest and in transit. - **Hashing:** Hash passwords before storing them in the database. - **Data Masking:** Mask sensitive data to prevent unauthorized access. ### 4.5. Secure API Communication - **HTTPS:** Use HTTPS for secure communication between the client and the server. - **API Keys:** Use API keys to authenticate API requests. - **Rate Limiting:** Implement rate limiting to prevent abuse of your API. ## 5. Testing Approaches ### 5.1. Unit Testing Strategies - **Test Driven Development (TDD):** Write tests before writing code. - **Component Testing:** Test components in isolation using mock data. - **Service Testing:** Test services in isolation using dependency injection. - **Pipe Testing:** Test pipes to ensure they transform data correctly. ### 5.2. Integration Testing - **Module Testing:** Test modules to ensure they integrate correctly. - **Component Interaction Testing:** Test the interaction between components. - **HTTP Testing:** Test HTTP requests and responses. ### 5.3. End-to-End Testing - **User Interface (UI) Testing:** Test the UI to ensure it behaves as expected. - **Workflow Testing:** Test complete workflows to ensure they function correctly. - **Cross-Browser Testing:** Test your application in different browsers. ### 5.4. Test Organization - **Test Directory Structure:** Mirror your source code directory structure in your test directory. - **Test File Naming:** Use consistent naming conventions for test files (e.g., `user.component.spec.ts`). - **Test Suites:** Group related tests into test suites. ### 5.5. Mocking and Stubbing - **Mock Dependencies:** Mock dependencies to isolate units of code for testing. - **Stub HTTP Requests:** Stub HTTP requests to avoid making actual API calls during testing. - **Use Mocking Libraries:** Use mocking libraries like Jasmine or Jest to simplify mocking and stubbing. ## 6. Common Pitfalls and Gotchas ### 6.1. Frequent Mistakes Developers Make - **Forgetting to Unsubscribe from Observables:** Always unsubscribe from Observables to prevent memory leaks. - **Using `any` Type:** Avoid using the `any` type, as it bypasses type checking. - **Not Handling Errors:** Handle errors gracefully to prevent unexpected behavior. - **Ignoring Performance:** Optimize your code for performance from the beginning. ### 6.2. Edge Cases to Be Aware Of - **Empty Arrays:** Handle empty arrays correctly. - **Null Values:** Handle null values correctly. - **Unexpected Input:** Validate user input to prevent unexpected behavior. ### 6.3. Version-Specific Issues - **Breaking Changes:** Be aware of breaking changes in new versions of Angular and third-party libraries. - **Deprecated APIs:** Avoid using deprecated APIs. - **Migration Guides:** Follow migration guides when upgrading to new versions of Angular. ### 6.4. Compatibility Concerns - **Browser Compatibility:** Test your application in different browsers to ensure compatibility. - **Device Compatibility:** Test your application on different devices to ensure compatibility. ### 6.5. Debugging Strategies - **Browser Developer Tools:** Use browser developer tools to debug your code. - **Logging:** Use logging to track the flow of execution and identify errors. - **Debugging Tools:** Use debugging tools like VS Code's debugger to step through your code. ## 7. Tooling and Environment ### 7.1. Recommended Development Tools - **VS Code:** Use VS Code as your code editor. - **Angular CLI:** Use the Angular CLI for scaffolding, building, and deploying your application. - **Chrome Developer Tools:** Use Chrome Developer Tools for debugging and performance profiling. ### 7.2. Build Configuration - **Angular CLI Configuration:** Configure your Angular CLI settings in the `angular.json` file. - **Environment Variables:** Use environment variables to configure your application for different environments. - **Build Optimization:** Configure your build process to optimize your code for production. ### 7.3. Linting and Formatting - **ESLint:** Use ESLint to enforce coding standards. - **Prettier:** Use Prettier to format your code automatically. - **Husky:** Use Husky to run linters and formatters before committing code. ### 7.4. Deployment Best Practices - **Continuous Integration/Continuous Deployment (CI/CD):** Use a CI/CD pipeline to automate the build, test, and deployment process. - **Deployment Environments:** Use different deployment environments for development, testing, and production. - **CDN:** Use a content delivery network (CDN) to serve static assets. ### 7.5. CI/CD Integration - **Jenkins:** Use Jenkins for CI/CD. - **GitHub Actions:** Use GitHub Actions for CI/CD. - **Azure DevOps:** Use Azure DevOps for CI/CD. - **GitLab CI:** Use GitLab CI for CI/CD. By following these best practices and coding standards, you can build robust, maintainable, and scalable Angular applications.