· 2 мин чтения

CSP без inline-скриптов: что пришлось отключить в Nuxt

Почему строгая политика script-src self ломает статический Nuxt и какие три шага сделали сайт совместимым, плюс проверка в сборке.

Проект: landscape-bureau-nuxt

Политика script-src 'self' без unsafe-inline закрывает целый класс XSS: любой инлайновый скрипт просто не выполнится. Платить за это приходится совместимостью с инструментами, которые любят вставлять код в HTML.

Что делает Nuxt по умолчанию

Статическая сборка кладёт в страницу inline-скрипт с window.__NUXT__ и importmap, а стили инлайнит. Под строгой политикой браузер их блокирует, и страница остаётся без гидрации: разметка есть, интерактивности нет. Так было и с самим сайтом-портфолио: фиксированный CSP на VPS блокировал гидрацию, пока из экспорта не убрали importmap и не вынесли конфигурацию Nuxt в файл.

Что сделано в landscape-bureau-nuxt

  1. В nuxt.config.ts выключен experimental.entryImportMap.
  2. Выключены инлайн-стили: features.inlineStyles: false.
  3. Скрипт postgenerate выносит window.__NUXT__ в файл _nuxt/inline-<hash>.js.

Чтобы не вернулось

check-security проверяет готовый HTML и проваливает сборку, если нашёл исполняемый inline-скрипт, <style> или style="". Тот же приём в React-проекте bike-workshop-react (линтер запрещает style={}) и в ceramics-vue.

Итог: CSP script-src 'self' и style-src 'self', HSTS, nosniff и frame-ancestors 'none' работают вместе с живым сайтом на Cloudflare Pages. Это концепт с выдуманным бюро, и Lighthouse я не запускал.