Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(SSG): Add isSSG and isSSR API #2033

Closed
wants to merge 6 commits into from
Closed

Conversation

nakasyou
Copy link
Contributor

@nakasyou nakasyou commented Jan 19, 2024

I added isSSG and isSSR API to SSG helper.
You can switch SSG/SSR if you merge.

Examples

SSG-Based mode (default is undefined)

import { Hono } from 'hono'
import { isSSG, isSSR, toSSG } from 'hono/ssg'

const app = new Hono()

app.get('/', c => c.html(<h1>Static Top Page</h1>))
app.get('/api', isSSR(), c => c.json({ random: Math.random() }))

await toSSG(app, fs)

SSG-Based mode (default is ssg)

import { Hono } from 'hono'
import { isSSG, isSSR, toSSG } from 'hono/ssg'

const app = new Hono()

app.get('/', c => c.html(<h1>Static Top Page</h1>))
app.get('/api', isSSR(), c => c.json({ random: Math.random() }))

await toSSG(app, fs, {
  default: 'ssg'
})

SSR-Based mode (default is ssr)

import { Hono } from 'hono'
import { isSSG, isSSR, toSSG } from 'hono/ssg'

const app = new Hono()

app.get('/', isSSG(), c => c.html(<h1>Static Top Page</h1>))
app.get('/api', c => c.json({ random: Math.random() }))

await toSSG(app, fs, {
  default: 'ssg'
})

Author should do the followings, if applicable

  • Add tests
  • Run tests
  • yarn denoify to generate files for Deno

@watany-dev
Copy link
Contributor

@nakasyou

Thanks, I think PR should be for v4.

@yusukebe yusukebe changed the base branch from main to v4 January 19, 2024 11:13
@nakasyou
Copy link
Contributor Author

Sorry, I mistook, it is second time.

@yusukebe
Copy link
Member

yusukebe commented Jan 19, 2024

@nakasyou

I'm checking about this PR. I have one question for you. Are you referring to other frameworks, such as Astro or Svelte, for these features?

@nakasyou
Copy link
Contributor Author

nakasyou commented Jan 20, 2024

@yusukebe

Are you referring to other frameworks, such as Astro or Svelte, for these features?

No, I'm not. But this idea is from Astro and Svelte.

In Astro, you can switch SSR/SSG:

---
export const prerender = true // SSG
---
<h1>Static Page</h1>
---
export const prerender = false // SSR
---
<h1>{ Math.random() }</h1>

Or, you can set config file default:

// astro.config.ts
import { defineConfig } from 'astro'

export default defineConfig({
  output: 'server', // Default is SSR
  // output: 'hybrid', // Default is SSG
  // output: 'static' // All SSG
})

If you use Astro, you create a file for each route. Hono isn't so. So I added isSSG and isSSR API.

@watany-dev
Copy link
Contributor

watany-dev commented Jan 20, 2024

Sorry that I suggested the name, but maybe server/static is more familiar and cooler than SSR/SSG!

Let's leave the name on this ticket and talk about it here.
#2043

@yusukebe
Copy link
Member

@nakasyou Thanks!

@watany-dev

As I mentioned in #2043, I think SSR/SSG is better than server/static.

If it is server or static, I don't know "what it does." With SSR, I know what it means "the application renders on the Server Side", and with SSG, I know what it means "create a Static site".

@yusukebe
Copy link
Member

yusukebe commented Jan 20, 2024

As for isSSG/isSSR, maybe asSSG/asSSR is better than isSSG/isSSR. However, I think either is acceptable.

@nakasyou
Copy link
Contributor Author

@yusukebe

As for isSSG/isSSR, maybe asSSG/asSSR is better than isSSG/isSSR. However, I think either is acceptable

I'm not familiar with English. So I can't decide which is better isSSG/isSSR or asSSG/asSSR, I want to hear many people thought.

@yusukebe yusukebe added the v4 label Jan 21, 2024
@yusukebe
Copy link
Member

Hey @nakasyou !

Please wait a moment for this PR review and merge. I'm actually using it and testing its use.

@yusukebe
Copy link
Member

Hi @nakasyou and @watany-dev

Sorry for the late reply. I have been considering about this isSSG and isSSR for a while. The following is my opinion.

  • We should make the API simple.
  • We don't need both isSSG and isSSR.
  • If we use toSSG(), ssg should always be the default.
  • I want just doNotSSG() though namign should be considered.
app.get('/api', doNotSSG(), (c) => {
  return c.json(0)
})

What do you think about it?

@watany-dev
Copy link
Contributor

watany-dev commented Jan 26, 2024

As you say, I think we don't need two middlewares.

How about a middleware Interface like defineRender() based on this parameter?
https://nuxt.com/docs/guide/concepts/rendering

This time, we will create a prerender or ssg option, and add swr (stale-while-revalidate) or spa (ssr: false) when necessary.

  • case1: toSSG
// Follows the default of toSSG.
app.get('/ssg/1', (c) => {
    return c.html('ssg1')
})
// If ssg: undefined, it follows the default of toSSG.
app.get('/ssg/2', defineRender(), (c) => {
    return c.html('ssg2')
})
app.get('/ssg/3', defineRender(ssg: true), (c) => {
    return c.html('ssg3')
})
app.get('/ssr', defineRender(ssg: false), (c) => {
    return c.html('ssr')
})

// SSG:
// ./static/ssg/1.html
// ./static/ssg/2.html
// ./static/ssg/3.html
toSSG(app, fs)
  • case2: toSSG and default SSG is not.
// Follows the default of toSSG.
app.get('/ssg/1', (c) => {
    return c.html('ssg1')
})
// If ssg: undefined, it follows the default of toSSG.
app.get('/ssg/2', defineRender(), (c) => {
    return c.html('ssg2')
})
app.get('/ssg/3', defineRender(ssg: true), (c) => {
    return c.html('ssg3')
})
app.get('/ssr', defineRender(ssg: false), (c) => {
    return c.html('ssr')
})

// SSG:
// ./static/ssg/3.html
toSSG(app, fs, {
  defaultSSG: false // default true
})

@nakasyou
Copy link
Contributor Author

nakasyou commented Jan 26, 2024

Hi @yusukebe @watany-dev, thank you for reviewing.
I think @watany-dev 's idea is better than doNotSSG() API.

It is very smart, and it's customizable.

If we use toSSG(), ssg should always be the default.

I don't think for that.
I think there are cases of SSR route is more common than the SSG route.
Also, Astro has SSR-Based mode.

So I don't think SSG should always be the default, and @watany-dev 's idea is better.

@yusukebe
Copy link
Member

Hi @nakasyou and @watany-dev

How about #2104 ?

@nakasyou
Copy link
Contributor Author

Hi @yusukebe

Hi @nakasyou and @watany-dev

How about #2104 ?

I think we can write this code.

app.use('*', disableSSG())
app.get('/', c => c.json('Hello world!'))

This code is like SSR-Based mode. I think this is cool.
If it's able, we don't have to make { default: 'ssg' } option.

@nakasyou
Copy link
Contributor Author

#2104

@nakasyou nakasyou closed this Jan 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants