mirror of
https://github.com/1f349/svelte-ssr-template.git
synced 2024-12-22 07:24:16 +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