-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Checkpoint, basics are working * Add the `--experimental-ssr` flag * Adds the changeset * Fixes population of getStaticPaths results * Pass through the imported module * Route manifest test * Fix remaining tests * Fix remaining tests * Copy server assets over * Fix types * Allowing passing in the request to the Node version of App * Improve the example app * Gets CI to pass
- Loading branch information
Showing
67 changed files
with
1,684 additions
and
627 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
--- | ||
'astro': patch | ||
--- | ||
|
||
Experimental SSR Support | ||
|
||
> ⚠️ If you are a user of Astro and see this PR and think that you can start deploying your app to a server and get SSR, slow down a second! This is only the initial flag and **very basic support**. Styles are not loading correctly at this point, for example. Like we did with the `--experimental-static-build` flag, this feature will be refined over the next few weeks/months and we'll let you know when its ready for community testing. | ||
## Changes | ||
|
||
- This adds a new `--experimental-ssr` flag to `astro build` which will result in `dist/server/` and `dist/client/` directories. | ||
- SSR can be used through this API: | ||
```js | ||
import { createServer } from 'http'; | ||
import { loadApp } from 'astro/app/node'; | ||
|
||
const app = await loadApp(new URL('./dist/server/', import.meta.url)); | ||
|
||
createServer((req, res) => { | ||
const route = app.match(req); | ||
if(route) { | ||
let html = await app.render(req, route); | ||
} | ||
|
||
}).listen(8080); | ||
``` | ||
- This API will be refined over time. | ||
- This only works in Node.js at the moment. | ||
- Many features will likely not work correctly, but rendering HTML at least should. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// @ts-check | ||
|
||
export default /** @type {import('astro').AstroUserConfig} */ ({ | ||
renderers: ['@astrojs/renderer-svelte'], | ||
vite: { | ||
server: { | ||
proxy: { | ||
'/api': 'http://localhost:8085' | ||
} | ||
} | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import {execa} from 'execa'; | ||
|
||
const api = execa('npm', ['run', 'dev-api']); | ||
api.stdout.pipe(process.stdout); | ||
api.stderr.pipe(process.stderr); | ||
|
||
const build = execa('yarn', ['astro', 'build', '--experimental-ssr']); | ||
build.stdout.pipe(process.stdout); | ||
build.stderr.pipe(process.stderr); | ||
await build; | ||
|
||
api.kill(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "@example/ssr", | ||
"version": "0.0.1", | ||
"private": true, | ||
"scripts": { | ||
"dev-api": "node server/dev-api.mjs", | ||
"dev": "npm run dev-api & astro dev --experimental-ssr", | ||
"start": "astro dev", | ||
"build": "echo 'Run yarn build-ssr instead'", | ||
"build-ssr": "node build.mjs", | ||
"server": "node server/server.mjs" | ||
}, | ||
"devDependencies": { | ||
"astro": "^0.23.0-next.0", | ||
"unocss": "^0.15.5", | ||
"vite-imagetools": "^4.0.1" | ||
}, | ||
"dependencies": { | ||
"@astropub/webapi": "^0.10.13" | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import fs from 'fs'; | ||
const dbJSON = fs.readFileSync(new URL('./db.json', import.meta.url)); | ||
const db = JSON.parse(dbJSON); | ||
const products = db.products; | ||
const productMap = new Map(products.map(product => [product.id, product])); | ||
|
||
const routes = [ | ||
{ | ||
match: /\/api\/products\/([0-9])+/, | ||
async handle(_req, res, [,idStr]) { | ||
const id = Number(idStr); | ||
if(productMap.has(id)) { | ||
const product = productMap.get(id); | ||
res.writeHead(200, { | ||
'Content-Type': 'application/json' | ||
}); | ||
res.end(JSON.stringify(product)); | ||
} else { | ||
res.writeHead(404, { | ||
'Content-Type': 'text/plain' | ||
}); | ||
res.end('Not found'); | ||
} | ||
} | ||
}, | ||
{ | ||
match: /\/api\/products/, | ||
async handle(_req, res) { | ||
res.writeHead(200, { | ||
'Content-Type': 'application/json', | ||
}); | ||
res.end(JSON.stringify(products)); | ||
} | ||
} | ||
|
||
] | ||
|
||
export async function apiHandler(req, res) { | ||
for(const route of routes) { | ||
const match = route.match.exec(req.url); | ||
if(match) { | ||
return route.handle(req, res, match); | ||
} | ||
} | ||
res.writeHead(404, { | ||
'Content-Type': 'text/plain' | ||
}); | ||
res.end('Not found'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"products": [ | ||
{ | ||
"id": 1, | ||
"name": "Cereal", | ||
"price": 3.99, | ||
"image": "/images/products/cereal.jpg" | ||
}, | ||
{ | ||
"id": 2, | ||
"name": "Yogurt", | ||
"price": 3.97, | ||
"image": "/images/products/yogurt.jpg" | ||
}, | ||
{ | ||
"id": 3, | ||
"name": "Rolled Oats", | ||
"price": 2.89, | ||
"image": "/images/products/oats.jpg" | ||
}, | ||
{ | ||
"id": 4, | ||
"name": "Muffins", | ||
"price": 4.39, | ||
"image": "/images/products/muffins.jpg" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { createServer } from 'http'; | ||
import { apiHandler } from './api.mjs'; | ||
|
||
const PORT = process.env.PORT || 8085; | ||
|
||
const server = createServer((req, res) => { | ||
apiHandler(req, res).catch(err => { | ||
console.error(err); | ||
res.writeHead(500, { | ||
'Content-Type': 'text/plain' | ||
}); | ||
res.end(err.toString()); | ||
}) | ||
}); | ||
|
||
server.listen(PORT); | ||
console.log(`API running at http://localhost:${PORT}`); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { createServer } from 'http'; | ||
import fs from 'fs'; | ||
import mime from 'mime'; | ||
import { loadApp } from 'astro/app/node'; | ||
import { polyfill } from '@astropub/webapi' | ||
import { apiHandler } from './api.mjs'; | ||
|
||
polyfill(globalThis); | ||
|
||
const clientRoot = new URL('../dist/client/', import.meta.url); | ||
const serverRoot = new URL('../dist/server/', import.meta.url); | ||
const app = await loadApp(serverRoot); | ||
|
||
async function handle(req, res) { | ||
const route = app.match(req); | ||
|
||
if(route) { | ||
const html = await app.render(req, route); | ||
|
||
res.writeHead(200, { | ||
'Content-Type': 'text/html' | ||
}); | ||
res.end(html) | ||
} else if(/^\/api\//.test(req.url)) { | ||
return apiHandler(req, res); | ||
} else { | ||
let local = new URL('.' + req.url, clientRoot); | ||
try { | ||
const data = await fs.promises.readFile(local); | ||
res.writeHead(200, { | ||
'Content-Type': mime.getType(req.url) | ||
}); | ||
res.end(data); | ||
} catch { | ||
res.writeHead(404); | ||
res.end(); | ||
} | ||
} | ||
} | ||
|
||
const server = createServer((req, res) => { | ||
handle(req, res).catch(err => { | ||
console.error(err); | ||
res.writeHead(500, { | ||
'Content-Type': 'text/plain' | ||
}); | ||
res.end(err.toString()); | ||
}) | ||
}); | ||
|
||
server.listen(8085); | ||
console.log('Serving at http://localhost:8085'); | ||
|
||
// Silence weird <time> warning | ||
console.error = () => {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
interface Product { | ||
id: number; | ||
name: string; | ||
price: number; | ||
image: string; | ||
} | ||
|
||
//let origin: string; | ||
const { mode } = import.meta.env; | ||
const origin = mode === 'develeopment' ? | ||
`http://localhost:3000` : | ||
`http://localhost:8085`; | ||
|
||
async function get<T>(endpoint: string, cb: (response: Response) => Promise<T>): Promise<T> { | ||
const response = await fetch(`${origin}${endpoint}`); | ||
if(!response.ok) { | ||
// TODO make this better... | ||
return null; | ||
} | ||
return cb(response); | ||
} | ||
|
||
export async function getProducts(): Promise<Product[]> { | ||
return get<Product[]>('/api/products', async response => { | ||
const products: Product[] = await response.json(); | ||
return products; | ||
}); | ||
} | ||
|
||
export async function getProduct(id: number): Promise<Product> { | ||
return get<Product>(`/api/products/${id}`, async response => { | ||
const product: Product = await response.json(); | ||
return product; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<script> | ||
export let id = 0; | ||
function addToCart() { | ||
window.dispatchEvent(new CustomEvent('add-to-cart', { | ||
detail: id | ||
})); | ||
} | ||
</script> | ||
<style> | ||
button { | ||
display:block; | ||
padding:0.5em 1em 0.5em 1em; | ||
border-radius:100px; | ||
border:none; | ||
font-size: 1.4em; | ||
position:relative; | ||
background:#0652DD; | ||
cursor:pointer; | ||
height:2em; | ||
width:10em; | ||
overflow:hidden; | ||
transition:transform 0.1s; | ||
z-index:1; | ||
} | ||
button:hover { | ||
transform:scale(1.1); | ||
} | ||
.pretext { | ||
color:#fff; | ||
background:#0652DD; | ||
position:absolute; | ||
top:0; | ||
left:0; | ||
height:100%; | ||
width:100%; | ||
display:flex; | ||
justify-content:center; | ||
align-items:center; | ||
font-family: 'Quicksand', sans-serif; | ||
text-transform: uppercase; | ||
} | ||
</style> | ||
<button on:click={addToCart}> | ||
<span class="pretext">Add to cart</span> | ||
</button> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<script> | ||
export let count = 0; | ||
let items = new Set(); | ||
function onAddToCart(ev) { | ||
const id = ev.detail; | ||
items.add(id); | ||
count++; | ||
} | ||
</script> | ||
<style> | ||
.cart { | ||
display: flex; | ||
align-items: center; | ||
} | ||
.cart :first-child { | ||
margin-right: 5px; | ||
} | ||
.cart-icon { | ||
font-size: 36px; | ||
} | ||
.count { | ||
font-size: 24px; | ||
} | ||
</style> | ||
<svelte:window on:add-to-cart={onAddToCart}/> | ||
<div class="cart"> | ||
<span class="material-icons cart-icon">shopping_cart</span> | ||
<span class="count">{count}</span> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
const { tag = 'div' } = Astro.props; | ||
const Tag = tag; | ||
--- | ||
<style> | ||
.container { | ||
width: 1248px; /** TODO: responsive */ | ||
margin-left: auto; | ||
margin-right: auto; | ||
} | ||
</style> | ||
<Tag class="container"><slot /></Tag> |
Oops, something went wrong.