mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-18 13:35:08 +00:00
Merge pull request #568 from nolanlawson/nolan/preload-in-export
fix: add link rel=preload for exported sites
This commit is contained in:
46
package-lock.json
generated
46
package-lock.json
generated
@@ -1986,7 +1986,8 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -2007,12 +2008,14 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -2027,17 +2030,20 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -2154,7 +2160,8 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@@ -2166,6 +2173,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -2180,6 +2188,7 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@@ -2187,12 +2196,14 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@@ -2211,6 +2222,7 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@@ -2291,7 +2303,8 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -2303,6 +2316,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@@ -2388,7 +2402,8 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@@ -2424,6 +2439,7 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@@ -2443,6 +2459,7 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@@ -2486,12 +2503,14 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2687,6 +2706,11 @@
|
|||||||
"uglify-js": "3.4.x"
|
"uglify-js": "3.4.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"http-link-header": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-link-header/-/http-link-header-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-z6YOZ8ZEnejkcCWlGZzYXNa6i+ZaTfiTg3WhlV/YvnNya3W/RbX1bMVUMTuCrg/DrtTCQxaFCkXCz4FtLpcebg=="
|
||||||
|
},
|
||||||
"https-browserify": {
|
"https-browserify": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"html-minifier": "^3.5.21",
|
"html-minifier": "^3.5.21",
|
||||||
|
"http-link-header": "^1.0.2",
|
||||||
"shimport": "0.0.14",
|
"shimport": "0.0.14",
|
||||||
"sourcemap-codec": "^1.4.4",
|
"sourcemap-codec": "^1.4.4",
|
||||||
"string-hash": "^1.1.3"
|
"string-hash": "^1.1.3"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import clean_html from './utils/clean_html';
|
|||||||
import minify_html from './utils/minify_html';
|
import minify_html from './utils/minify_html';
|
||||||
import Deferred from './utils/Deferred';
|
import Deferred from './utils/Deferred';
|
||||||
import { noop } from './utils/noop';
|
import { noop } from './utils/noop';
|
||||||
|
import { parse as parseLinkHeader } from 'http-link-header';
|
||||||
import { rimraf, copy, mkdirp } from './utils/fs_utils';
|
import { rimraf, copy, mkdirp } from './utils/fs_utils';
|
||||||
|
|
||||||
type Opts = {
|
type Opts = {
|
||||||
@@ -22,6 +23,12 @@ type Opts = {
|
|||||||
onfile?: ({ file, size, status }: { file: string, size: number, status: number }) => void;
|
onfile?: ({ file, size, status }: { file: string, size: number, status: number }) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Ref = {
|
||||||
|
uri: string,
|
||||||
|
rel: string,
|
||||||
|
as: string
|
||||||
|
};
|
||||||
|
|
||||||
function resolve(from: string, to: string) {
|
function resolve(from: string, to: string) {
|
||||||
return url.parse(url.resolve(from, to));
|
return url.parse(url.resolve(from, to));
|
||||||
}
|
}
|
||||||
@@ -137,38 +144,49 @@ async function _export({
|
|||||||
clearTimeout(the_timeout); // prevent it hanging at the end
|
clearTimeout(the_timeout); // prevent it hanging at the end
|
||||||
|
|
||||||
let type = r.headers.get('Content-Type');
|
let type = r.headers.get('Content-Type');
|
||||||
|
|
||||||
let body = await r.text();
|
let body = await r.text();
|
||||||
|
|
||||||
const range = ~~(r.status / 100);
|
const range = ~~(r.status / 100);
|
||||||
|
|
||||||
if (range === 2) {
|
if (range === 2) {
|
||||||
if (type === 'text/html' && pathname !== '/service-worker-index.html') {
|
if (type === 'text/html') {
|
||||||
const cleaned = clean_html(body);
|
// parse link rel=preload headers and embed them in the HTML
|
||||||
|
let link = parseLinkHeader(r.headers.get('Link') || '');
|
||||||
|
link.refs.forEach((ref: Ref) => {
|
||||||
|
if (ref.rel === 'preload') {
|
||||||
|
body = body.replace('</head>',
|
||||||
|
`<link rel="preload" as=${JSON.stringify(ref.as)} href=${JSON.stringify(ref.uri)}></head>`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (pathname !== '/service-worker-index.html') {
|
||||||
|
const cleaned = clean_html(body);
|
||||||
|
|
||||||
const q = yootils.queue(8);
|
const q = yootils.queue(8);
|
||||||
let promise;
|
let promise;
|
||||||
|
|
||||||
const base_match = /<base ([\s\S]+?)>/m.exec(cleaned);
|
const base_match = /<base ([\s\S]+?)>/m.exec(cleaned);
|
||||||
const base_href = base_match && get_href(base_match[1]);
|
const base_href = base_match && get_href(base_match[1]);
|
||||||
const base = resolve(url.href, base_href);
|
const base = resolve(url.href, base_href);
|
||||||
|
|
||||||
let match;
|
let match;
|
||||||
let pattern = /<a ([\s\S]+?)>/gm;
|
let pattern = /<a ([\s\S]+?)>/gm;
|
||||||
|
|
||||||
while (match = pattern.exec(cleaned)) {
|
while (match = pattern.exec(cleaned)) {
|
||||||
const attrs = match[1];
|
const attrs = match[1];
|
||||||
const href = get_href(attrs);
|
const href = get_href(attrs);
|
||||||
|
|
||||||
if (href) {
|
if (href) {
|
||||||
const url = resolve(base.href, href);
|
const url = resolve(base.href, href);
|
||||||
|
|
||||||
if (url.protocol === protocol && url.host === host) {
|
if (url.protocol === protocol && url.host === host) {
|
||||||
promise = q.add(() => handle(url));
|
promise = q.add(() => handle(url));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
await promise;
|
await promise;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
test/apps/export-webpack/src/client.js
Normal file
9
test/apps/export-webpack/src/client.js
Normal file
@@ -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);
|
||||||
3
test/apps/export-webpack/src/routes/_error.svelte
Normal file
3
test/apps/export-webpack/src/routes/_error.svelte
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<h1>{status}</h1>
|
||||||
|
|
||||||
|
<p>{error.message}</p>
|
||||||
13
test/apps/export-webpack/src/routes/blog/[slug].html
Normal file
13
test/apps/export-webpack/src/routes/blog/[slug].html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<script context="module">
|
||||||
|
export function preload({ params }) {
|
||||||
|
return this.fetch(`blog/${params.slug}.json`).then(r => r.json()).then(post => {
|
||||||
|
return { post };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let post;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>{post.title}</h1>
|
||||||
19
test/apps/export-webpack/src/routes/blog/[slug].json.js
Normal file
19
test/apps/export-webpack/src/routes/blog/[slug].json.js
Normal file
@@ -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' }));
|
||||||
|
}
|
||||||
|
}
|
||||||
5
test/apps/export-webpack/src/routes/blog/_posts.js
Normal file
5
test/apps/export-webpack/src/routes/blog/_posts.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export default [
|
||||||
|
{ slug: 'foo', title: 'once upon a foo' },
|
||||||
|
{ slug: 'bar', title: 'a bar is born' },
|
||||||
|
{ slug: 'baz', title: 'bazzily ever after' }
|
||||||
|
];
|
||||||
17
test/apps/export-webpack/src/routes/blog/index.html
Normal file
17
test/apps/export-webpack/src/routes/blog/index.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script context="module">
|
||||||
|
export function preload() {
|
||||||
|
return this.fetch('blog.json').then(r => r.json()).then(posts => {
|
||||||
|
return { posts };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export let posts;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h1>blog</h1>
|
||||||
|
|
||||||
|
{#each posts as post}
|
||||||
|
<p><a href="blog/{post.slug}">{post.title}</a></p>
|
||||||
|
{/each}
|
||||||
9
test/apps/export-webpack/src/routes/blog/index.json.js
Normal file
9
test/apps/export-webpack/src/routes/blog/index.json.js
Normal file
@@ -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));
|
||||||
|
}
|
||||||
4
test/apps/export-webpack/src/routes/index.svelte
Normal file
4
test/apps/export-webpack/src/routes/index.svelte
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<h1>Great success!</h1>
|
||||||
|
|
||||||
|
<a href="blog">blog</a>
|
||||||
|
<a href="">empty anchor</a>
|
||||||
15
test/apps/export-webpack/src/server.js
Normal file
15
test/apps/export-webpack/src/server.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import sirv from 'sirv';
|
||||||
|
import polka from 'polka';
|
||||||
|
import * as sapper from '@sapper/server';
|
||||||
|
|
||||||
|
const { PORT, NODE_ENV } = process.env;
|
||||||
|
const dev = NODE_ENV === 'development';
|
||||||
|
|
||||||
|
polka()
|
||||||
|
.use(
|
||||||
|
sirv('static', { dev }),
|
||||||
|
sapper.middleware()
|
||||||
|
)
|
||||||
|
.listen(PORT, err => {
|
||||||
|
if (err) console.log('error', err);
|
||||||
|
});
|
||||||
82
test/apps/export-webpack/src/service-worker.js
Normal file
82
test/apps/export-webpack/src/service-worker.js
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
14
test/apps/export-webpack/src/template.html
Normal file
14
test/apps/export-webpack/src/template.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
|
||||||
|
%sapper.base%
|
||||||
|
%sapper.styles%
|
||||||
|
%sapper.head%
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='sapper'>%sapper.html%</div>
|
||||||
|
%sapper.scripts%
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3
test/apps/export-webpack/static/global.css
Normal file
3
test/apps/export-webpack/static/global.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
body {
|
||||||
|
font-family: 'Comic Sans MS';
|
||||||
|
}
|
||||||
19
test/apps/export-webpack/test.ts
Normal file
19
test/apps/export-webpack/test.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import * as assert from 'assert';
|
||||||
|
import * as api from '../../../api';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
describe('export-webpack', function() {
|
||||||
|
this.timeout(10000);
|
||||||
|
|
||||||
|
// hooks
|
||||||
|
before(async () => {
|
||||||
|
await api.build({ cwd: __dirname, bundler: 'webpack' });
|
||||||
|
await api.export({ cwd: __dirname, bundler: 'webpack' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('injects <link rel=preload> tags', () => {
|
||||||
|
const index = fs.readFileSync(`${__dirname}/__sapper__/export/index.html`, 'utf8');
|
||||||
|
assert.ok(/rel=preload/.test(index));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
73
test/apps/export-webpack/webpack.config.js
Normal file
73
test/apps/export-webpack/webpack.config.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
const webpack = require('webpack');
|
||||||
|
const config = require('../../../config/webpack.js');
|
||||||
|
|
||||||
|
const mode = process.env.NODE_ENV;
|
||||||
|
const dev = mode === 'development';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
client: {
|
||||||
|
entry: config.client.entry(),
|
||||||
|
output: config.client.output(),
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.mjs', '.js', '.json', '.html', '.svelte'],
|
||||||
|
mainFields: ['svelte', 'module', 'browser', 'main']
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(html|svelte)$/,
|
||||||
|
use: {
|
||||||
|
loader: 'svelte-loader',
|
||||||
|
options: {
|
||||||
|
dev,
|
||||||
|
hydratable: true,
|
||||||
|
hotReload: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
mode,
|
||||||
|
plugins: [
|
||||||
|
dev && new webpack.HotModuleReplacementPlugin(),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
'process.browser': true,
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(mode)
|
||||||
|
}),
|
||||||
|
].filter(Boolean),
|
||||||
|
devtool: dev ? 'inline-source-map' : 'source-map'
|
||||||
|
},
|
||||||
|
|
||||||
|
server: {
|
||||||
|
entry: config.server.entry(),
|
||||||
|
output: config.server.output(),
|
||||||
|
target: 'node',
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.mjs', '.js', '.json', '.html', '.svelte'],
|
||||||
|
mainFields: ['svelte', 'module', 'browser', 'main']
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(html|svelte)$/,
|
||||||
|
use: {
|
||||||
|
loader: 'svelte-loader',
|
||||||
|
options: {
|
||||||
|
css: false,
|
||||||
|
generate: 'ssr',
|
||||||
|
dev
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
mode: process.env.NODE_ENV
|
||||||
|
},
|
||||||
|
|
||||||
|
serviceworker: {
|
||||||
|
entry: config.serviceworker.entry(),
|
||||||
|
output: config.serviceworker.output(),
|
||||||
|
mode: process.env.NODE_ENV,
|
||||||
|
devtool: 'sourcemap'
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user