Postgres on Angular with PGlite
· 2 min read
PGlite and Angular Signals seem an intriguing alternative to state management solutions like NgRx. The combo is particularly appealing if Postgres is already in (backend) stack.
- Unified Queries: Same Postgres syntax frontend & backend
- Fast Reads: Zero network for local queries
- Signal-Driven UI: Reactivity without reducers
- Sync Ready: Pair with remote Postgres when needed
Getting PGlite to work with Angular took some time, so I thought of documenting a minimal demo.
- Create a demo app
npm install -g @angular/cli@latest
NG_PROJECT_NAME=${NG_PROJECT_NAME:-"ng-pglite-demo"}
ng new --inline-style --inline-template --routing --ssr=false --style=scss $NG_PROJECT_NAME
cd $NG_PROJECT_NAME
npm install @electric-sql/pglite
- Update
angular.json
(withjq
like below) or set the values manually
cp angular.json angular.json.bak
jq --arg project_name "$NG_PROJECT_NAME" \
'(.projects[$project_name].architect.build.options.allowedCommonJsDependencies += ["@electric-sql/pglite"])
| (.projects[$project_name].architect.build.configurations.production.externalDependencies += ["util"])
| (.projects[$project_name].architect.build.configurations.development.externalDependencies += ["util"])
| (.projects[$project_name].architect.serve.options.prebundle) = false
| (.projects[$project_name].architect.build.options.assets += [{"glob": "**/*", "input": "node_modules/@electric-sql/pglite/dist", "output": "/"}])' \
angular.json > tmp.json && mv tmp.json angular.json
- Try PGlite in a service / component eg
src/app/app.component.ts
with below content
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';
import { PGlite } from '@electric-sql/pglite';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-root',
imports: [CommonModule],
template: `
<div>Rows
@if (rows.length === 0) {
<span>Loading...</span>
} @else {
<span>Loaded {{ rows.length }} rows</span>
<pre><code>{{ rows | json }}</code></pre>
}
</div>
`,
styles: [],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements OnInit {
private cdr = inject(ChangeDetectorRef);
db = new PGlite();
rows: any[] = [];
async ngOnInit() {
try {
await this.testDB();
} catch (err) {
console.error("Error initializing database:", err);
}
}
async testDB() {
await this.db.exec("CREATE TABLE users (id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, name TEXT)");
await this.db.exec("INSERT INTO users (name) VALUES ('Alice'), ('Bob'), ('Charlie')");
const result = await this.db.query("SELECT * FROM users");
console.log("Query Result:", result);
this.rows = result.rows;
this.cdr.detectChanges();
}
}
- Verify
ng serve
Visit http://localhost:4200 and notice the rows of users table are rendered.