Angular example
In this guide, you'll learn how to integrate Angular into moon.
Begin by creating a new Angular project in the root of an existing moon project (this should not be created in the workspace root, unless a polyrepo).
cd apps && npx -p @angular/cli@latest ng new angular-app
View the official Angular docs for a more in-depth guide to getting started!
Setup
Since Angular is per-project, the associated moon tasks should be defined in each project's
moon.yml
file.
fileGroups:
app:
- 'src/**/*'
- 'angular.*'
tasks:
dev:
command: 'ng serve'
local: true
build:
command: 'ng build'
inputs:
- '@group(app)'
- '@group(sources)'
outputs:
- 'dist'
# Extends the top-level lint
lint:
args:
- '--ext'
- '.ts'
ESLint integration
Angular does not provide a built-in linting abstraction, but instead there is an ESLint package, which is great, but complicates things a bit. Because of this, you have two options for moving forward:
- Use a global
lint
task and bypass Angular's solution (preferred). - Use Angular's ESLint package solution only.
Regardless of which option is chosen, the following changes are applicable to all options and should
be made. Begin be installing the dependencies that the
@angular-eslint
package need in the
application's package.json
.
- Yarn
- Yarn (classic)
- npm
- pnpm
- Bun
yarn workspace <project> add --dev @angular-eslint/builder @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/schematics @angular-eslint/template-parser
yarn workspace <project> add --dev @angular-eslint/builder @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/schematics @angular-eslint/template-parser
npm install --save-dev --workspace <project> @angular-eslint/builder @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/schematics @angular-eslint/template-parser
pnpm add --save-dev --filter <project> @angular-eslint/builder @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/schematics @angular-eslint/template-parser
bun install --dev @angular-eslint/builder @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/schematics @angular-eslint/template-parser
Since Angular has some specific rules, we'll need to tell the ESLint package to overrides the
default ones. This can be achieved with a project-level .eslintrc.json
file.
{
"root": true,
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@angular-eslint/recommended",
// This is required if you use inline templates in Components
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
/**
* Any TypeScript source code (NOT TEMPLATE) related rules you wish to use/reconfigure over and above the
* recommended set provided by the @angular-eslint project would go here.
*/
"@angular-eslint/directive-selector": [
"error",
{ "type": "attribute", "prefix": "app", "style": "camelCase" }
],
"@angular-eslint/component-selector": [
"error",
{ "type": "element", "prefix": "app", "style": "kebab-case" }
]
}
},
{
"files": ["*.html"],
"extends": [
"plugin:@angular-eslint/template/recommended",
"plugin:@angular-eslint/template/accessibility"
],
"rules": {
/**
* Any template/HTML related rules you wish to use/reconfigure over and above the
* recommended set provided by the @angular-eslint project would go here.
*/
}
}
]
}
With the basics now setup, choose the option that works best for you.
- Global lint
- Angular lint
We encourage using the global lint
task for consistency across all projects within the repository.
With this approach, the eslint
command itself will be ran and the ng lint
command will be
ignored, but the @angular-eslint
rules will still be used.
If you'd prefer to use the ng lint
command, add it as a task to the project's
moon.yml
.
tasks:
lint:
command: 'ng lint'
inputs:
- '@group(angular)'
Furthermore, if a global lint
task exists, be sure to exclude it from being inherited.
workspace:
inheritedTasks:
exclude: ['lint']
In addition to configuring moon.yml
, you also need to add a lint target in the angular.json
file
for linting to work properly. The lint target specifies which builder to use for linting, as well as
the file patterns that should be linted.
{
"projects": {
"angular-app": {
"architect": {
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
}
}
}
}
}
Adding this lint target is crucial for ensuring that the linting process is properly configured and integrated with Angular's build system.
TypeScript integration
Angular has built-in support for TypeScript, so there is no need for additional configuration to enable TypeScript support.
At this point we'll assume that a tsconfig.json
has been created in the application, and
typechecking works. From here we suggest utilizing a global typecheck
task for
consistency across all projects within the repository.
Configuration
Root-level
We suggest against root-level configuration, as Angular should be installed per-project, and the
ng
command expects the configuration to live relative to the project root.
Project-level
When creating a new Angular project, a angular.json
is created, and must exist in the project root. This allows each project to configure Angular for
their needs.
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"projects": {
"angular-app": {
"projectType": "application",
...
}
},
...
}