CSP for Single Page Apps — React, Vue, Angular
Single-page apps make CSP harder because bundlers and frameworks sometimes use eval(), inject inline scripts, and load resources dynamically. Here is how to handle each framework.
React (Create React App / Vite)
CRA and Vite do not use eval() by default. A nonce-based CSP works if you are serving from a Node.js server. For static deployments (Netlify, Vercel, S3), use hashes for any inline scripts.
# Starting CSP for React on Vercel Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.yourbackend.com; frame-ancestors 'none'; object-src 'none';
The style-src 'unsafe-inline' is usually required for CSS-in-JS (styled-components, emotion). Use nonces or the strictDynamic approach to avoid it.
Next.js (App Router)
# Next.js with nonces — see our dedicated guide
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{nonce}' 'strict-dynamic'; style-src 'self' 'unsafe-inline';
Vue.js
Vue's template compiler does not use eval(). The runtime-only build is CSP-compatible. If you use the full build (including compiler), set script-src to allow eval:
# Vue runtime-only (recommended for production) Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; # Vue full build (includes template compiler) — less secure Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval';
Angular
Angular supports Trusted Types — the strictest CSP mode available:
# Angular with Trusted Types Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; require-trusted-types-for 'script'; trusted-types angular angular#unsafe-bypass;
Dynamic imports and code splitting
Webpack and Vite code splitting loads chunks dynamically. Add your CDN domain or use 'strict-dynamic' to allow script tags created by your trusted inline scripts:
script-src 'self' 'nonce-{nonce}' 'strict-dynamic';
# strict-dynamic propagates trust from your nonce to any script those scripts load
Generate your SPA CSP → CSPFixer