SPA just use APIs so most of frameworks are compatible
That's significantly more work than just doing whatever logic you want on the server to begin with where you have access to all tables directly (they're an ORM call away) and not have to worry about access control because all of this still happens within the trusted environment of the server.
Instead of this:
def endpointAB:
a = db.getA()
b = db.getB()
return template('ab.html', {a=a, b=b})
You tend to have this: def endpointAB:
a = db.getA()
b = db.getB()
return json({a=a, b=b})
When I think of ways you may want to generalize over arbitrary queries on the server, I run into the same challenges you'd have in a SPA rather than fewer.