Skip to content

Commit d7e3634

Browse files
authored
Merge pull request #26 from FullStacksDev/angular-v19-etc
Angular v19 upgrades and more
2 parents 2bf23f1 + a945b5c commit d7e3634

31 files changed

+5389
-5142
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
- name: Set up pnpm
3333
uses: pnpm/action-setup@v4
3434
with:
35-
version: 9
35+
version: 10
3636

3737
- name: Set up Node.js
3838
uses: actions/setup-node@v4

ARCHITECTURE.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ This isolation is important as Firebase Functions currently deploy ALL dependenc
7272
>
7373
> This does mean you have to manage, install and update dependencies separately, for each subfolder.
7474
75-
A VS Code workspace config is provided to work on both at the same time, in a single VS Code window. The workspace also provides settings and recommended extensions that will help your development experience.
75+
A VS Code workspace config is provided to work on both subfolders at the same time, in a single VS Code window. The workspace also provides settings and recommended extensions that will help your development experience.
7676

7777
> [!TIP]
7878
>
@@ -90,7 +90,7 @@ The `firebase/common` folder is the place for this shared common code. We recomm
9090

9191
> [!WARNING]
9292
>
93-
> It's highly recommended to only put types, interfaces and very simple utility functions here, and to not rely on any external libraries. Where you do want to rely on an external library (e.g. [type-fest](https://github.com/sindresorhus/type-fest/)) make sure the library is added to both the `app` and `firebase` `package.json` files.
93+
> It's highly recommended to only put types, interfaces and very simple utility functions here, and to not rely on any external libraries. Where you do want to rely on an external library (e.g. [type-fest](https://github.com/sindresorhus/type-fest/)) make sure the library is added to both the `app` and `firebase` `package.json` files as well.
9494
9595
> [!TIP]
9696
>
@@ -118,7 +118,7 @@ All data in the emulators is persisted to the `firebase/local` folder (on shutdo
118118

119119
| **:brain: Design decision** |
120120
| :-- |
121-
| Beyond local development, this base template assumes only one live Firebase project / environment (which you set up), as specified in the [`firebase/.firebaserc`](./firebase/.firebaserc) file.<br><br>We believe this is a good simple set-up to get you started, and for the first phase of your project (going from 0 to 1), after which you can always add intermediate environments for testing and less risky deploys / rollouts |
121+
| Beyond local development, this base template assumes only one live Firebase project / environment (which you set up), as specified in the [`firebase/.firebaserc`](./firebase/.firebaserc) file.<br><br>We believe this is a good simple set-up to get you started, and for the first phase of your project (going from 0 to 1), after which you can always add a intermediate environment (aka 'staging') for testing and less risky deploys / rollouts |
122122

123123
This live project is your **production** environment — what your users will access, and where all your real data will live.
124124

@@ -162,7 +162,7 @@ The [`./deploy`](./deploy) script in the root of the project is a simple script
162162

163163
| **:brain: Design decision** |
164164
| :-- |
165-
| We don't use [Angular modules (i.e. `@Module`)](https://angular.dev/guide/ngmodules) for our own code — we've chosen to go all-in on [Angular's recent **standalone** approach](https://angular.dev/guide/components/importing#standalone-components). So we only ever define (and prefer to import) standalone components, directives, etc.<br><br> The base template has configured the Angular CLI generator to always set the `standalone: true` flag on any components, directives, etc. you generate. |
165+
| As of Angular v19, 'standalone' components, pipes and directives are the default (and thus no need for NgModules). We have also enabled the Angular-specific TypeScript flag `strictStandalone` to guard against the use of non-standalone bits. |
166166

167167
| **:brain: Design decision** |
168168
| :-- |
@@ -222,7 +222,7 @@ We'll refer to these in the rest of the document.
222222

223223
> [!NOTE]
224224
>
225-
> There are some files at the root of the `/app` folder (not shown in the listing above) which we'll touch on in later sections. These include: `angular.json`, `prerendered-routes.txt`, `ngsw-config.json` and `tailwind.config.js`.
225+
> There are some files at the root of the `/app` folder (not shown in the listing above) which we'll touch on in later sections. These include: `angular.json`, `prerendered-routes.txt`, and `ngsw-config.json`.
226226
227227
| **:brain: Design decision** |
228228
| :-- |
@@ -240,7 +240,7 @@ We'll refer to these in the rest of the document.
240240

241241
The `data` folder is for (most) state management and data access services. Page and smart components go in the `feature` folder, whilst presentational components go in the `ui`folder. And the `util` folder is for standalone utilities.
242242

243-
This is a recommended folder structure based on [Nx's suggested library types](https://nx.dev/concepts/more-concepts/library-types).
243+
This is a recommended folder structure based on [Nx's suggested library types](https://nx.dev/concepts/decisions/project-dependency-rules).
244244

245245
For features within the `shared` folder you should follow the same structure, except you probably won't need a `feature` subfolder within each shared feature since these are shared bits of code for use elsewhere.
246246

@@ -321,25 +321,21 @@ Whilst on the topic of Firebase Hosting, we also set up some caching headers in
321321

322322
The core of a PWA config is the [`manifest.webmanifest`](./app/src/manifest.webmanifest) file, which defines the app's name, icons, colors, etc. This is used by the browser to provide a more "app-like" experience when the user adds the app to their home screen / app launcher (depending on device capabilities). This file follows the regular [PWA manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) spec. **You'll need to customize this file to specify your app's name and branding.**
323323

324-
For the Angular service worker, the [`app/ngsw-config.json`](./app/ngsw-config.json) file is the main configuration, determining how to cache assets, handle updates, etc ([docs](https://angular.io/guide/service-worker-config)).
324+
For the Angular service worker, the [`app/ngsw-config.json`](./app/ngsw-config.json) file is the main configuration, determining how to cache assets, handle updates, etc ([docs](https://angular.dev/ecosystem/service-workers/config)).
325325

326326
The [`app/src/app/app.component.ts`](./app/src/app/app.component.ts) file contains the logic for the in-app update notification, which checks for updates to the app and prompts the user to reload when a new version is available.
327327

328328
> [!NOTE]
329329
>
330-
> Technically, a new "version" of an app is just a new build of assets, as defined by the `assetGroups` in the `ngsw-config.json` file. The service worker will automatically download (and cache) these new assets in the background and the trigger the in-app update notification.
330+
> Technically, a new "version" of an app is just a new build of assets, as defined by the `assetGroups` in the `ngsw-config.json` file. The service worker will automatically download (and cache) these new assets in the background and the trigger the in-app update notification. We also use set `"applicationMaxAge": "30d"` to force the service worker to refetch assets every 30 days, just in case.
331331
332332
## [`app`] UI components and styling using Angular Material and Tailwind CSS
333333

334334
| **:brain: Design decision** |
335335
| :-- |
336-
| We use [Angular Material](https://material.angular.io/) (with Material 3) for UI components, and [Tailwind CSS](https://tailwindcss.com/) for styling. You can still create your own UI components or add in other libraries, if needed. You can also customize Tailwind CSS as you wish, by updating the [`app/tailwind.config.js`](./app/tailwind.config.js) config file. |
336+
| We use [Angular Material](https://material.angular.io/) (with Material 3) for UI components, and [Tailwind CSS](https://tailwindcss.com/) for styling. You can still create your own UI components or add in other libraries, if needed. You can also customize Tailwind CSS as you wish, using v4's [CSS-first configuration](https://tailwindcss.com/blog/tailwindcss-v4#css-first-configuration). |
337337

338-
The [`app/src/styles.scss`](./app/src/styles.scss) file sets up both Angular Material (with a basic Material 3 theme with custom background and text colors) and Tailwind CSS styling. Here, we also provide styling overrides to make Angular Material work okay with the Tailwind CSS base styles.
339-
340-
> [!NOTE]
341-
>
342-
> We scope all Tailwind CSS and custom styles within the `#app` selector — we apply the `app` ID on the `<body>` element in the [`app/src/index.html`](./app/src/index.html) file and configure `tailwind.config.js` to place all Tailwind-specific styles within the `#app` selector, acting as a "namespace". When adding styles to the `styles.scss` file make sure to add them within the `#app` selector (already defined) to stick to this namespaced approach. This will hopefully allow for better overrides as you will have more specificity in your custom styles.
338+
The [`app/src/styles.scss`](./app/src/styles.scss) file sets up both Angular Material (with a basic Material 3 theme with custom background and text colors) and Tailwind CSS styling. Styles are provided for headings and paragraphs (`h1`-`h6` and `p` tags) as Angular Material no longer provides these out of the box. We also provide styling overrides to make Angular Material work okay with the Tailwind CSS base styles.
343339

344340
You can import and use Angular Material components within your components as usual (see the [docs](https://material.angular.io/)). And you can use Tailwind CSS classes in your HTML and SCSS files as you wish (see the [docs](https://tailwindcss.com/docs)).
345341

@@ -387,7 +383,7 @@ These return the underlying Firebase service instances provided by the Firebase
387383

388384
A critical component of any app that provides user-specific capabilities is authentication. The base template comes with an auth store, auth guard, login page, passwordless login flow and logout flow out of the box.
389385

390-
To use the auth store: inject the global `AuthStore` service into your component, service, directive, etc. using `inject(AuthStore)`. You then have access to the state of the auth store. Note that this auth store automatically connects to Firebase Authentication and listens for changes, when your app starts up.
386+
To use the auth store: inject the global `AuthStore` service into your component, service, directive, etc. using `inject(AuthStore)`. You then have access to the state of the auth store. Note that this auth store automatically connects to Firebase Authentication and listens for changes when your app starts up.
391387

392388
To use the auth guard:
393389

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ This template gives you an empty app skeleton, working end-to-end, with the foll
2727
- Login flow using [Firebase Auth's Email Link](https://firebase.google.com/docs/auth/web/email-link-auth).
2828
- Angular Material and Tailwind CSS, with styling overrides to make them work well together.
2929
- Helpers to inject Firebase services into Angular components, services, etc.
30-
- [RxFire](https://github.com/FirebaseExtended/rxfire) used for Observable wrappers for Firebase access in the frontend.
30+
- [RxFire](https://github.com/FirebaseExtended/rxfire) for Observable wrappers for Firebase access in the frontend.
3131
- Frontend logging using [consola](https://github.com/unjs/consola).
3232
- VS Code, ESLint, Prettier, etc. all set up for a consistent and clean development experience.
3333
- Continuous integration (CI) set up with GitHub Actions (for linting, tests and builds).
@@ -44,12 +44,12 @@ For more details see the [Architecture and design decisions](./ARCHITECTURE.md)
4444
> Basic familiarity with the technologies and services listed is required to make the best of this tech stack and template.
4545
4646
- [Node.js](https://nodejs.org/en/) v20.x
47-
- [TypeScript](https://www.typescriptlang.org/) v5.5
48-
- [Angular](https://angular.dev/) v18.1
49-
- [Angular Material](https://material.angular.io/) v18.1
50-
- [Tailwind CSS](https://tailwindcss.com/) v3.4
51-
- [NgRx Signals](https://ngrx.io/guide/signals) v18.0
52-
- [RxFire](https://github.com/FirebaseExtended/rxfire)
47+
- [TypeScript](https://www.typescriptlang.org/) v5.7
48+
- [Angular](https://angular.dev/) v19.1
49+
- [Angular Material](https://material.angular.io/) v19.1
50+
- [Tailwind CSS](https://tailwindcss.com/) v4.0
51+
- [NgRx Signals](https://ngrx.io/guide/signals) v19.0
52+
- [RxFire](https://github.com/FirebaseExtended/rxfire) v6.1
5353
- [Firebase](https://firebase.google.com/)
5454
- [Hosting](https://firebase.google.com/products/hosting)
5555
- [Authentication](https://firebase.google.com/products/auth)
@@ -63,7 +63,7 @@ For more details see the [Architecture and design decisions](./ARCHITECTURE.md)
6363
- [Git](https://git-scm.com/) for version control.
6464
- [GitHub](https://github.com/) for hosting the code and running the CI pipeline.
6565
- [VS Code](https://code.visualstudio.com/) as the main editor.
66-
- [pnpm](https://pnpm.io/) as the package manager and script runner.
66+
- [pnpm](https://pnpm.io/) v10 as the package manager and script runner.
6767
- [Angular CLI](https://angular.io/cli)
6868
- [Firebase CLI](https://firebase.google.com/docs/cli)
6969
- [Firebase Emulator Suite](https://firebase.google.com/docs/emulator-suite) for local Firebase services.

app/.postcssrc.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"plugins": {
3+
"@tailwindcss/postcss": {}
4+
}
5+
}

app/angular.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
"routesFile": "prerendered-routes.txt"
6565
},
6666
"ssr": {
67-
"entry": "server.ts"
67+
"entry": "src/server.ts"
6868
}
6969
},
7070
"configurations": {
@@ -119,6 +119,7 @@
119119
"test": {
120120
"builder": "@angular-devkit/build-angular:karma",
121121
"options": {
122+
"builderMode": "application",
122123
"polyfills": ["zone.js", "zone.js/testing"],
123124
"tsConfig": "tsconfig.spec.json",
124125
"inlineStyleLanguage": "scss",

app/ngsw-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
33
"index": "/index.csr.html",
4+
"applicationMaxAge": "30d",
45
"assetGroups": [
56
{
67
"name": "app",

app/package.json

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,58 +15,69 @@
1515
},
1616
"engines": {
1717
"node": "20",
18-
"pnpm": "9"
18+
"pnpm": "10"
1919
},
20+
"packageManager": "[email protected]",
2021
"private": true,
2122
"dependencies": {
22-
"@angular/animations": "^18.2.12",
23-
"@angular/cdk": "18.2.13",
24-
"@angular/common": "^18.2.12",
25-
"@angular/compiler": "^18.2.12",
26-
"@angular/core": "^18.2.12",
27-
"@angular/forms": "^18.2.12",
28-
"@angular/material": "18.2.13",
29-
"@angular/platform-browser": "^18.2.12",
30-
"@angular/platform-browser-dynamic": "^18.2.12",
31-
"@angular/platform-server": "^18.2.12",
32-
"@angular/router": "^18.2.12",
33-
"@angular/service-worker": "^18.2.12",
34-
"@angular/ssr": "^18.2.12",
35-
"@ngrx/operators": "^18.1.1",
36-
"@ngrx/signals": "^18.1.1",
37-
"consola": "^3.2.3",
38-
"express": "^4.21.1",
39-
"firebase": "^11.0.2",
40-
"ngxtension": "^4.1.0",
41-
"rxfire": "^6.0.6-canary.5cfad21",
23+
"@angular/animations": "^19.1.5",
24+
"@angular/cdk": "19.1.3",
25+
"@angular/common": "^19.1.5",
26+
"@angular/compiler": "^19.1.5",
27+
"@angular/core": "^19.1.5",
28+
"@angular/forms": "^19.1.5",
29+
"@angular/material": "19.1.3",
30+
"@angular/platform-browser": "^19.1.5",
31+
"@angular/platform-browser-dynamic": "^19.1.5",
32+
"@angular/platform-server": "^19.1.5",
33+
"@angular/router": "^19.1.5",
34+
"@angular/service-worker": "^19.1.5",
35+
"@angular/ssr": "^19.1.6",
36+
"@ngrx/operators": "^19.0.1",
37+
"@ngrx/signals": "^19.0.1",
38+
"consola": "^3.4.0",
39+
"express": "^4.21.2",
40+
"firebase": "^11.3.0",
41+
"ngxtension": "^4.3.2",
42+
"rxfire": "^6.1.0",
4243
"rxjs": "~7.8.0",
4344
"tslib": "^2.8.1",
44-
"zone.js": "~0.14.10"
45+
"zone.js": "~0.15.0"
4546
},
4647
"devDependencies": {
47-
"@angular-devkit/build-angular": "^18.2.12",
48-
"@angular/cli": "^18.2.12",
49-
"@angular/compiler-cli": "^18.2.12",
50-
"@ngrx/eslint-plugin": "^18.1.1",
51-
"@types/express": "^4.17.17",
52-
"@types/jasmine": "~5.1.0",
53-
"@types/node": "^22.9.0",
54-
"angular-eslint": "18.4.1",
55-
"autoprefixer": "^10.4.20",
56-
"eslint": "^9.15.0",
57-
"eslint-config-prettier": "^9.1.0",
58-
"jasmine-core": "~5.4.0",
48+
"@angular-devkit/build-angular": "^19.1.6",
49+
"@angular/cli": "^19.1.6",
50+
"@angular/compiler-cli": "^19.1.5",
51+
"@ngrx/eslint-plugin": "^19.0.1",
52+
"@tailwindcss/postcss": "^4.0.0",
53+
"@types/express": "^5.0.0",
54+
"@types/jasmine": "~5.1.5",
55+
"@types/node": "^22.13.1",
56+
"angular-eslint": "^19.0.2",
57+
"eslint": "^9.19.0",
58+
"eslint-config-prettier": "^10.0.1",
59+
"jasmine-core": "~5.5.0",
5960
"karma": "~6.4.4",
6061
"karma-chrome-launcher": "~3.2.0",
6162
"karma-coverage": "~2.2.0",
6263
"karma-jasmine": "~5.1.0",
6364
"karma-jasmine-html-reporter": "~2.1.0",
64-
"ng-mocks": "^14.13.1",
65+
"ng-mocks": "^14.13.2",
6566
"postcss": "^8.4.49",
66-
"prettier": "^3.3.3",
67-
"prettier-plugin-tailwindcss": "^0.6.8",
68-
"tailwindcss": "^3.4.15",
69-
"typescript": "~5.5.4",
70-
"typescript-eslint": "^8.15.0"
67+
"prettier": "^3.4.2",
68+
"prettier-plugin-tailwindcss": "^0.6.11",
69+
"tailwindcss": "^4.0.0",
70+
"typescript": "~5.7.3",
71+
"typescript-eslint": "^8.23.0"
72+
},
73+
"pnpm": {
74+
"onlyBuiltDependencies": [
75+
"protobufjs",
76+
"nx",
77+
"@parcel/watcher",
78+
"esbuild",
79+
"msgpackr-extract",
80+
"lmdb"
81+
]
7182
}
7283
}

0 commit comments

Comments
 (0)