mirror of
https://github.com/1f349/svelte-ssr-template.git
synced 2024-11-21 11:01:36 +00:00
First commit
This commit is contained in:
commit
88a66f6763
4
create.sh
Executable file
4
create.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
git clone https://github.com/1f349/svelte-ssr-template svelte-ssr-template
|
||||||
|
cp -r svelte-ssr-template/template/* .
|
||||||
|
rm -r svelte-ssr-template
|
36
template/.editorconfig
Normal file
36
template/.editorconfig
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
# CSS
|
||||||
|
[*.css]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# HTML
|
||||||
|
[*.{htm,html}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# GNU make
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
# Svelte
|
||||||
|
[*.svelte]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# YAML
|
||||||
|
[*.{yaml,yml}]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
25
template/.gitignore
vendored
Normal file
25
template/.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
*.development
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
13
template/.prettierrc
Normal file
13
template/.prettierrc
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 150,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": false,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"requirePragma": false,
|
||||||
|
"insertPragma": false
|
||||||
|
}
|
3
template/.vscode/extensions.json
vendored
Normal file
3
template/.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"recommendations": ["svelte.svelte-vscode"]
|
||||||
|
}
|
15
template/README.md
Normal file
15
template/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Svelte SSR Template
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn
|
||||||
|
yarn run build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn
|
||||||
|
yarn run dev
|
||||||
|
```
|
38
template/package.json
Normal file
38
template/package.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "svelte-ssr-template",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"prettier:check:ci": "./node_modules/.bin/prettier --check .",
|
||||||
|
"format": "./node_modules/.bin/prettier --write .",
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@svelte-parts/markdown": "^0.0.23",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^1.1.0",
|
||||||
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
|
"@types/dompurify": "^2.4.0",
|
||||||
|
"@types/highlight.js": "^10.1.0",
|
||||||
|
"dompurify": "^2.4.1",
|
||||||
|
"highlight.js": "^11.7.0",
|
||||||
|
"prettier": "^2.7.1",
|
||||||
|
"prettier-plugin-svelte": "^2.8.0",
|
||||||
|
"sass": "^1.56.0",
|
||||||
|
"svelte": "^3.52.0",
|
||||||
|
"svelte-check": "^2.9.2",
|
||||||
|
"svelte-markdown": "^0.2.3",
|
||||||
|
"svelte-navigator": "^3.2.2",
|
||||||
|
"svelte-preprocess": "^4.10.7",
|
||||||
|
"tslib": "^2.4.0",
|
||||||
|
"typescript": "^4.6.4",
|
||||||
|
"vite": "^3.2.0",
|
||||||
|
"vite-plugin-ssr": "^0.4.90"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"semver": "^7.5.3"
|
||||||
|
}
|
||||||
|
}
|
BIN
template/public/fonts/Ubuntu.woff2
Normal file
BIN
template/public/fonts/Ubuntu.woff2
Normal file
Binary file not shown.
36
template/server.ts
Normal file
36
template/server.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const {renderPage} = require("vite-plugin-ssr");
|
||||||
|
|
||||||
|
const isProduction = process.env.NODE_ENV === "production";
|
||||||
|
const root = `${__dirname}/..`;
|
||||||
|
|
||||||
|
startServer();
|
||||||
|
|
||||||
|
async function startServer() {
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
if (isProduction) {
|
||||||
|
app.use(express.static(`${root}/client`));
|
||||||
|
} else {
|
||||||
|
const vite = require("vite");
|
||||||
|
const viteDevServer = await vite.createServer({
|
||||||
|
root,
|
||||||
|
server: {
|
||||||
|
middlewareMode: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
app.use(viteDevServer.middlewares);
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get("*", async (req, res, next) => {
|
||||||
|
const pageContextInit = {urlOriginal: req.originalUrl};
|
||||||
|
const pageContext = await renderPage(pageContextInit);
|
||||||
|
if (pageContext.httpResponse === null) return next();
|
||||||
|
const {body, statusCode, contentType} = pageContext.httpResponse;
|
||||||
|
res.status(statusCode).type(contentType).send(body);
|
||||||
|
});
|
||||||
|
|
||||||
|
const port = 5173;
|
||||||
|
app.listen(port);
|
||||||
|
console.log(`Server running at http://localhost:${port}`);
|
||||||
|
}
|
27
template/src/components/MetaTags.svelte
Normal file
27
template/src/components/MetaTags.svelte
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export let url: string;
|
||||||
|
export let title: string;
|
||||||
|
export let description: string;
|
||||||
|
export let keywords: string;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||||
|
<title>{title}</title>
|
||||||
|
|
||||||
|
<meta name="theme-color" content="#0000" />
|
||||||
|
<meta name="default-theme" content="auto" />
|
||||||
|
<meta name="author" content="Svelte SSR Template" />
|
||||||
|
<meta name="description" content={description} />
|
||||||
|
<meta name="keywords" content="svelte-ssr-template,{keywords}" />
|
||||||
|
<meta name="referrer" content="no-referrer" />
|
||||||
|
|
||||||
|
<meta property="og:title" content={title} />
|
||||||
|
<meta property="og:url" content={url.indexOf("https://") == 0 ? url : "https://example.com" + (url[0] == "/" ? url : "/" + url)} />
|
||||||
|
<meta property="og:type" content="object" />
|
||||||
|
<meta property="og:image" content="https://example.com/logo.png" />
|
||||||
|
<meta property="og:site_name" content="Svelte SSR Template" />
|
||||||
|
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
|
||||||
|
<link rel="icon" type="image/png" href="/logo.png" />
|
||||||
|
</svelte:head>
|
9
template/src/pages/__layout.svelte
Normal file
9
template/src/pages/__layout.svelte
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import "~/styles/app.scss";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<main>
|
||||||
|
<slot />
|
||||||
|
</main>
|
||||||
|
</div>
|
30
template/src/pages/_default/_default.page.client.js
Normal file
30
template/src/pages/_default/_default.page.client.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export const clientRouting = true;
|
||||||
|
|
||||||
|
export const prefetchStaticAssets = {when: "HOVER"};
|
||||||
|
|
||||||
|
export async function render(pageContext) {
|
||||||
|
const app_el = document.getElementById("app");
|
||||||
|
new pageContext.Page({
|
||||||
|
target: app_el,
|
||||||
|
hydrate: true,
|
||||||
|
props: {
|
||||||
|
__: pageContext.__,
|
||||||
|
pageProps: pageContext.pageProps,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onPageTransitionStart(pageContext) {
|
||||||
|
console.log("Page transition start");
|
||||||
|
// `pageContext.isBackwardNavigation` is also set at `render(pageContext)`
|
||||||
|
// and `onPageTransitionEnd(pageContext)`.
|
||||||
|
console.log("Is backwards navigation?", pageContext.isBackwardNavigation);
|
||||||
|
// For example:
|
||||||
|
document.body.classList.add("page-transition");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onPageTransitionEnd(pageContext) {
|
||||||
|
console.log("Page transition end");
|
||||||
|
// For example:
|
||||||
|
document.body.classList.remove("page-transition");
|
||||||
|
}
|
44
template/src/pages/_default/_default.page.server.js
Normal file
44
template/src/pages/_default/_default.page.server.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import {escapeInject, dangerouslySkipEscape} from "vite-plugin-ssr";
|
||||||
|
const base = import.meta.env.BASE_URL;
|
||||||
|
|
||||||
|
// See https://vite-plugin-ssr.com/data-fetching
|
||||||
|
export const passToClient = ["__", "pageProps", "routeParams", "urlOriginal"];
|
||||||
|
|
||||||
|
export async function onBeforeRender(pageContext) {
|
||||||
|
const {routeParams, urlOriginal} = pageContext;
|
||||||
|
|
||||||
|
return {
|
||||||
|
pageContext: {
|
||||||
|
__: {
|
||||||
|
routeParams,
|
||||||
|
urlOriginal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function render(pageContext) {
|
||||||
|
const app = pageContext.Page.render(pageContext);
|
||||||
|
const appHtml = app.html;
|
||||||
|
const appCss = app.css.code;
|
||||||
|
const appHead = app.head;
|
||||||
|
|
||||||
|
// We are using Svelte's app.head variable rather than the Vite Plugin SSR
|
||||||
|
// technique described here: https://vite-plugin-ssr.com/html-head This seems
|
||||||
|
// easier for using data fetched from APIs and also allows us to input the
|
||||||
|
// data using our custom MetaTags Svelte component.
|
||||||
|
|
||||||
|
return escapeInject`<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" href="${base}logo.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
${dangerouslySkipEscape(appHead)}
|
||||||
|
<style>${appCss}</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">${dangerouslySkipEscape(appHtml)}</div>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
}
|
24
template/src/pages/_error.page.svelte
Normal file
24
template/src/pages/_error.page.svelte
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {navigate} from "vite-plugin-ssr/client/router";
|
||||||
|
import MetaTags from "~/components/MetaTags.svelte";
|
||||||
|
import Layout from "./__layout.svelte";
|
||||||
|
|
||||||
|
export let __;
|
||||||
|
export let pageProps;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<MetaTags url={__.urlOriginal} title="Error" description="" keywords="error,error page" />
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<div>
|
||||||
|
{#if pageProps.is404}
|
||||||
|
<h1 class="title-text">404 Not Found</h1>
|
||||||
|
<p class="coming-soon">You have lost your way, please return to valid paths.</p>
|
||||||
|
<p><button on:click={() => navigate("/")} class="refresh-btn">Back to homepage</button></p>
|
||||||
|
{:else}
|
||||||
|
<h1 class="title-text">500 Internal Server Error</h1>
|
||||||
|
<p class="coming-soon">The server had an issue with this page.</p>
|
||||||
|
<p><button on:click={() => navigate("/")} class="refresh-btn">Back to homepage</button></p>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
21
template/src/pages/index.page.svelte
Normal file
21
template/src/pages/index.page.svelte
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import MetaTags from "~/components/MetaTags.svelte";
|
||||||
|
import Layout from "./__layout.svelte";
|
||||||
|
|
||||||
|
export let __;
|
||||||
|
export let pageProps;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<MetaTags url={__.urlOriginal} title="Svelte SSR Template" description="Svelte SSR Template Home Page" keywords="" />
|
||||||
|
|
||||||
|
<Layout isHome={true}>
|
||||||
|
<h1 class="title-text">Svelte SSR Template</h1>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.title-text {
|
||||||
|
margin: 0 0 24px 0;
|
||||||
|
font-size: 3.2em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
</style>
|
39
template/src/styles/app.scss
Normal file
39
template/src/styles/app.scss
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Ubuntu';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: swap;
|
||||||
|
src: url('/fonts/Ubuntu.woff2') format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: Ubuntu, Inter, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: #e2e2e2;
|
||||||
|
background-color: #000000;
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: 500;
|
||||||
|
color: tomato;
|
||||||
|
text-decoration: inherit;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: tomato;
|
||||||
|
}
|
||||||
|
}
|
9
template/src/vite-env.d.ts
vendored
Normal file
9
template/src/vite-env.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/// <reference types="svelte" />
|
||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
7
template/svelte.config.js
Normal file
7
template/svelte.config.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import sveltePreprocess from "svelte-preprocess";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Consult https://github.com/sveltejs/svelte-preprocess
|
||||||
|
// for more information about preprocessors
|
||||||
|
preprocess: sveltePreprocess(),
|
||||||
|
};
|
22
template/tsconfig.json
Normal file
22
template/tsconfig.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"baseUrl": "./src",
|
||||||
|
"paths": {"~/*": ["./*"]},
|
||||||
|
/**
|
||||||
|
* Typecheck JS in `.svelte` and `.js` files by default.
|
||||||
|
* Disable checkJs if you'd like to use dynamic types in JS.
|
||||||
|
* Note that setting allowJs false does not prevent the use
|
||||||
|
* of JS in `.svelte` files.
|
||||||
|
*/
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"isolatedModules": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "src/**/*.mjs"],
|
||||||
|
"references": [{"path": "./tsconfig.node.json"}]
|
||||||
|
}
|
8
template/tsconfig.node.json
Normal file
8
template/tsconfig.node.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node"
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
38
template/vite.config.ts
Normal file
38
template/vite.config.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import {defineConfig} from "vite";
|
||||||
|
import {svelte} from "@sveltejs/vite-plugin-svelte";
|
||||||
|
import sveltePreprocess from "svelte-preprocess";
|
||||||
|
import {resolve as pathResolve} from "path";
|
||||||
|
import ssr from "vite-plugin-ssr/plugin";
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
emptyOutDir: true,
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
svelte({
|
||||||
|
preprocess: sveltePreprocess({
|
||||||
|
preserve: ["ld+json"],
|
||||||
|
scss: {
|
||||||
|
includePaths: ["src/"],
|
||||||
|
quietDeps: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
compilerOptions: {
|
||||||
|
hydratable: true,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
ssr({
|
||||||
|
prerender: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
optimizeDeps: {exclude: ["svelte-navigator"]},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"~": pathResolve(__dirname, "src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
1056
template/yarn.lock
Normal file
1056
template/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user