mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-19 05:45:27 +00:00
incorporate Sirv, and add a sapper.start() function
This commit is contained in:
@@ -24,8 +24,9 @@ function template(kind, external) {
|
|||||||
external,
|
external,
|
||||||
plugins: [
|
plugins: [
|
||||||
resolve({
|
resolve({
|
||||||
extensions: ['.mjs', '.js', '.ts']
|
extensions: ['.mjs', '.js', '.json', '.ts']
|
||||||
}),
|
}),
|
||||||
|
json(),
|
||||||
commonjs(),
|
commonjs(),
|
||||||
string({
|
string({
|
||||||
include: '**/*.md'
|
include: '**/*.md'
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ export async function hydrate_target(target: Target): Promise<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
function load_css(chunk: string) {
|
function load_css(chunk: string) {
|
||||||
const href = `client/${chunk}`;
|
const href = `sapper/${chunk}`;
|
||||||
if (document.querySelector(`link[href="${href}"]`)) return;
|
if (document.querySelector(`link[href="${href}"]`)) return;
|
||||||
|
|
||||||
return new Promise((fulfil, reject) => {
|
return new Promise((fulfil, reject) => {
|
||||||
|
|||||||
@@ -1 +1,14 @@
|
|||||||
export { default as middleware } from './middleware/index';
|
import * as http from 'http';
|
||||||
|
import middleware from './middleware/index';
|
||||||
|
import { StartOptions, MiddlewareOptions, Handler } from './types';
|
||||||
|
|
||||||
|
export { middleware };
|
||||||
|
|
||||||
|
export function start(opts: StartOptions = {}) {
|
||||||
|
const handler = middleware(opts) as Handler;
|
||||||
|
const server = http.createServer(handler as http.ServerOptions);
|
||||||
|
|
||||||
|
server.listen(opts.port || process.env.PORT);
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import cookie from 'cookie';
|
|||||||
import devalue from 'devalue';
|
import devalue from 'devalue';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import URL from 'url';
|
import URL from 'url';
|
||||||
import { Manifest, Page, Req, Res } from './types';
|
import { Manifest, Page, Req, Res } from '../types';
|
||||||
import { build_dir, dev, src_dir } from '@sapper/internal/manifest-server';
|
import { build_dir, dev, src_dir } from '@sapper/internal/manifest-server';
|
||||||
import App from '@sapper/internal/App.svelte';
|
import App from '@sapper/internal/App.svelte';
|
||||||
|
|
||||||
@@ -21,9 +21,8 @@ export function get_page_handler(
|
|||||||
? () => read_template(src_dir)
|
? () => read_template(src_dir)
|
||||||
: (str => () => str)(read_template(build_dir));
|
: (str => () => str)(read_template(build_dir));
|
||||||
|
|
||||||
const has_service_worker = fs.existsSync(path.join(build_dir, 'service-worker.js'));
|
const has_service_worker = fs.existsSync(path.join(build_dir, 'service-worker/service-worker.js'));
|
||||||
|
|
||||||
const { server_routes, pages } = manifest;
|
|
||||||
const error_route = manifest.error;
|
const error_route = manifest.error;
|
||||||
|
|
||||||
function handle_error(req: Req, res: Res, statusCode: number, error: Error | string) {
|
function handle_error(req: Req, res: Res, statusCode: number, error: Error | string) {
|
||||||
@@ -63,7 +62,7 @@ export function get_page_handler(
|
|||||||
// TODO add dependencies and CSS
|
// TODO add dependencies and CSS
|
||||||
const link = preloaded_chunks
|
const link = preloaded_chunks
|
||||||
.filter(file => file && !file.match(/\.map$/))
|
.filter(file => file && !file.match(/\.map$/))
|
||||||
.map(file => `<${req.baseUrl}/client/${file}>;rel="modulepreload"`)
|
.map(file => `<${req.baseUrl}/sapper/${file}>;rel="modulepreload"`)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
res.setHeader('Link', link);
|
res.setHeader('Link', link);
|
||||||
@@ -72,7 +71,7 @@ export function get_page_handler(
|
|||||||
.filter(file => file && !file.match(/\.map$/))
|
.filter(file => file && !file.match(/\.map$/))
|
||||||
.map((file) => {
|
.map((file) => {
|
||||||
const as = /\.css$/.test(file) ? 'style' : 'script';
|
const as = /\.css$/.test(file) ? 'style' : 'script';
|
||||||
return `<${req.baseUrl}/client/${file}>;rel="preload";as="${as}"`;
|
return `<${req.baseUrl}/sapper/${file}>;rel="preload";as="${as}"`;
|
||||||
})
|
})
|
||||||
.join(', ');
|
.join(', ');
|
||||||
|
|
||||||
@@ -263,14 +262,14 @@ export function get_page_handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const file = [].concat(build_info.assets.main).filter(file => file && /\.js$/.test(file))[0];
|
const file = [].concat(build_info.assets.main).filter(file => file && /\.js$/.test(file))[0];
|
||||||
const main = `${req.baseUrl}/client/${file}`;
|
const main = `${req.baseUrl}/sapper/${file}`;
|
||||||
|
|
||||||
if (build_info.bundler === 'rollup') {
|
if (build_info.bundler === 'rollup') {
|
||||||
if (build_info.legacy_assets) {
|
if (build_info.legacy_assets) {
|
||||||
const legacy_main = `${req.baseUrl}/client/legacy/${build_info.legacy_assets.main}`;
|
const legacy_main = `${req.baseUrl}/sapper/legacy/${build_info.legacy_assets.main}`;
|
||||||
script += `(function(){try{eval("async function x(){}");var main="${main}"}catch(e){main="${legacy_main}"};var s=document.createElement("script");try{new Function("if(0)import('')")();s.src=main;s.type="module";s.crossOrigin="use-credentials";}catch(e){s.src="${req.baseUrl}/client/shimport@${build_info.shimport}.js";s.setAttribute("data-main",main);}document.head.appendChild(s);}());`;
|
script += `(function(){try{eval("async function x(){}");var main="${main}"}catch(e){main="${legacy_main}"};var s=document.createElement("script");try{new Function("if(0)import('')")();s.src=main;s.type="module";s.crossOrigin="use-credentials";}catch(e){s.src="${req.baseUrl}/sapper/shimport@${build_info.shimport}.js";s.setAttribute("data-main",main);}document.head.appendChild(s);}());`;
|
||||||
} else {
|
} else {
|
||||||
script += `var s=document.createElement("script");try{new Function("if(0)import('')")();s.src="${main}";s.type="module";s.crossOrigin="use-credentials";}catch(e){s.src="${req.baseUrl}/client/shimport@${build_info.shimport}.js";s.setAttribute("data-main","${main}")}document.head.appendChild(s)`;
|
script += `var s=document.createElement("script");try{new Function("if(0)import('')")();s.src="${main}";s.type="module";s.crossOrigin="use-credentials";}catch(e){s.src="${req.baseUrl}/sapper/shimport@${build_info.shimport}.js";s.setAttribute("data-main","${main}")}document.head.appendChild(s)`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
script += `</script><script src="${main}">`;
|
script += `</script><script src="${main}">`;
|
||||||
@@ -295,7 +294,7 @@ export function get_page_handler(
|
|||||||
});
|
});
|
||||||
|
|
||||||
styles = Array.from(css_chunks)
|
styles = Array.from(css_chunks)
|
||||||
.map(href => `<link rel="stylesheet" href="client/${href}">`)
|
.map(href => `<link rel="stylesheet" href="sapper/${href}">`)
|
||||||
.join('')
|
.join('')
|
||||||
} else {
|
} else {
|
||||||
styles = (css && css.code ? `<style>${css.code}</style>` : '');
|
styles = (css && css.code ? `<style>${css.code}</style>` : '');
|
||||||
@@ -327,12 +326,12 @@ export function get_page_handler(
|
|||||||
|
|
||||||
return function find_route(req: Req, res: Res, next: () => void) {
|
return function find_route(req: Req, res: Res, next: () => void) {
|
||||||
if (req.path === '/service-worker-index.html') {
|
if (req.path === '/service-worker-index.html') {
|
||||||
const homePage = pages.find(page => page.pattern.test('/'));
|
const homePage = manifest.pages.find(page => page.pattern.test('/'));
|
||||||
handle_page(homePage, req, res);
|
handle_page(homePage, req, res);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const page of pages) {
|
for (const page of manifest.pages) {
|
||||||
if (page.pattern.test(req.path)) {
|
if (page.pattern.test(req.path)) {
|
||||||
handle_page(page, req, res);
|
handle_page(page, req, res);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Req, Res, ServerRoute } from './types';
|
import { Req, Res, ServerRoute } from '../types';
|
||||||
|
|
||||||
export function get_server_route_handler(routes: ServerRoute[]) {
|
export function get_server_route_handler(routes: ServerRoute[]) {
|
||||||
async function handle_route(route: ServerRoute, req: Req, res: Res, next: () => void) {
|
async function handle_route(route: ServerRoute, req: Req, res: Res, next: () => void) {
|
||||||
|
|||||||
@@ -1,23 +1,41 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import sirv from 'sirv';
|
||||||
import { build_dir, dev, manifest } from '@sapper/internal/manifest-server';
|
import { build_dir, dev, manifest } from '@sapper/internal/manifest-server';
|
||||||
import { Handler, Req, Res } from './types';
|
import { Handler, Req, Res, MiddlewareOptions } from '../types';
|
||||||
import { get_server_route_handler } from './get_server_route_handler';
|
import { get_server_route_handler } from './get_server_route_handler';
|
||||||
import { get_page_handler } from './get_page_handler';
|
import { get_page_handler } from './get_page_handler';
|
||||||
import { lookup } from './mime';
|
import { lookup } from './mime';
|
||||||
|
import { stringify } from 'querystring';
|
||||||
|
|
||||||
export default function middleware(opts: {
|
export default function middleware(opts: MiddlewareOptions = {}) {
|
||||||
session?: (req: Req, res: Res) => any,
|
|
||||||
ignore?: any
|
|
||||||
} = {}) {
|
|
||||||
const { session, ignore } = opts;
|
const { session, ignore } = opts;
|
||||||
|
|
||||||
let emitted_basepath = false;
|
let emitted_basepath = false;
|
||||||
|
|
||||||
return compose_handlers(ignore, [
|
return compose_handlers(ignore, [
|
||||||
|
sirv('static', {
|
||||||
|
dev,
|
||||||
|
setHeaders: opts.static && opts.static.headers && ((res: Response, pathname: string, stats: fs.Stats) => {
|
||||||
|
const headers = opts.static.headers(pathname, stats);
|
||||||
|
for (const k in headers) res.setHeader(k, headers[k]);
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
sirv(`${build_dir}/client`, {
|
||||||
|
dev,
|
||||||
|
maxAge: 31536000,
|
||||||
|
immutable: true
|
||||||
|
}),
|
||||||
|
|
||||||
|
sirv(`${build_dir}/service-worker`, {
|
||||||
|
dev,
|
||||||
|
maxAge: 300
|
||||||
|
}),
|
||||||
|
|
||||||
(req: Req, res: Res, next: () => void) => {
|
(req: Req, res: Res, next: () => void) => {
|
||||||
if (req.baseUrl === undefined) {
|
if (req.baseUrl === undefined) {
|
||||||
let { originalUrl } = req;
|
let originalUrl = req.originalUrl || req.url;
|
||||||
if (req.url === '/' && originalUrl[originalUrl.length - 1] !== '/') {
|
if (req.url === '/' && originalUrl[originalUrl.length - 1] !== '/') {
|
||||||
originalUrl += '/';
|
originalUrl += '/';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Stats } from 'fs';
|
||||||
import { ClientRequest, ServerResponse } from 'http';
|
import { ClientRequest, ServerResponse } from 'http';
|
||||||
|
|
||||||
export type ServerRoute = {
|
export type ServerRoute = {
|
||||||
@@ -37,6 +38,18 @@ export type Props = {
|
|||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface MiddlewareOptions {
|
||||||
|
static?: {
|
||||||
|
headers?: (pathname: string, stats: Stats) => Record<string, string>
|
||||||
|
},
|
||||||
|
session?: (req: Req, res: Res) => any,
|
||||||
|
ignore?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StartOptions extends MiddlewareOptions {
|
||||||
|
port?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Req extends ClientRequest {
|
export interface Req extends ClientRequest {
|
||||||
url: string;
|
url: string;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
@@ -122,7 +122,7 @@ export async function build({
|
|||||||
|
|
||||||
const client_files = client_result.chunks
|
const client_files = client_result.chunks
|
||||||
.filter(chunk => !chunk.file.endsWith('.map')) // SW does not need to cache sourcemap files
|
.filter(chunk => !chunk.file.endsWith('.map')) // SW does not need to cache sourcemap files
|
||||||
.map(chunk => `client/${chunk.file}`);
|
.map(chunk => `sapper/${chunk.file}`);
|
||||||
|
|
||||||
create_serviceworker_manifest({
|
create_serviceworker_manifest({
|
||||||
manifest_data,
|
manifest_data,
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ class Watcher extends EventEmitter {
|
|||||||
JSON.stringify(result.to_json(manifest_data, this.dirs), null, ' ')
|
JSON.stringify(result.to_json(manifest_data, this.dirs), null, ' ')
|
||||||
);
|
);
|
||||||
|
|
||||||
const client_files = result.chunks.map(chunk => `client/${chunk.file}`);
|
const client_files = result.chunks.map(chunk => `sapper/${chunk.file}`);
|
||||||
|
|
||||||
create_serviceworker_manifest({
|
create_serviceworker_manifest({
|
||||||
manifest_data,
|
manifest_data,
|
||||||
|
|||||||
@@ -60,9 +60,8 @@ async function _export({
|
|||||||
rimraf(export_dir);
|
rimraf(export_dir);
|
||||||
|
|
||||||
copy(static_files, export_dir);
|
copy(static_files, export_dir);
|
||||||
copy(path.join(build_dir, 'client'), path.join(export_dir, 'client'));
|
copy(path.join(build_dir, 'client'), export_dir);
|
||||||
copy(path.join(build_dir, 'service-worker.js'), path.join(export_dir, 'service-worker.js'));
|
copy(path.join(build_dir, 'service-worker'), export_dir);
|
||||||
copy(path.join(build_dir, 'service-worker.js.map'), path.join(export_dir, 'service-worker.js.map'));
|
|
||||||
|
|
||||||
const defaultPort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
const defaultPort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
|
||||||
const port = await ports.find(defaultPort);
|
const port = await ports.find(defaultPort);
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import { mkdirp } from './fs_utils';
|
||||||
|
|
||||||
export function copy_shimport(dest: string) {
|
export function copy_shimport(dest: string) {
|
||||||
|
mkdirp(`${dest}/client/sapper`);
|
||||||
|
|
||||||
const shimport_version = require('shimport/package.json').version;
|
const shimport_version = require('shimport/package.json').version;
|
||||||
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
`${dest}/client/shimport@${shimport_version}.js`,
|
`${dest}/client/sapper/shimport@${shimport_version}.js`,
|
||||||
fs.readFileSync(require.resolve('shimport/index.js'))
|
fs.readFileSync(require.resolve('shimport/index.js'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
output: () => {
|
output: () => {
|
||||||
let dir = `${dest}/client`;
|
let dir = `${dest}/client/sapper`;
|
||||||
if (process.env.SAPPER_LEGACY_BUILD) dir += `/legacy`;
|
if (process.env.SAPPER_LEGACY_BUILD) dir += `/legacy`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -45,7 +45,7 @@ export default {
|
|||||||
|
|
||||||
output: () => {
|
output: () => {
|
||||||
return {
|
return {
|
||||||
file: `${dest}/service-worker.js`,
|
file: `${dest}/service-worker/service-worker.js`,
|
||||||
format: 'iife'
|
format: 'iife'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ export default {
|
|||||||
|
|
||||||
output: () => {
|
output: () => {
|
||||||
return {
|
return {
|
||||||
path: `${dest}/client`,
|
path: `${dest}/client/sapper`,
|
||||||
filename: '[hash]/[name].js',
|
filename: '[hash]/[name].js',
|
||||||
chunkFilename: '[hash]/[name].[id].js',
|
chunkFilename: '[hash]/[name].[id].js',
|
||||||
publicPath: `client/`
|
publicPath: `sapper/`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -46,7 +46,7 @@ export default {
|
|||||||
|
|
||||||
output: () => {
|
output: () => {
|
||||||
return {
|
return {
|
||||||
path: dest,
|
path: `${dest}/service-worker`,
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
chunkFilename: '[name].[id].[hash].js'
|
chunkFilename: '[name].[id].[hash].js'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export default function extract_css(client_result: CompileResult, components: Pa
|
|||||||
|
|
||||||
if (!client_result.css_files) return; // Rollup-only for now
|
if (!client_result.css_files) return; // Rollup-only for now
|
||||||
|
|
||||||
let asset_dir = `${dirs.dest}/client`;
|
let asset_dir = `${dirs.dest}/client/sapper`;
|
||||||
if (process.env.SAPPER_LEGACY_BUILD) asset_dir += '/legacy';
|
if (process.env.SAPPER_LEGACY_BUILD) asset_dir += '/legacy';
|
||||||
|
|
||||||
const unclaimed = new Set(client_result.css_files.map(x => x.id));
|
const unclaimed = new Set(client_result.css_files.map(x => x.id));
|
||||||
@@ -238,7 +238,7 @@ export default function extract_css(client_result: CompileResult, components: Pa
|
|||||||
map.file = output_file_name;
|
map.file = output_file_name;
|
||||||
map.sources = map.sources.map(source => path.relative(asset_dir, source));
|
map.sources = map.sources.map(source => path.relative(asset_dir, source));
|
||||||
|
|
||||||
fs.writeFileSync(`${asset_dir}/${output_file_name}`, `${code}\n/* sourceMappingURL=client/${output_file_name}.map */`);
|
fs.writeFileSync(`${asset_dir}/${output_file_name}`, `${code}\n/* sourceMappingURL=sapper/${output_file_name}.map */`);
|
||||||
fs.writeFileSync(`${asset_dir}/${output_file_name}.map`, JSON.stringify(map, null, ' '));
|
fs.writeFileSync(`${asset_dir}/${output_file_name}.map`, JSON.stringify(map, null, ' '));
|
||||||
|
|
||||||
result.main = output_file_name;
|
result.main = output_file_name;
|
||||||
|
|||||||
Reference in New Issue
Block a user