From 1466cb94b581dd0136407d6ae24ddeef7e177763 Mon Sep 17 00:00:00 2001 From: Bob Fanger Date: Sun, 24 Nov 2019 22:35:16 +0100 Subject: [PATCH] feat: sapper export --no-subfolders Prevent trailing slash redirect for hosts that prefer `export/foo.htm` instead of `export/foo/index.htm` (github pages) --- site/content/docs/10-exporting.md | 2 + src/api/export.ts | 8 +- src/cli.ts | 3 + .../content/example-192.png | Bin 0 -> 5334 bytes .../content/example-512.png | Bin 0 -> 15358 bytes .../export-no-subfolders/content/test.pdf | Bin 0 -> 5681 bytes .../export-no-subfolders/rollup.config.js | 58 +++++++++++++ test/apps/export-no-subfolders/src/client.js | 9 ++ .../src/routes/_error.svelte | 10 +++ .../src/routes/blog/[slug].html | 24 +++++ .../src/routes/blog/[slug].json.js | 19 ++++ .../src/routes/blog/_posts.js | 5 ++ .../src/routes/blog/index.html | 17 ++++ .../src/routes/blog/index.json.js | 9 ++ .../src/routes/boom/[a]/[b].html.svelte | 12 +++ .../src/routes/boom/[a]/[b].svelte | 12 +++ .../src/routes/boom/[a]/index.svelte | 16 ++++ .../src/routes/boom/index.svelte | 7 ++ .../src/routes/img/[slug].png.js | 15 ++++ .../src/routes/index.svelte | 20 +++++ .../src/routes/pdfs/[slug].pdf.js | 15 ++++ test/apps/export-no-subfolders/src/server.js | 13 +++ .../src/service-worker.js | 82 ++++++++++++++++++ .../export-no-subfolders/src/template.html | 14 +++ .../export-no-subfolders/static/global.css | 3 + .../apps/export-no-subfolders/static/test.pdf | Bin 0 -> 5681 bytes test/apps/export-no-subfolders/test.ts | 50 +++++++++++ 27 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 test/apps/export-no-subfolders/content/example-192.png create mode 100644 test/apps/export-no-subfolders/content/example-512.png create mode 100644 test/apps/export-no-subfolders/content/test.pdf create mode 100644 test/apps/export-no-subfolders/rollup.config.js create mode 100644 test/apps/export-no-subfolders/src/client.js create mode 100644 test/apps/export-no-subfolders/src/routes/_error.svelte create mode 100644 test/apps/export-no-subfolders/src/routes/blog/[slug].html create mode 100644 test/apps/export-no-subfolders/src/routes/blog/[slug].json.js create mode 100644 test/apps/export-no-subfolders/src/routes/blog/_posts.js create mode 100644 test/apps/export-no-subfolders/src/routes/blog/index.html create mode 100644 test/apps/export-no-subfolders/src/routes/blog/index.json.js create mode 100644 test/apps/export-no-subfolders/src/routes/boom/[a]/[b].html.svelte create mode 100644 test/apps/export-no-subfolders/src/routes/boom/[a]/[b].svelte create mode 100644 test/apps/export-no-subfolders/src/routes/boom/[a]/index.svelte create mode 100644 test/apps/export-no-subfolders/src/routes/boom/index.svelte create mode 100644 test/apps/export-no-subfolders/src/routes/img/[slug].png.js create mode 100644 test/apps/export-no-subfolders/src/routes/index.svelte create mode 100644 test/apps/export-no-subfolders/src/routes/pdfs/[slug].pdf.js create mode 100644 test/apps/export-no-subfolders/src/server.js create mode 100644 test/apps/export-no-subfolders/src/service-worker.js create mode 100644 test/apps/export-no-subfolders/src/template.html create mode 100644 test/apps/export-no-subfolders/static/global.css create mode 100644 test/apps/export-no-subfolders/static/test.pdf create mode 100644 test/apps/export-no-subfolders/test.ts diff --git a/site/content/docs/10-exporting.md b/site/content/docs/10-exporting.md index 447d4185a..f92857949 100644 --- a/site/content/docs/10-exporting.md +++ b/site/content/docs/10-exporting.md @@ -69,3 +69,5 @@ Because `sapper export` writes to the filesystem, it isn't possible to have two The solution is to rename one of the routes to avoid conflict — for example, `src/routes/foo-bar.js`. (Note that you would also need to update any code that fetches data from `/foo/bar` to reference `/foo-bar` instead.) For *pages*, we skirt around this problem by writing `export/foo/index.html` instead of `export/foo`. + +For hosts that prefer `export/foo.html` instead of `export/foo/index.html` pass the `--no-subfolders` option to prevent a redirect with a trailing slash added to the url. \ No newline at end of file diff --git a/src/api/export.ts b/src/api/export.ts index d193ffaa8..1c6e09473 100644 --- a/src/api/export.ts +++ b/src/api/export.ts @@ -22,6 +22,7 @@ type Opts = { static?: string; basepath?: string; host_header?: string; + subfolders?: boolean, timeout?: number | false; concurrent?: number; oninfo?: ({ message }: { message: string }) => void; @@ -82,6 +83,7 @@ async function _export({ export_dir = '__sapper__/export', basepath = '', host_header = undefined, + subfolders = true, timeout = 5000, concurrent = 8, oninfo = noop, @@ -147,7 +149,11 @@ async function _export({ if (is_html) { if (!file.endsWith('.html')) { - file = file === '' ? 'index.html' : `${file}/index.html`; + if (file === '') { + file = 'index.html'; + } else if (file !== 'manifest.json') { + file = subfolders ? `${file}/index.html` : `${file}.html`; + } } if (typeof body === 'string') { diff --git a/src/cli.ts b/src/cli.ts index 9e961bfef..e7cccd15d 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -207,6 +207,7 @@ prog.command('export [dest]') .option('--build-dir', 'Intermediate build directory', '__sapper__/build') .option('--ext', 'Custom page route extensions (space separated)', '.svelte .html') .option('--entry', 'Custom entry points (space separated)', '/') + .option('--subfolders', 'Generate /path/index.html instead of /path.html', true) .action(async (dest = '__sapper__/export', opts: { build: boolean; legacy: boolean; @@ -223,6 +224,7 @@ prog.command('export [dest]') 'build-dir': string; ext: string; entry: string; + subfolders: boolean; }) => { try { if (opts.build) { @@ -244,6 +246,7 @@ prog.command('export [dest]') timeout: opts.timeout, concurrent: opts.concurrent, entry: opts.entry, + subfolders: opts.subfolders, oninfo: event => { console.log(colors.bold().cyan(`> ${event.message}`)); diff --git a/test/apps/export-no-subfolders/content/example-192.png b/test/apps/export-no-subfolders/content/example-192.png new file mode 100644 index 0000000000000000000000000000000000000000..0a9e4b147e0e398ed739a6445dee3c480c67f97c GIT binary patch literal 5334 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

$wgR5 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 M4&dQY*M$Q92deKvQUCw| literal 0 HcmV?d00001 diff --git a/test/apps/export-no-subfolders/rollup.config.js b/test/apps/export-no-subfolders/rollup.config.js new file mode 100644 index 000000000..b926ab4ad --- /dev/null +++ b/test/apps/export-no-subfolders/rollup.config.js @@ -0,0 +1,58 @@ +import resolve from '@rollup/plugin-node-resolve'; +import replace from '@rollup/plugin-replace'; +import svelte from 'rollup-plugin-svelte'; + +const mode = process.env.NODE_ENV; +const dev = mode === 'development'; + +const config = require('../../../config/rollup.js'); + +export default { + client: { + input: config.client.input(), + output: config.client.output(), + plugins: [ + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + dev, + hydratable: true, + emitCss: true + }), + resolve() + ] + }, + + server: { + input: config.server.input(), + output: config.server.output(), + plugins: [ + replace({ + 'process.browser': false, + 'process.env.NODE_ENV': JSON.stringify(mode) + }), + svelte({ + generate: 'ssr', + dev + }), + resolve({ + preferBuiltins: true + }) + ], + external: ['sirv', 'polka'] + }, + + serviceworker: { + input: config.serviceworker.input(), + output: config.serviceworker.output(), + plugins: [ + resolve(), + replace({ + 'process.browser': true, + 'process.env.NODE_ENV': JSON.stringify(mode) + }) + ] + } +}; diff --git a/test/apps/export-no-subfolders/src/client.js b/test/apps/export-no-subfolders/src/client.js new file mode 100644 index 000000000..249d80671 --- /dev/null +++ b/test/apps/export-no-subfolders/src/client.js @@ -0,0 +1,9 @@ +import * as sapper from '@sapper/app'; + +window.start = () => sapper.start({ + target: document.querySelector('#sapper') +}); + +window.prefetchRoutes = () => sapper.prefetchRoutes(); +window.prefetch = href => sapper.prefetch(href); +window.goto = href => sapper.goto(href); diff --git a/test/apps/export-no-subfolders/src/routes/_error.svelte b/test/apps/export-no-subfolders/src/routes/_error.svelte new file mode 100644 index 000000000..a8fca7e98 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/_error.svelte @@ -0,0 +1,10 @@ + + +

{status}

+ +

{error.message}

+ +
{error.stack}
diff --git a/test/apps/export-no-subfolders/src/routes/blog/[slug].html b/test/apps/export-no-subfolders/src/routes/blog/[slug].html new file mode 100644 index 000000000..b00b43c1f --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/blog/[slug].html @@ -0,0 +1,24 @@ + + + + +

{post.title}

+ +{#if post.src} + + + + +{/if} + +{#if post.pdf} +
{post.pdf} +{/if} diff --git a/test/apps/export-no-subfolders/src/routes/blog/[slug].json.js b/test/apps/export-no-subfolders/src/routes/blog/[slug].json.js new file mode 100644 index 000000000..f940aed32 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/blog/[slug].json.js @@ -0,0 +1,19 @@ +import posts from './_posts.js'; + +export function get(req, res) { + const post = posts.find(post => post.slug === req.params.slug); + + if (post) { + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify(post)); + } else { + res.writeHead(404, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify({ message: 'not found' })); + } +} diff --git a/test/apps/export-no-subfolders/src/routes/blog/_posts.js b/test/apps/export-no-subfolders/src/routes/blog/_posts.js new file mode 100644 index 000000000..c3f209651 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/blog/_posts.js @@ -0,0 +1,5 @@ +export default [ + { slug: 'foo', title: 'once upon a foo', src: 'img/example-512.png', srcset: 'img/example-512.png 512w, img/example-192.png 192w', pdf: 'pdfs/test.pdf' }, + { slug: 'bar', title: 'a bar is born' }, + { slug: 'baz', title: 'bazzily ever after' } +]; diff --git a/test/apps/export-no-subfolders/src/routes/blog/index.html b/test/apps/export-no-subfolders/src/routes/blog/index.html new file mode 100644 index 000000000..d12e4321d --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/blog/index.html @@ -0,0 +1,17 @@ + + + + +

blog

+ +{#each posts as post} +

{post.title}

+{/each} \ No newline at end of file diff --git a/test/apps/export-no-subfolders/src/routes/blog/index.json.js b/test/apps/export-no-subfolders/src/routes/blog/index.json.js new file mode 100644 index 000000000..46dc233ba --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/blog/index.json.js @@ -0,0 +1,9 @@ +import posts from './_posts.js'; + +export function get(req, res) { + res.writeHead(200, { + 'Content-Type': 'application/json' + }); + + res.end(JSON.stringify(posts)); +} diff --git a/test/apps/export-no-subfolders/src/routes/boom/[a]/[b].html.svelte b/test/apps/export-no-subfolders/src/routes/boom/[a]/[b].html.svelte new file mode 100644 index 000000000..7134cbcbd --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/boom/[a]/[b].html.svelte @@ -0,0 +1,12 @@ + + + + +

{a}/{b}.html

\ No newline at end of file diff --git a/test/apps/export-no-subfolders/src/routes/boom/[a]/[b].svelte b/test/apps/export-no-subfolders/src/routes/boom/[a]/[b].svelte new file mode 100644 index 000000000..9b7b9b45f --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/boom/[a]/[b].svelte @@ -0,0 +1,12 @@ + + + + +

{a}/{b}

\ No newline at end of file diff --git a/test/apps/export-no-subfolders/src/routes/boom/[a]/index.svelte b/test/apps/export-no-subfolders/src/routes/boom/[a]/index.svelte new file mode 100644 index 000000000..b33133b12 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/boom/[a]/index.svelte @@ -0,0 +1,16 @@ + + + + +{#each list as b} + {a}/{b} + {a}/{b}.html +{/each} \ No newline at end of file diff --git a/test/apps/export-no-subfolders/src/routes/boom/index.svelte b/test/apps/export-no-subfolders/src/routes/boom/index.svelte new file mode 100644 index 000000000..84ed15847 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/boom/index.svelte @@ -0,0 +1,7 @@ + + +{#each list as a} + {a} +{/each} \ No newline at end of file diff --git a/test/apps/export-no-subfolders/src/routes/img/[slug].png.js b/test/apps/export-no-subfolders/src/routes/img/[slug].png.js new file mode 100644 index 000000000..f6191e50e --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/img/[slug].png.js @@ -0,0 +1,15 @@ +const fs = require('fs'); +const path = require('path'); +const cwd = process.cwd(); + +export function get(req, res) { + + const { slug } = req.params; + const image = path.join(cwd, `/content/${slug}.png`); + + const s = fs.createReadStream(image); + s.on('open', () => { + res.writeHead(200, { 'Content-Type': 'image/png' }); + s.pipe(res); + }); +} diff --git a/test/apps/export-no-subfolders/src/routes/index.svelte b/test/apps/export-no-subfolders/src/routes/index.svelte new file mode 100644 index 000000000..0bb9b3774 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/index.svelte @@ -0,0 +1,20 @@ + + + + +

Great success!

+ +blog + +empty anchor + +empty anchor #2 + +empty anchor #3 + +empty anchor #4 +empty anchor #5 + +empty anchor #6 +boom +pdf file \ No newline at end of file diff --git a/test/apps/export-no-subfolders/src/routes/pdfs/[slug].pdf.js b/test/apps/export-no-subfolders/src/routes/pdfs/[slug].pdf.js new file mode 100644 index 000000000..8063d6037 --- /dev/null +++ b/test/apps/export-no-subfolders/src/routes/pdfs/[slug].pdf.js @@ -0,0 +1,15 @@ +const fs = require('fs'); +const path = require('path'); +const cwd = process.cwd(); + +export function get(req, res, next) { + + const { slug } = req.params; + const image = path.join(cwd, `/content/${slug}.pdf`); + + const s = fs.createReadStream(image); + s.on('open', () => { + res.writeHead(200, { 'Content-Type': 'application/pdf' }); + s.pipe(res); + }); +} diff --git a/test/apps/export-no-subfolders/src/server.js b/test/apps/export-no-subfolders/src/server.js new file mode 100644 index 000000000..4ccaf34a1 --- /dev/null +++ b/test/apps/export-no-subfolders/src/server.js @@ -0,0 +1,13 @@ +import sirv from 'sirv'; +import polka from 'polka'; +import * as sapper from '@sapper/server'; + +import { start, dev } from '../../common.js'; + +const app = polka() + .use( + sirv('static', { dev }), + sapper.middleware() + ); + +start(app); diff --git a/test/apps/export-no-subfolders/src/service-worker.js b/test/apps/export-no-subfolders/src/service-worker.js new file mode 100644 index 000000000..4ba51adc3 --- /dev/null +++ b/test/apps/export-no-subfolders/src/service-worker.js @@ -0,0 +1,82 @@ +import * as sapper from '@sapper/service-worker'; + +const ASSETS = `cache${sapper.timestamp}`; + +// `shell` is an array of all the files generated by webpack, +// `files` is an array of everything in the `static` directory +const to_cache = sapper.shell.concat(sapper.files); +const cached = new Set(to_cache); + +self.addEventListener('install', event => { + event.waitUntil( + caches + .open(ASSETS) + .then(cache => cache.addAll(to_cache)) + .then(() => { + self.skipWaiting(); + }) + ); +}); + +self.addEventListener('activate', event => { + event.waitUntil( + caches.keys().then(async keys => { + // delete old caches + for (const key of keys) { + if (key !== ASSETS) await caches.delete(key); + } + + self.clients.claim(); + }) + ); +}); + +self.addEventListener('fetch', event => { + if (event.request.method !== 'GET') return; + + const url = new URL(event.request.url); + + // don't try to handle e.g. data: URIs + if (!url.protocol.startsWith('http')) return; + + // ignore dev server requests + if (url.hostname === self.location.hostname && url.port !== self.location.port) return; + + // always serve assets and webpack-generated files from cache + if (url.host === self.location.host && cached.has(url.pathname)) { + event.respondWith(caches.match(event.request)); + return; + } + + // for pages, you might want to serve a shell `index.html` file, + // which Sapper has generated for you. It's not right for every + // app, but if it's right for yours then uncomment this section + /* + if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) { + event.respondWith(caches.match('/index.html')); + return; + } + */ + + if (event.request.cache === 'only-if-cached') return; + + // for everything else, try the network first, falling back to + // cache if the user is offline. (If the pages never change, you + // might prefer a cache-first approach to a network-first one.) + event.respondWith( + caches + .open(`offline${sapper.timestamp}`) + .then(async cache => { + try { + const response = await fetch(event.request); + cache.put(event.request, response.clone()); + return response; + } catch (err) { + const response = await cache.match(event.request); + if (response) return response; + + throw err; + } + }) + ); +}); diff --git a/test/apps/export-no-subfolders/src/template.html b/test/apps/export-no-subfolders/src/template.html new file mode 100644 index 000000000..75027cea6 --- /dev/null +++ b/test/apps/export-no-subfolders/src/template.html @@ -0,0 +1,14 @@ + + + + + + %sapper.base% + %sapper.styles% + %sapper.head% + %sapper.scripts% + + +
%sapper.html%
+ + diff --git a/test/apps/export-no-subfolders/static/global.css b/test/apps/export-no-subfolders/static/global.css new file mode 100644 index 000000000..800f57ad1 --- /dev/null +++ b/test/apps/export-no-subfolders/static/global.css @@ -0,0 +1,3 @@ +body { + font-family: 'Comic Sans MS'; +} \ No newline at end of file diff --git a/test/apps/export-no-subfolders/static/test.pdf b/test/apps/export-no-subfolders/static/test.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b1d78ce502355fe158957e918ed337a6f21a41af GIT binary patch literal 5681 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 M4&dQY*M$Q92deKvQUCw| literal 0 HcmV?d00001 diff --git a/test/apps/export-no-subfolders/test.ts b/test/apps/export-no-subfolders/test.ts new file mode 100644 index 000000000..ef3e50ff5 --- /dev/null +++ b/test/apps/export-no-subfolders/test.ts @@ -0,0 +1,50 @@ +import * as assert from 'assert'; +import { walk } from '../../utils'; +import * as api from '../../../api'; + +describe('export-no-subfolders', function () { + this.timeout(10000); + + // hooks + before('build app', () => api.build({ cwd: __dirname })); + before('export app', () => api.export({ cwd: __dirname, subfolders: false })); + + // tests + it('exports to ${path}.html instead of ${path}/index.html', () => { + const files = walk(`${__dirname}/__sapper__/export`); + + const client_assets = files.filter(file => file.startsWith('client/')); + const non_client_assets = files.filter(file => !file.startsWith('client/')).sort(); + + assert.ok(client_assets.length > 0); + + const boom = ['boom.html']; + for (let a = 1; a <= 20; a += 1) { + boom.push(`boom/${a}.html`); + for (let b = 1; b <= 20; b += 1) { + boom.push(`boom/${a}/${b}.html`); + } + } + + assert.deepEqual(non_client_assets.sort(), [ + 'blog.json', + 'blog/bar.json', + 'blog/bar.html', + 'blog/baz.json', + 'blog/baz.html', + 'blog/foo.json', + 'blog/foo.html', + 'blog.html', + 'global.css', + 'index.html', + 'manifest.json', + 'service-worker-index.html', + 'service-worker.js', + 'test.pdf', + 'img/example-192.png', + 'img/example-512.png', + 'pdfs/test.pdf', + ...boom + ].sort()); + }); +});