Skip to content

Commit

Permalink
feat: ssr router support
Browse files Browse the repository at this point in the history
  • Loading branch information
htmujahid committed Oct 2, 2024
1 parent 2dca28c commit 3e94e9c
Showing 78 changed files with 2,763 additions and 1,280 deletions.
1,864 changes: 1,553 additions & 311 deletions package-lock.json

Large diffs are not rendered by default.

34 changes: 29 additions & 5 deletions packages/create-sonnet/index.js
Original file line number Diff line number Diff line change
@@ -197,11 +197,18 @@ async function init() {
message: 'Select a template',
choices: [
{ title: 'Default', value: 'default' },
{ title: 'Router', value: 'router' },
{ title: 'SSR', value: 'ssr' },
],
initial: 0,
},
{
name: 'needsRouter',
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
message: language.needsRouter.message,
initial: false,
active: language.defaultToggleOptions.active,
inactive: language.defaultToggleOptions.inactive
},
{
name: 'needsTypeScript',
type: () => (isFeatureFlagsUsed ? null : 'toggle'),
@@ -256,10 +263,27 @@ async function init() {
render('base')

// Render code template.
// prettier-ignore
const codeTemplate =
(result.selectTemplate) +
(needsTypeScript ? '-ts' : '')
let codeTemplate = '';
switch (result.selectTemplate) {
case 'ssr':
codeTemplate = 'ssr';
break;
case 'default':
codeTemplate = 'default';
break;
default:
codeTemplate = 'default'
break;
}

if (result.needsRouter) {
codeTemplate += 'router';
}

if (needsTypeScript) {
codeTemplate += '-ts';
}

render(`code/${codeTemplate}`)

// An external data store for callbacks to share data
2 changes: 1 addition & 1 deletion packages/create-sonnet/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-sonnet-app",
"version": "0.0.18",
"version": "0.0.19",
"description": "",
"main": "index.js",
"type": "module",
Original file line number Diff line number Diff line change
@@ -10,6 +10,6 @@
},
"dependencies": {
"@sonnetjs/core": "0.0.33",
"@sonnetjs/router": "0.0.5"
"@sonnetjs/router": "0.0.7"
}
}
Original file line number Diff line number Diff line change
@@ -9,6 +9,6 @@
},
"dependencies": {
"@sonnetjs/core": "0.0.33",
"@sonnetjs/router": "0.0.5"
"@sonnetjs/router": "0.0.7"
}
}
14 changes: 14 additions & 0 deletions packages/create-sonnet/template/code/ssr-router-ts/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!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 + TS</title>
<!--app-head-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/entry-client.ts"></script>
</body>
</html>
28 changes: 28 additions & 0 deletions packages/create-sonnet/template/code/ssr-router-ts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "ssr-router",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "node server",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --ssrManifest --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.ts --outDir dist/server",
"preview": "cross-env NODE_ENV=production node server"
},
"dependencies": {
"@remix-run/router": "^1.15.3",
"compression": "^1.7.4",
"express": "^4.18.2",
"sirv": "^2.0.4",
"@sonnetjs/core": "0.0.33",
"@sonnetjs/router": "0.0.7"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/node": "^20.10.5",
"cross-env": "^7.0.3",
"typescript": "^5.3.3",
"vite": "^5.0.10"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions packages/create-sonnet/template/code/ssr-router-ts/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import fs from 'node:fs/promises';
import express from 'express';

// Constants
const isProduction = process.env.NODE_ENV === 'production';
const port = process.env.PORT || 4000;
const base = process.env.BASE || '/';

// Cached production assets
const templateHtml = isProduction
? await fs.readFile('./dist/client/index.html', 'utf-8')
: '';
const ssrManifest = isProduction
? await fs.readFile('./dist/client/.vite/ssr-manifest.json', 'utf-8')
: undefined;

// Create http server
const app = express();

// Add Vite or respective production middlewares
let vite;
if (!isProduction) {
const { createServer } = await import('vite');
vite = await createServer({
server: { middlewareMode: true, watch: { usePolling: true } },
appType: 'custom',
base,
});
app.use(vite.middlewares);
} else {
const compression = (await import('compression')).default;
const sirv = (await import('sirv')).default;
app.use(compression());
app.use(base, sirv('./dist/client', { extensions: [] }));
}

// Serve HTML
app.use('*', async (req, res) => {
try {
const url = req.originalUrl.replace(base, '');

let template;
let render;
if (!isProduction) {
// Always read fresh template in development
template = await fs.readFile('./index.html', 'utf-8');
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule('/src/entry-server.ts')).render;
} else {
template = templateHtml;
render = (await import('./dist/server/entry-server.js')).render;
}

const rendered = await render(url, ssrManifest);

const html = template
.replace(`<!--app-head-->`, rendered.head ?? '')
.replace(`<!--app-html-->`, rendered.html ?? '');

res.status(200).set({ 'Content-Type': 'text/html' }).send(html);
} catch (e) {
vite?.ssrFixStacktrace(e);
console.log(e.stack);
res.status(500).end(e.stack);
}
});

// Start http server
app.listen(port, () => {
console.log(`Server started at http://localhost:${port}`);
});
19 changes: 19 additions & 0 deletions packages/create-sonnet/template/code/ssr-router-ts/src/App.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { $component, SonnetComponent } from '@sonnetjs/core';
import { header } from './partials/header';

class App extends SonnetComponent {
static script(): void {
console.log('App script');
}

public get() {
return /*html */ `
${header()}
<div id="app-1">
${this._children}
</div
`;
}
}

export default $component(App);
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import './style.css';
import { createApp } from '@sonnetjs/core';

import App from './App';
import { routers } from './routes';

const app = createApp();
app.root(App);
app.use(routers);
app.lazy();
app.ssr();
app.mount('#app');
app.initialized();
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import App from './App';
import { routers } from './routes';

export async function render(url: string) {
routers.navigate(url ? url : '/');

const { root, children } = await routers.hyderate(App);

if (!root) {
return { html: url };
}

const html = root().children(children ?? '').get();

return { html };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { $component, SonnetComponent } from '@sonnetjs/core';
class About extends SonnetComponent {
public get() {
return /*html */ `
<div>
<h1>About</h1>
<p>Welcome to the Sonnet Playground</p>
</div>
`;
}
}

export default $component(About);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { $component, SonnetComponent } from '@sonnetjs/core';

class Contact extends SonnetComponent {
public get() {
return /*html */ `
<div>
<h1>Contact</h1>
<p>Welcome to the Sonnet Playground</p>
</div>
`;
}
}

export default $component(Contact);
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { $component, SonnetComponent } from '@sonnetjs/core';

class Home extends SonnetComponent {
script(): void {
console.log('Home script');
}
public get() {
return /*html */ `
<div>
<h1>Home</h1>
<p>Welcome to the Sonnet Playground</p>
</div>
`;
}
}

export default $component(Home);
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { $component, SonnetComponent } from '@sonnetjs/core';

class RootComponent extends SonnetComponent {
public get() {
return /*html*/ `
<div>
${this._children}
this is new thing
</div>
`;
}
}

export default $component(RootComponent);
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export const header = () => /*html*/ `
<header>
<h1>My Website</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact/1/1">Contact</a>
</nav>
</header>
`;
13 changes: 13 additions & 0 deletions packages/create-sonnet/template/code/ssr-router-ts/src/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { router, createMemoryHistory, createRouter } from '@sonnetjs/router';

export const routes = router().layout(
async () => (await import('./partials/Layout')).default()
).children([
router().path('/').component(async () => (await import('./pages/Home')).default()).get(),
router().path('/about').component(async () => (await import('./pages/About')).default()).get(),
router().path('/contact/1/1').component(async () => (await import('./pages/Contact')).default()).get(),
]).get()

const history = createMemoryHistory();

export const routers = createRouter().routes(routes).history(history).mountedId('#app-1').get();
Loading

0 comments on commit 3e94e9c

Please sign in to comment.