|
@@ -1,49 +1,87 @@
|
|
|
---
|
|
|
-order: 5
|
|
|
+order: 1
|
|
|
title: CSP
|
|
|
---
|
|
|
|
|
|
-# CSP (Content-Security Policy)
|
|
|
+# CSP (Content-Security Policy) Build
|
|
|
|
|
|
-In order for Alpine to be able to execute plain strings from HTML attributes as JavaScript expressions, for example `x-on:click="console.log()"`, it needs to rely on utilities that violate the "unsafe-eval" content security policy.
|
|
|
+In order for Alpine to be able to execute plain strings from HTML attributes as JavaScript expressions, for example `x-on:click="console.log()"`, it needs to rely on utilities that violate the "unsafe-eval" [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) that some applications may enforce for security purposes.
|
|
|
|
|
|
> Under the hood, Alpine doesn't actually use eval() itself because it's slow and problematic. Instead it uses Function declarations, which are much better, but still violate "unsafe-eval".
|
|
|
|
|
|
-In order to accommodate environments where this CSP is necessary, Alpine will offer an alternate build that doesn't violate "unsafe-eval", but has a more restrictive syntax.
|
|
|
+In order to accommodate environments where this CSP is necessary, Alpine offer's an alternate build that doesn't violate "unsafe-eval", but has a more restrictive syntax.
|
|
|
|
|
|
<a name="installation"></a>
|
|
|
## Installation
|
|
|
|
|
|
-The CSP build hasn’t been officially released yet. In the meantime, you may build it from source. To do this, clone the [`alpinejs/alpine`](https://github.com/alpinejs/alpine) repository and run:
|
|
|
+You can use this build by either including it from a `<script>` tag or installing it via NPM:
|
|
|
|
|
|
-```shell
|
|
|
-npm install
|
|
|
-npm run build
|
|
|
+### Via CDN
|
|
|
+
|
|
|
+You can include this build's CDN as a `<script>` tag just like you would normally with standard Alpine build:
|
|
|
+
|
|
|
+```alpine
|
|
|
+<!-- Alpine's CSP-friendly Core -->
|
|
|
+<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js"></script>
|
|
|
```
|
|
|
|
|
|
-This will generate a `/packages/csp/dist/` directory with the built files. After copying the appropriate file into your project, you can include it either via `<script>` tag or module import:
|
|
|
+### Via NPM
|
|
|
|
|
|
-<a name="script-tag"></a>
|
|
|
-### Script tag
|
|
|
+You can alternatively install this build from NPM for use inside your bundle like so:
|
|
|
|
|
|
-```alpine
|
|
|
-<html>
|
|
|
- <script src="/path/to/cdn.js" defer></script>
|
|
|
-</html>
|
|
|
+```shell
|
|
|
+npm install @alpinejs/csp
|
|
|
```
|
|
|
|
|
|
-<a name="module-import"></a>
|
|
|
-### Module import
|
|
|
+Then initialize it from your bundle:
|
|
|
|
|
|
```js
|
|
|
-import Alpine from './path/to/module.esm.js'
|
|
|
+import Alpine from '@alpinejs/csp'
|
|
|
|
|
|
window.Alpine = Alpine
|
|
|
-window.Alpine.start()
|
|
|
+
|
|
|
+Alpine.start()
|
|
|
```
|
|
|
|
|
|
-<a name="restrictions"></a>
|
|
|
-## Restrictions
|
|
|
+<a name="basic-example"></a>
|
|
|
+## Basic Example
|
|
|
+
|
|
|
+To provide a glimpse of how using the CSP build might feel, here is a copy-pastable HTML file with a working counter component using a common CSP setup:
|
|
|
+
|
|
|
+```alpine
|
|
|
+<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.x.x/dist/cdn.min.js"></script>
|
|
|
+ </head>
|
|
|
+
|
|
|
+ <body>
|
|
|
+ <div x-data="counter">
|
|
|
+ <button x-on:click="increment"></button>
|
|
|
+
|
|
|
+ <span x-text="count"></span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <script nonce="a23gbfz9e">
|
|
|
+ document.addEventListener('alpine:init', () => {
|
|
|
+ Alpine.data('counter', () => {
|
|
|
+ return {
|
|
|
+ count: 1,
|
|
|
+
|
|
|
+ increment() {
|
|
|
+ this.count++;
|
|
|
+ },
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ </script>
|
|
|
+ </body>
|
|
|
+</html>
|
|
|
+```
|
|
|
+
|
|
|
+<a name="api-restrictions"></a>
|
|
|
+## API Restrictions
|
|
|
|
|
|
Since Alpine can no longer interpret strings as plain JavaScript, it has to parse and construct JavaScript functions from them manually.
|
|
|
|
|
@@ -70,10 +108,13 @@ However, breaking out the expressions into external APIs, the following is valid
|
|
|
<span x-text="count"></span>
|
|
|
</div>
|
|
|
```
|
|
|
+
|
|
|
```js
|
|
|
Alpine.data('counter', () => ({
|
|
|
count: 1,
|
|
|
|
|
|
- increment() { this.count++ }
|
|
|
+ increment() {
|
|
|
+ this.count++
|
|
|
+ },
|
|
|
}))
|
|
|
```
|