diff --git a/.changeset/big-cups-exist.md b/.changeset/big-cups-exist.md
new file mode 100644
index 000000000000..4859d353d2b9
--- /dev/null
+++ b/.changeset/big-cups-exist.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+[breaking] remove amp config option in favour of amp.transform helper function
diff --git a/documentation/docs/14-configuration.md b/documentation/docs/14-configuration.md
index a595b34b859a..ac2053fcb6fc 100644
--- a/documentation/docs/14-configuration.md
+++ b/documentation/docs/14-configuration.md
@@ -16,7 +16,6 @@ const config = {
kit: {
adapter: undefined,
- amp: false,
appDir: '_app',
browser: {
hydrate: true,
@@ -92,10 +91,6 @@ export default config;
Required when running `svelte-kit build` and determines how the output is converted for different platforms. See [Adapters](/docs/adapters).
-### amp
-
-Enable [AMP](/docs/seo#amp) mode.
-
### appDir
The directory relative to `paths.assets` where the built JS and CSS (and imported assets) are served from. (The filenames therein contain content-based hashes, meaning they can be cached indefinitely). Must not start or end with `/`.
diff --git a/documentation/docs/16-seo.md b/documentation/docs/16-seo.md
index c75e61864b79..0e61d988e93c 100644
--- a/documentation/docs/16-seo.md
+++ b/documentation/docs/16-seo.md
@@ -22,7 +22,7 @@ SvelteKit redirects pathnames with trailing slashes to ones without (or vice ver
### Manual setup
-#### <title> and <meta>
+#### <title> and <meta>
Every page should have well-written and unique `
` and `` elements inside a [``](https://svelte.dev/docs#template-syntax-svelte-head). Guidance on how to write descriptive titles and descriptions, along with other suggestions on making content understandable by search engines, can be found on Google's [Lighthouse SEO audits](https://web.dev/lighthouse-seo/) documentation.
@@ -82,8 +82,40 @@ export async function get() {
#### AMP
-An unfortunate reality of modern web development is that it is sometimes necessary to create an [Accelerated Mobile Pages (AMP)](https://amp.dev/) version of your site. In SvelteKit this can be done by setting the [`amp`](/docs/configuration#amp) config option, which has the following effects:
+An unfortunate reality of modern web development is that it is sometimes necessary to create an [Accelerated Mobile Pages (AMP)](https://amp.dev/) version of your site. In SvelteKit this can be done by enforcing the following [configuration](/docs/configuration) options...
-- Client-side JavaScript, including the router, is disabled
-- Styles are concatenated into `
+
+
+`;
+
+/** @param {string} html */
+export function transform(html) {
+ return html
+ .replace(/`)
+ .replace(/
-
- `;
-
- if (options.service_worker) {
- head +=
- '';
-
- body += ``;
- }
- } else {
- if (inlined_style) {
- const attributes = [];
- if (options.dev) attributes.push(' data-sveltekit');
- if (csp.style_needs_nonce) attributes.push(` nonce="${csp.nonce}"`);
+ if (inlined_style) {
+ const attributes = [];
+ if (options.dev) attributes.push(' data-sveltekit');
+ if (csp.style_needs_nonce) attributes.push(` nonce="${csp.nonce}"`);
- csp.add_style(inlined_style);
+ csp.add_style(inlined_style);
- head += `\n\t`;
- }
+ head += `\n\t`;
+ }
- // prettier-ignore
- head += Array.from(stylesheets)
- .map((dep) => {
- const attributes = [
- 'rel="stylesheet"',
- `href="${options.prefix + dep}"`
- ];
+ // prettier-ignore
+ head += Array.from(stylesheets)
+ .map((dep) => {
+ const attributes = [
+ 'rel="stylesheet"',
+ `href="${options.prefix + dep}"`
+ ];
+
+ if (csp.style_needs_nonce) {
+ attributes.push(`nonce="${csp.nonce}"`);
+ }
- if (csp.style_needs_nonce) {
- attributes.push(`nonce="${csp.nonce}"`);
- }
+ if (styles.has(dep)) {
+ // don't load stylesheets that are already inlined
+ // include them in disabled state so that Vite can detect them and doesn't try to add them
+ attributes.push('disabled', 'media="(max-width: 0)"');
+ }
- if (styles.has(dep)) {
- // don't load stylesheets that are already inlined
- // include them in disabled state so that Vite can detect them and doesn't try to add them
- attributes.push('disabled', 'media="(max-width: 0)"');
- }
+ return `\n\t`;
+ })
+ .join('');
- return `\n\t`;
- })
+ if (page_config.router || page_config.hydrate) {
+ head += Array.from(modulepreloads)
+ .map((dep) => `\n\t`)
.join('');
- if (page_config.router || page_config.hydrate) {
- head += Array.from(modulepreloads)
- .map((dep) => `\n\t`)
- .join('');
-
- const attributes = ['type="module"', `data-sveltekit-hydrate="${target}"`];
+ const attributes = ['type="module"', `data-sveltekit-hydrate="${target}"`];
- csp.add_script(init_app);
+ csp.add_script(init_app);
- if (csp.script_needs_nonce) {
- attributes.push(`nonce="${csp.nonce}"`);
- }
+ if (csp.script_needs_nonce) {
+ attributes.push(`nonce="${csp.nonce}"`);
+ }
- body += `\n\t\t`;
+ body += `\n\t\t`;
- body += serialized_data
- .map(({ url, body, response }) =>
- render_json_payload_script(
- { type: 'data', url, body: typeof body === 'string' ? hash(body) : undefined },
- response
- )
+ body += serialized_data
+ .map(({ url, body, response }) =>
+ render_json_payload_script(
+ { type: 'data', url, body: typeof body === 'string' ? hash(body) : undefined },
+ response
)
- .join('\n\t');
+ )
+ .join('\n\t');
- if (shadow_props) {
- body += render_json_payload_script({ type: 'props' }, shadow_props);
- }
+ if (shadow_props) {
+ body += render_json_payload_script({ type: 'props' }, shadow_props);
}
+ }
- if (options.service_worker) {
- // always include service worker unless it's turned off explicitly
- csp.add_script(init_service_worker);
+ if (options.service_worker) {
+ // always include service worker unless it's turned off explicitly
+ csp.add_script(init_service_worker);
- head += `
- `;
- }
+ head += `
+ `;
}
- if (state.prerender && !options.amp) {
+ if (state.prerender) {
const http_equiv = [];
const csp_headers = csp.get_meta();
diff --git a/packages/kit/src/utils/filesystem.js b/packages/kit/src/utils/filesystem.js
index fbc201f401bc..dc63b0ed8570 100644
--- a/packages/kit/src/utils/filesystem.js
+++ b/packages/kit/src/utils/filesystem.js
@@ -13,7 +13,7 @@ export function mkdirp(dir) {
/** @param {string} path */
export function rimraf(path) {
- (fs.rmSync || fs.rmdirSync)(path, { recursive: true, force: true });
+ fs.rmSync(path, { force: true, recursive: true });
}
/**
diff --git a/packages/kit/test/apps/amp/package.json b/packages/kit/test/apps/amp/package.json
index 8cf523e3d410..a66b74094572 100644
--- a/packages/kit/test/apps/amp/package.json
+++ b/packages/kit/test/apps/amp/package.json
@@ -12,8 +12,10 @@
"test:build": "playwright test"
},
"devDependencies": {
+ "@sveltejs/amp": "workspace:*",
"@sveltejs/kit": "workspace:*",
"cross-env": "^7.0.3",
+ "purify-css": "^1.2.5",
"svelte": "^3.43.0",
"svelte-check": "^2.5.0",
"typescript": "~4.6.2"
diff --git a/packages/kit/test/apps/amp/src/app.html b/packages/kit/test/apps/amp/src/app.html
index c462a30011e5..bfb96ec90242 100644
--- a/packages/kit/test/apps/amp/src/app.html
+++ b/packages/kit/test/apps/amp/src/app.html
@@ -3,7 +3,7 @@
-
+
%svelte.head%
diff --git a/packages/kit/test/apps/amp/src/hooks.js b/packages/kit/test/apps/amp/src/hooks.js
new file mode 100644
index 000000000000..c75f6f29116a
--- /dev/null
+++ b/packages/kit/test/apps/amp/src/hooks.js
@@ -0,0 +1,26 @@
+import purify from 'purify-css';
+import * as amp from '@sveltejs/amp';
+
+/** @type {import('@sveltejs/kit').Handle} */
+export async function handle({ event, resolve }) {
+ const response = await resolve(event, {
+ transformPage: ({ html }) => {
+ html = amp.transform(html);
+
+ // remove unused CSS
+ let css = '';
+ const markup = html.replace(
+ /`;
+ }
+ );
+
+ css = purify(markup, css);
+ return markup.replace('', `${css}`);
+ }
+ });
+
+ return response;
+}
diff --git a/packages/kit/test/apps/amp/src/routes/http-equiv/cache-control.svelte b/packages/kit/test/apps/amp/src/routes/http-equiv/cache-control.svelte
new file mode 100644
index 000000000000..6be73f14d259
--- /dev/null
+++ b/packages/kit/test/apps/amp/src/routes/http-equiv/cache-control.svelte
@@ -0,0 +1,14 @@
+
+
+
the cache-control headers should be removed from this page