mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-13 19:45:26 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afcd643035 | ||
|
|
7cc2a03aae | ||
|
|
002718b609 | ||
|
|
45d216c64d | ||
|
|
3d69d483d7 | ||
|
|
54da524467 | ||
|
|
ee95240ca6 | ||
|
|
74d5d1f9c0 | ||
|
|
8c2688b1be | ||
|
|
e170e4af9b | ||
|
|
bc31c73c33 | ||
|
|
7798f8f684 | ||
|
|
70fd7038b0 | ||
|
|
c6af2ddfa3 | ||
|
|
65d0172abe | ||
|
|
1e22031765 | ||
|
|
46bf8f2b78 |
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,5 +1,22 @@
|
||||
# sapper changelog
|
||||
|
||||
## 0.18.5
|
||||
|
||||
* Bugfix
|
||||
|
||||
## 0.18.4
|
||||
|
||||
* Handle non-Sapper responses when exporting ([#382](https://github.com/sveltejs/sapper/issues/392))
|
||||
* Add `--dev-port` flag to `sapper dev` ([#381](https://github.com/sveltejs/sapper/issues/381))
|
||||
|
||||
## 0.18.3
|
||||
|
||||
* Fix service worker Rollup build config
|
||||
|
||||
## 0.18.2
|
||||
|
||||
* Update `pkg.files`
|
||||
|
||||
## 0.18.1
|
||||
|
||||
* Add live reloading ([#385](https://github.com/sveltejs/sapper/issues/385))
|
||||
|
||||
24
package-lock.json
generated
24
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sapper",
|
||||
"version": "0.17.1",
|
||||
"version": "0.18.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -5574,12 +5574,6 @@
|
||||
"integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
|
||||
"dev": true
|
||||
},
|
||||
"querystringify": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz",
|
||||
"integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==",
|
||||
"dev": true
|
||||
},
|
||||
"randomatic": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz",
|
||||
@@ -5872,12 +5866,6 @@
|
||||
"resolve-from": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
|
||||
@@ -7285,16 +7273,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz",
|
||||
"integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.0.0",
|
||||
"requires-port": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"use": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sapper",
|
||||
"version": "0.18.1",
|
||||
"version": "0.18.5",
|
||||
"description": "Military-grade apps, engineered by Svelte",
|
||||
"main": "dist/middleware.js",
|
||||
"bin": {
|
||||
@@ -10,6 +10,7 @@
|
||||
"*.js",
|
||||
"runtime",
|
||||
"webpack",
|
||||
"config",
|
||||
"sapper",
|
||||
"components",
|
||||
"dist"
|
||||
@@ -62,7 +63,6 @@
|
||||
"tiny-glob": "^0.2.2",
|
||||
"ts-node": "^7.0.1",
|
||||
"typescript": "^2.8.3",
|
||||
"url-parse": "^1.2.0",
|
||||
"walk-sync": "^0.3.2",
|
||||
"webpack": "^4.8.3",
|
||||
"webpack-format-messages": "^2.0.1"
|
||||
|
||||
@@ -55,7 +55,7 @@ async function execute(emitter: EventEmitter, {
|
||||
const route_objects = create_routes();
|
||||
|
||||
// create app/manifest/client.js and app/manifest/server.js
|
||||
create_main_manifests({ routes: route_objects });
|
||||
create_main_manifests({ bundler, routes: route_objects });
|
||||
|
||||
const { client, server, serviceworker } = create_compilers(validate_bundler(bundler), { webpack, rollup });
|
||||
|
||||
@@ -69,7 +69,7 @@ async function execute(emitter: EventEmitter, {
|
||||
fs.writeFileSync(path.join(dest, 'build.json'), JSON.stringify({
|
||||
bundler,
|
||||
shimport: bundler === 'rollup' && require('shimport/package.json').version,
|
||||
assets: client_result.assetsByChunkName
|
||||
assets: client_result.assets
|
||||
}));
|
||||
|
||||
const server_stats = await server.compile();
|
||||
@@ -84,7 +84,7 @@ async function execute(emitter: EventEmitter, {
|
||||
if (serviceworker) {
|
||||
create_serviceworker_manifest({
|
||||
routes: route_objects,
|
||||
client_files: client_result.assets.map((file: string) => `client/${file}`)
|
||||
client_files: client_result.chunks.map((file: string) => `client/${file}`)
|
||||
});
|
||||
|
||||
serviceworker_stats = await serviceworker.compile();
|
||||
|
||||
@@ -29,6 +29,8 @@ class Watcher extends EventEmitter {
|
||||
}
|
||||
port: number;
|
||||
closed: boolean;
|
||||
|
||||
dev_port: number;
|
||||
live: boolean;
|
||||
hot: boolean;
|
||||
|
||||
@@ -50,6 +52,7 @@ class Watcher extends EventEmitter {
|
||||
app = locations.app(),
|
||||
dest = locations.dest(),
|
||||
routes = locations.routes(),
|
||||
'dev-port': dev_port,
|
||||
live,
|
||||
hot,
|
||||
bundler,
|
||||
@@ -60,6 +63,7 @@ class Watcher extends EventEmitter {
|
||||
app: string,
|
||||
dest: string,
|
||||
routes: string,
|
||||
'dev-port': number,
|
||||
live: boolean,
|
||||
hot: boolean,
|
||||
bundler?: string,
|
||||
@@ -74,6 +78,7 @@ class Watcher extends EventEmitter {
|
||||
this.port = port;
|
||||
this.closed = false;
|
||||
|
||||
this.dev_port = dev_port;
|
||||
this.live = live;
|
||||
this.hot = hot;
|
||||
|
||||
@@ -120,11 +125,11 @@ class Watcher extends EventEmitter {
|
||||
mkdirp.sync(`${dest}/client`);
|
||||
if (this.bundler === 'rollup') copy_shimport(dest);
|
||||
|
||||
const dev_port = await ports.find(10000);
|
||||
if (!this.dev_port) this.dev_port = await ports.find(10000);
|
||||
|
||||
try {
|
||||
const routes = create_routes();
|
||||
create_main_manifests({ routes, dev_port });
|
||||
create_main_manifests({ bundler: this.bundler, routes, dev_port: this.dev_port });
|
||||
} catch (err) {
|
||||
this.emit('fatal', <events.FatalEvent>{
|
||||
message: err.message
|
||||
@@ -132,7 +137,7 @@ class Watcher extends EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
this.dev_server = new DevServer(dev_port);
|
||||
this.dev_server = new DevServer(this.dev_port);
|
||||
|
||||
this.filewatchers.push(
|
||||
watch_dir(
|
||||
@@ -145,11 +150,11 @@ class Watcher extends EventEmitter {
|
||||
},
|
||||
() => {
|
||||
const routes = create_routes();
|
||||
create_main_manifests({ routes, dev_port });
|
||||
create_main_manifests({ bundler: this.bundler, routes, dev_port: this.dev_port });
|
||||
|
||||
try {
|
||||
const routes = create_routes();
|
||||
create_main_manifests({ routes, dev_port });
|
||||
create_main_manifests({ bundler: this.bundler, routes, dev_port: this.dev_port });
|
||||
} catch (err) {
|
||||
this.emit('error', <events.ErrorEvent>{
|
||||
message: err.message
|
||||
@@ -280,10 +285,10 @@ class Watcher extends EventEmitter {
|
||||
fs.writeFileSync(path.join(dest, 'build.json'), JSON.stringify({
|
||||
bundler: this.bundler,
|
||||
shimport: this.bundler === 'rollup' && require('shimport/package.json').version,
|
||||
assets: result.assetsByChunkName
|
||||
assets: result.assets
|
||||
}, null, ' '));
|
||||
|
||||
const client_files = result.assets.map((file: string) => `client/${file}`);
|
||||
const client_files = result.chunks.map((file: string) => `client/${file}`);
|
||||
|
||||
create_serviceworker_manifest({
|
||||
routes: create_routes(),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as child_process from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as sander from 'sander';
|
||||
import URL from 'url-parse';
|
||||
import * as url from 'url';
|
||||
import fetch from 'node-fetch';
|
||||
import * as ports from 'port-authority';
|
||||
import { EventEmitter } from 'events';
|
||||
@@ -34,6 +34,12 @@ export function exporter(opts: Opts) {
|
||||
return emitter;
|
||||
}
|
||||
|
||||
function resolve(from: string, to: string) {
|
||||
return url.parse(url.resolve(from, to));
|
||||
}
|
||||
|
||||
type URL = url.UrlWithStringQuery;
|
||||
|
||||
async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
const export_dir = path.join(opts.dest, opts.basepath);
|
||||
|
||||
@@ -53,8 +59,12 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
|
||||
const port = await ports.find(3000);
|
||||
|
||||
const origin = `http://localhost:${port}`;
|
||||
const root = new URL(opts.basepath || '', origin);
|
||||
const protocol = 'http:';
|
||||
const host = `localhost:${port}`;
|
||||
const origin = `${protocol}//${host}`;
|
||||
|
||||
const root = resolve(origin, opts.basepath || '');
|
||||
if (!root.href.endsWith('/')) root.href += '/';
|
||||
|
||||
emitter.emit('info', {
|
||||
message: `Crawling ${root.href}`
|
||||
@@ -72,29 +82,15 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
|
||||
const seen = new Set();
|
||||
const saved = new Set();
|
||||
const deferreds = new Map();
|
||||
|
||||
function get_deferred(pathname: string) {
|
||||
pathname = pathname.replace(root.pathname, '');
|
||||
|
||||
if (!deferreds.has(pathname)) {
|
||||
deferreds.set(pathname, new Deferred());
|
||||
}
|
||||
|
||||
return deferreds.get(pathname);
|
||||
}
|
||||
|
||||
proc.on('message', message => {
|
||||
if (!message.__sapper__ || message.event !== 'file') return;
|
||||
|
||||
const pathname = new URL(message.url, origin).pathname;
|
||||
function save(path: string, status: number, type: string, body: string) {
|
||||
const { pathname } = resolve(origin, path);
|
||||
let file = pathname.slice(1);
|
||||
let { body } = message;
|
||||
|
||||
if (saved.has(file)) return;
|
||||
saved.add(file);
|
||||
|
||||
const is_html = message.type === 'text/html';
|
||||
const is_html = type === 'text/html';
|
||||
|
||||
if (is_html) {
|
||||
file = file === '' ? 'index.html' : `${file}/index.html`;
|
||||
@@ -104,12 +100,15 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
emitter.emit('file', <events.FileEvent>{
|
||||
file,
|
||||
size: body.length,
|
||||
status: message.status
|
||||
status
|
||||
});
|
||||
|
||||
sander.writeFileSync(export_dir, file, body);
|
||||
}
|
||||
|
||||
get_deferred(pathname).fulfil();
|
||||
proc.on('message', message => {
|
||||
if (!message.__sapper__ || message.event !== 'file') return;
|
||||
save(message.url, message.status, message.type, message.body);
|
||||
});
|
||||
|
||||
async function handle(url: URL) {
|
||||
@@ -118,32 +117,34 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
if (seen.has(pathname)) return;
|
||||
seen.add(pathname);
|
||||
|
||||
const deferred = get_deferred(pathname);
|
||||
|
||||
const timeout_deferred = new Deferred();
|
||||
const timeout = setTimeout(() => {
|
||||
timeout_deferred.reject(new Error(`Timed out waiting for ${url.href}`));
|
||||
}, opts.timeout);
|
||||
|
||||
const r = await Promise.race([
|
||||
fetch(url.href),
|
||||
fetch(url.href, {
|
||||
redirect: 'manual'
|
||||
}),
|
||||
timeout_deferred.promise
|
||||
]);
|
||||
|
||||
clearTimeout(timeout); // prevent it hanging at the end
|
||||
|
||||
let type = r.headers.get('Content-Type');
|
||||
let body = await r.text();
|
||||
|
||||
const range = ~~(r.status / 100);
|
||||
|
||||
if (range === 2) {
|
||||
if (r.headers.get('Content-Type') === 'text/html') {
|
||||
const body = await r.text();
|
||||
if (type === 'text/html') {
|
||||
const urls: URL[] = [];
|
||||
|
||||
const cleaned = clean_html(body);
|
||||
|
||||
const base_match = /<base ([\s\S]+?)>/m.exec(cleaned);
|
||||
const base_href = base_match && get_href(base_match[1]);
|
||||
const base = new URL(base_href || '/', url.href);
|
||||
const base = resolve(url.href, base_href);
|
||||
|
||||
let match;
|
||||
let pattern = /<a ([\s\S]+?)>/gm;
|
||||
@@ -153,8 +154,11 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
const href = get_href(attrs);
|
||||
|
||||
if (href) {
|
||||
const url = new URL(href, base.href);
|
||||
if (url.origin === origin) urls.push(url);
|
||||
const url = resolve(base.href, href);
|
||||
|
||||
if (url.protocol === protocol && url.host === host) {
|
||||
urls.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +166,16 @@ async function execute(emitter: EventEmitter, opts: Opts) {
|
||||
}
|
||||
}
|
||||
|
||||
await deferred.promise;
|
||||
if (range === 3) {
|
||||
const location = r.headers.get('Location');
|
||||
|
||||
type = 'text/html';
|
||||
body = `<script>window.location.href = "${location}"</script>`;
|
||||
|
||||
await handle(resolve(root.href, location));
|
||||
}
|
||||
|
||||
save(pathname, r.status, type, body);
|
||||
}
|
||||
|
||||
return ports.wait(port)
|
||||
|
||||
@@ -11,12 +11,14 @@ prog.command('dev')
|
||||
.describe('Start a development server')
|
||||
.option('-p, --port', 'Specify a port')
|
||||
.option('-o, --open', 'Open a browser window')
|
||||
.option('--dev-port', 'Specify a port for development server')
|
||||
.option('--hot', 'Use hot module replacement (requires webpack)', true)
|
||||
.option('-l --live', 'Reload on changes if not using --hot', true)
|
||||
.option('--live', 'Reload on changes if not using --hot', true)
|
||||
.option('--bundler', 'Specify a bundler (rollup or webpack)')
|
||||
.action(async (opts: {
|
||||
port: number,
|
||||
open: boolean,
|
||||
'dev-port': number,
|
||||
live: boolean,
|
||||
hot: boolean,
|
||||
bundler?: string
|
||||
|
||||
@@ -17,8 +17,8 @@ export class CompileResult {
|
||||
duration: number;
|
||||
errors: CompileError[];
|
||||
warnings: CompileError[];
|
||||
assets: string[];
|
||||
assetsByChunkName: Record<string, string>;
|
||||
chunks: string[];
|
||||
assets: Record<string, string>;
|
||||
}
|
||||
|
||||
class RollupResult extends CompileResult {
|
||||
@@ -32,15 +32,15 @@ class RollupResult extends CompileResult {
|
||||
this.errors = compiler.errors.map(munge_rollup_warning_or_error);
|
||||
this.warnings = compiler.warnings.map(munge_rollup_warning_or_error); // TODO emit this as they happen
|
||||
|
||||
this.assets = compiler.chunks.map(chunk => chunk.fileName);
|
||||
this.chunks = compiler.chunks.map(chunk => chunk.fileName);
|
||||
|
||||
// TODO populate this properly. We don't have namedcompiler. chunks, as in
|
||||
// webpack, but we can have a route -> [chunk] map or something
|
||||
this.assetsByChunkName = {};
|
||||
this.assets = {};
|
||||
|
||||
compiler.chunks.forEach(chunk => {
|
||||
if (compiler.input in chunk.modules) {
|
||||
this.assetsByChunkName.main = chunk.fileName;
|
||||
this.assets.main = chunk.fileName;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -110,8 +110,8 @@ class WebpackResult extends CompileResult {
|
||||
|
||||
this.duration = info.time;
|
||||
|
||||
this.assets = info.assets.map((chunk: { name: string }) => chunk.name);
|
||||
this.assetsByChunkName = info.assetsByChunkName;
|
||||
this.chunks = info.assets.map((chunk: { name: string }) => chunk.name);
|
||||
this.assets = info.assetsByChunkName;
|
||||
}
|
||||
|
||||
print() {
|
||||
|
||||
@@ -5,7 +5,8 @@ import { posixify, write_if_changed } from './utils';
|
||||
import { dev, locations } from '../config';
|
||||
import { Page, PageComponent, ServerRoute } from '../interfaces';
|
||||
|
||||
export function create_main_manifests({ routes, dev_port }: {
|
||||
export function create_main_manifests({ bundler, routes, dev_port }: {
|
||||
bundler: string,
|
||||
routes: { components: PageComponent[], pages: Page[], server_routes: ServerRoute[] };
|
||||
dev_port?: number;
|
||||
}) {
|
||||
@@ -14,7 +15,7 @@ export function create_main_manifests({ routes, dev_port }: {
|
||||
|
||||
const path_to_routes = path.relative(manifest_dir, locations.routes());
|
||||
|
||||
const client_manifest = generate_client(routes, path_to_routes, dev_port);
|
||||
const client_manifest = generate_client(routes, path_to_routes, bundler, dev_port);
|
||||
const server_manifest = generate_server(routes, path_to_routes);
|
||||
|
||||
write_if_changed(
|
||||
@@ -48,6 +49,7 @@ export function create_serviceworker_manifest({ routes, client_files }: {
|
||||
function generate_client(
|
||||
routes: { root: PageComponent, components: PageComponent[], pages: Page[], server_routes: ServerRoute[] },
|
||||
path_to_routes: string,
|
||||
bundler: string,
|
||||
dev_port?: number
|
||||
) {
|
||||
const page_ids = new Set(routes.pages.map(page =>
|
||||
@@ -61,10 +63,15 @@ function generate_client(
|
||||
import root from '${get_file(path_to_routes, routes.root)}';
|
||||
import error from '${posixify(`${path_to_routes}/_error.html`)}';
|
||||
|
||||
${routes.components.map(component =>
|
||||
`const ${component.name} = () =>
|
||||
import(/* webpackChunkName: "${component.name}" */ '${get_file(path_to_routes, component)}');`)
|
||||
.join('\n')}
|
||||
${routes.components.map(component => {
|
||||
const annotation = bundler === 'webpack'
|
||||
? `/* webpackChunkName: "${component.name}" */ `
|
||||
: '';
|
||||
|
||||
const source = get_file(path_to_routes, component);
|
||||
|
||||
return `const ${component.name} = () => import(${annotation}'${source}');`;
|
||||
}).join('\n')}
|
||||
|
||||
export const manifest = {
|
||||
ignore: [${server_routes_to_ignore.map(route => route.pattern).join(', ')}],
|
||||
|
||||
@@ -128,12 +128,12 @@ export default function create_routes(cwd = locations.routes()) {
|
||||
components.push(component);
|
||||
if (item.basename === 'index.html') {
|
||||
pages.push({
|
||||
pattern: get_pattern(parent_segments),
|
||||
pattern: get_pattern(parent_segments, true),
|
||||
parts
|
||||
});
|
||||
} else {
|
||||
pages.push({
|
||||
pattern: get_pattern(segments),
|
||||
pattern: get_pattern(segments, true),
|
||||
parts
|
||||
});
|
||||
}
|
||||
@@ -142,7 +142,7 @@ export default function create_routes(cwd = locations.routes()) {
|
||||
else {
|
||||
server_routes.push({
|
||||
name: `route_${get_slug(item.file)}`,
|
||||
pattern: get_pattern(segments),
|
||||
pattern: get_pattern(segments, false),
|
||||
file: item.file,
|
||||
params: params
|
||||
});
|
||||
@@ -276,7 +276,7 @@ function get_slug(file: string) {
|
||||
});
|
||||
}
|
||||
|
||||
function get_pattern(segments: Part[][]) {
|
||||
function get_pattern(segments: Part[][], add_trailing_slash: boolean) {
|
||||
return new RegExp(
|
||||
`^` +
|
||||
segments.map(segment => {
|
||||
@@ -290,6 +290,6 @@ function get_pattern(segments: Part[][]) {
|
||||
.replace(/%5D/g, ']');
|
||||
}).join('');
|
||||
}).join('') +
|
||||
'\\\/?$'
|
||||
(add_trailing_slash ? '\\\/?$' : '$')
|
||||
);
|
||||
}
|
||||
@@ -414,18 +414,6 @@ function get_page_handler(
|
||||
res.setHeader('Location', location);
|
||||
res.end();
|
||||
|
||||
if (process.send) {
|
||||
process.send({
|
||||
__sapper__: true,
|
||||
event: 'file',
|
||||
url: req.url,
|
||||
method: req.method,
|
||||
status: redirect.statusCode,
|
||||
type: 'text/html',
|
||||
body: `<script>window.location.href = "${location}"</script>`
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,18 +500,6 @@ function get_page_handler(
|
||||
|
||||
res.statusCode = status;
|
||||
res.end(body);
|
||||
|
||||
if (process.send) {
|
||||
process.send({
|
||||
__sapper__: true,
|
||||
event: 'file',
|
||||
url: req.url,
|
||||
method: req.method,
|
||||
status,
|
||||
type: 'text/html',
|
||||
body
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
if (error) {
|
||||
// we encountered an error while rendering the error page — oops
|
||||
|
||||
@@ -38,7 +38,7 @@ export default {
|
||||
|
||||
output: () => {
|
||||
return {
|
||||
dir: locations.dest(),
|
||||
file: `${locations.dest()}/service-worker.js`,
|
||||
format: 'iife'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,13 @@ const middlewares = [
|
||||
}),
|
||||
];
|
||||
|
||||
app.get(`${BASEPATH}/non-sapper-redirect-from`, (req, res) => {
|
||||
res.writeHead(301, {
|
||||
Location: `${BASEPATH}/non-sapper-redirect-to`
|
||||
});
|
||||
res.end();
|
||||
});
|
||||
|
||||
if (BASEPATH) {
|
||||
app.use(BASEPATH, ...middlewares);
|
||||
} else {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<a href='.'>home</a>
|
||||
<a href='about'>about</a>
|
||||
<a href='slow-preload'>slow preload</a>
|
||||
<a href='non-sapper-redirect-from'>redirect</a>
|
||||
<a href='redirect-from'>redirect</a>
|
||||
<a href='redirect-root'>redirect (root)</a>
|
||||
<a href='blog/nope'>broken link</a>
|
||||
|
||||
1
test/app/routes/non-sapper-redirect-to.html
Normal file
1
test/app/routes/non-sapper-redirect-to.html
Normal file
@@ -0,0 +1 @@
|
||||
<h1>redirected</h1>
|
||||
@@ -2,9 +2,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const assert = require('assert');
|
||||
const Nightmare = require('nightmare');
|
||||
const serve = require('serve-static');
|
||||
const walkSync = require('walk-sync');
|
||||
const fetch = require('node-fetch');
|
||||
const rimraf = require('rimraf');
|
||||
const ports = require('port-authority');
|
||||
|
||||
@@ -83,6 +81,11 @@ function testExport({ basepath = '' }) {
|
||||
'about/index.html',
|
||||
'slow-preload/index.html',
|
||||
|
||||
'redirect-from/index.html',
|
||||
'redirect-to/index.html',
|
||||
'non-sapper-redirect-from/index.html',
|
||||
'non-sapper-redirect-to/index.html',
|
||||
|
||||
'blog/index.html',
|
||||
'blog/a-very-long-post/index.html',
|
||||
'blog/how-can-i-get-involved/index.html',
|
||||
|
||||
@@ -53,14 +53,14 @@ describe('create_routes', () => {
|
||||
assert.deepEqual(server_routes, [
|
||||
{
|
||||
name: 'route_blog_json',
|
||||
pattern: /^\/blog.json\/?$/,
|
||||
pattern: /^\/blog.json$/,
|
||||
file: 'blog/index.json.js',
|
||||
params: []
|
||||
},
|
||||
|
||||
{
|
||||
name: 'route_blog_$slug_json',
|
||||
pattern: /^\/blog\/([^\/]+?).json\/?$/,
|
||||
pattern: /^\/blog\/([^\/]+?).json$/,
|
||||
file: 'blog/[slug].json.js',
|
||||
params: ['slug']
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user