<html> <head> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-a23gbfz9e'" /> <script defer nonce="a23gbfz9e" src="https://cdn.jsdelivr.net/npm/@alpinejs/csp@3/dist/cdn.min.js" ></script> </head> <body> <div x-data="counter"> <button x-on:click="count++"><span x-text="count"></span></button> </div> <script nonce="a23gbfz9e"> document.addEventListener('alpine:init', () => { Alpine.data('counter', () => { return { count: 1, increment() { this.count++; }, }; }); }); </script> </body></html>
Политика безопасности содержимого (CSP)
Чтобы Alpine мог выполнять простые строки из HTML-атрибутов как выражения JavaScript, например x-on:click="console.log()"
, ему необходимо использовать утилиты, нарушающие принцип «unsafe-eval» Политики безопасности содержимого, применяемой некоторыми приложениями для повышения безопасности.
Чтобы приспособиться к средам, где этот CSP необходим, Alpine предлагает альтернативную сборку, которая не нарушает «unsafe-eval», но имеет более строгий синтаксис.
Установка
Вы можете использовать эту сборку, включив её в тег <script>
или установив с помощью менеджера пакетов.
Через CDN
Вы можете включить CDN этой сборки в виде тега <script>
, как это делается в стандартной сборке Alpine:
<!-- Ядро Alpine, дружественное к CSP --><script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/csp@3/dist/cdn.min.js"></script>
Через менеджер пакетов
Вы можете установить эту сборку для использования внутри вашего пакета следующим образом:
npm add @alpinejs/csp
pnpm add @alpinejs/csp
yarn add @alpinejs/csp
Затем инициализируйте её из вашего пакета:
import Alpine from '@alpinejs/csp';
window.Alpine = Alpine;window.Alpine.start();
Пример использования
Чтобы дать представление о том, как может выглядеть использование сборки CSP, вот копируемый HTML-файл с работающим компонентом счётчика, использующим обычную настройку CSP:
Ограничения API
Поскольку Alpine больше не может интерпретировать строки как обычный JavaScript, ему приходится разбирать и конструировать из них JavaScript-функции вручную.
Из-за этого ограничения для регистрации объектов x-data
нужно использовать Alpine.data
, а для обращения к свойствам и методам — ссылаться на них только через ключ.
Например, такой встроенный компонент не будет работать:
<!-- Плохо --><div x-data="{ count: 1 }"> <button @click="count++">Увеличить</button> <span x-text="count"></span></div>
Однако, если разбить выражения на внешние API, то для сборки CSP будет справедливо следующее:
<!-- Хорошо --><div x-data="counter"> <button @click="increment">Увеличить</button> <span x-text="count"></span></div>
Alpine.data('counter', () => ({ count: 1,
increment() { this.count++; },}));
Сборка CSP поддерживает доступ к вложенным свойствам (аксессорам свойств) с использованием точечной нотации.
<!-- Это тоже работает --><div x-data="counter"> <button @click="foo.increment">Увеличить</button> <span x-text="foo.count"></span></div>
Alpine.data('counter', () => ({ foo: { count: 1,
increment() { this.count++ }, },}))