Skip to content

Commit

Permalink
chore(templates): add SSG template (#1)
Browse files Browse the repository at this point in the history
* ssg template

* todos

* fixes

* use appType

* ignore error
  • Loading branch information
JoviDeCroock authored and rschristian committed Jul 28, 2023
1 parent f5d4cce commit 457a153
Show file tree
Hide file tree
Showing 18 changed files with 395 additions and 47 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ dist-ssr

# Local Netlify folder
.netlify

./templates/**/package-lock.json
./templates/**/yarn.lock
27 changes: 20 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const brandColor = /** @type {const} */ ([174, 128, 255]);
kl.trueColor(...brandColor)('Preact - Fast 3kB alternative to React with the same modern API')
);

const { dir, language, useRouter, useESLint } = await prompts.group(
const { dir, language, useRouter, useESLint, appType } = await prompts.group(
{
dir: () =>
prompts.text({
Expand All @@ -36,6 +36,14 @@ const brandColor = /** @type {const} */ ([174, 128, 255]);
}
},
}),
appType : () => prompts.select({
message: 'Project Type:',
initialValue: 'spa',
options: [
{ value: 'spa', label: 'Single Page Application (only client-side)' },
{ value: 'ssg', label: 'Static Site Generation (prerenders pages)' },
],
}),
language: () =>
prompts.select({
message: 'Project language:',
Expand All @@ -45,11 +53,11 @@ const brandColor = /** @type {const} */ ([174, 128, 255]);
{ value: 'ts', label: 'TypeScript' },
],
}),
useRouter: () =>
useRouter: ({ results }) => results.appType === 'spa' ?
prompts.confirm({
message: 'Use router?',
initialValue: false,
}),
}) : Promise.resolve(false),
useESLint: () =>
prompts.confirm({
message: 'Use ESLint?',
Expand All @@ -68,13 +76,13 @@ const brandColor = /** @type {const} */ ([174, 128, 255]);

await useSpinner(
'Setting up your project directory...',
() => scaffold(targetDir, { useTS, useRouter, useESLint }),
() => scaffold(targetDir, { useTS, useRouter, useESLint, appType }),
'Set up project directory'
);

await useSpinner(
'Installing project dependencies...',
() => installDeps(targetDir, packageManager, { useTS, useRouter, useESLint }),
() => installDeps(targetDir, packageManager, { useTS, useRouter, useESLint, appType }),
'Installed project dependencies'
);

Expand Down Expand Up @@ -103,8 +111,9 @@ async function useSpinner(startMessage, fn, finishMessage) {
/**
* @typedef {Object} ConfigOptions
* @property {boolean} useTS
* @property {boolean} useRouter
* @property {unknown} useRouter
* @property {boolean} useESLint
* @property {string} appType
*/

/**
Expand All @@ -117,7 +126,11 @@ async function scaffold(to, opts) {
await fs.mkdir(to, { recursive: true });

const __dirname = dirname(fileURLToPath(import.meta.url));
await templateDir(resolve(__dirname, '../templates', 'base'), to, opts.useTS);
if (opts.appType === 'spa') {
await templateDir(resolve(__dirname, '../templates', 'base'), to, opts.useTS);
} else {
await templateDir(resolve(__dirname, '../templates', 'ssr'), to, opts.useTS);
}

if (opts.useRouter) {
await templateDir(
Expand Down
24 changes: 24 additions & 0 deletions templates/ssr/_gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
13 changes: 13 additions & 0 deletions templates/ssr/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Preact</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/index.jsx"></script>
</body>
</html>
13 changes: 13 additions & 0 deletions templates/ssr/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"noEmit": true,
"allowJs": true,
"checkJs": true,
"jsx": "react-jsx",
"jsxImportSource": "preact"
},
"include": ["node_modules/vite/client.d.ts", "**/*"]
}
19 changes: 19 additions & 0 deletions templates/ssr/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "example",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite build && vite preview"
},
"dependencies": {
"preact": "^10.16.0",
"preact-render-to-string": "^6.2.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.5.0",
"vite": "^4.3.2",
"vite-plugin-ssr": "^0.4.133"
}
}
1 change: 1 addition & 0 deletions templates/ssr/pages/assets/preact.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions templates/ssr/pages/index.page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import preactLogo from './assets/preact.svg';
import { useState } from 'preact/hooks'
import viteLogo from '/vite.svg';

export function Page() {
const [count, setCount] = useState(0);

return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} class="logo" alt="Vite logo" />
</a>
<a href="https://preactjs.com" target="_blank">
<img src={preactLogo} class="logo preact" alt="Preact logo" />
</a>
</div>
<h1>Vite + Preact</h1>
<div class="card">
<button onClick={() => setCount((count) => count + 1)}>count is {count}</button>
<p>
Edit <code>src/app.jsx</code> and save to test HMR
</p>
</div>
<p class="read-the-docs">Click on the Vite and Preact logos to learn more</p>
</>
);
}
1 change: 1 addition & 0 deletions templates/ssr/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions templates/ssr/renderer/PageShell.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PageContextProvider } from './usePageContext'

export { PageShell }

function PageShell({ pageContext, children }) {
return (
<PageContextProvider pageContext={pageContext}>
<main>{children}</main>
</PageContextProvider>
)
}
23 changes: 23 additions & 0 deletions templates/ssr/renderer/_default.page.client.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export { render }

import { hydrate } from 'preact'
import { PageShell } from './PageShell'

// This render() hook only supports SSR, see https://vite-plugin-ssr.com/render-modes for how to modify render() to support SPA
async function render(pageContext) {
const { Page, pageProps } = pageContext
if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined')
const root = document.getElementById('app')
if (!root) throw new Error('DOM element #app not found')

hydrate(
<PageShell pageContext={pageContext}>
<Page {...pageProps} />
</PageShell>,
root
)
}

/* To enable Client-side Routing:
export const clientRouting = true
// !! WARNING !! Before doing so, read https://vite-plugin-ssr.com/clientRouting */
44 changes: 44 additions & 0 deletions templates/ssr/renderer/_default.page.server.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
export { render }
// See https://vite-plugin-ssr.com/data-fetching
export const passToClient = ['pageProps', 'urlPathname']

import { renderToString } from 'preact-render-to-string'
import { PageShell } from './PageShell'
import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr/server'

async function render(pageContext) {
const { Page, pageProps } = pageContext
// This render() hook only supports SSR, see https://vite-plugin-ssr.com/render-modes for how to modify render() to support SPA
if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined')
const pageHtml = renderToString(
<PageShell pageContext={pageContext}>
<Page {...pageProps} />
</PageShell>
)

// See https://vite-plugin-ssr.com/head
const { documentProps } = pageContext.exports
const title = (documentProps && documentProps.title) || 'Vite SSR app'
const desc = (documentProps && documentProps.description) || 'App using Vite + vite-plugin-ssr'

const documentHtml = escapeInject`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="${desc}" />
<title>${title}</title>
</head>
<body>
<div id="app">${dangerouslySkipEscape(pageHtml)}</div>
</body>
</html>`

return {
documentHtml,
pageContext: {
// We can add some `pageContext` here, which is useful if we want to do page redirection https://vite-plugin-ssr.com/page-redirection
}
}
}
19 changes: 19 additions & 0 deletions templates/ssr/renderer/usePageContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// `usePageContext` allows us to access `pageContext` in any Preact component.
// See https://vite-plugin-ssr.com/pageContext-anywhere

import { createContext } from 'preact'
import { useContext } from 'preact/hooks'

export { PageContextProvider }
export { usePageContext }

const Context = createContext(undefined)

function PageContextProvider({ pageContext, children }) {
return <Context.Provider value={pageContext}>{children}</Context.Provider>
}

function usePageContext() {
const pageContext = useContext(Context)
return pageContext
}
1 change: 1 addition & 0 deletions templates/ssr/src/assets/preact.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions templates/ssr/src/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { render } from 'preact';
import { useState } from 'preact/hooks';
import preactLogo from './assets/preact.svg';
import viteLogo from '/vite.svg';
import './style.css';

export function App() {
const [count, setCount] = useState(0);

return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} class="logo" alt="Vite logo" />
</a>
<a href="https://preactjs.com" target="_blank">
<img src={preactLogo} class="logo preact" alt="Preact logo" />
</a>
</div>
<h1>Vite + Preact</h1>
<div class="card">
<button onClick={() => setCount((count) => count + 1)}>count is {count}</button>
<p>
Edit <code>src/app.jsx</code> and save to test HMR
</p>
</div>
<p class="read-the-docs">Click on the Vite and Preact logos to learn more</p>
</>
);
}

render(<App />, document.getElementById('app'));
Loading

0 comments on commit 457a153

Please sign in to comment.