Skip to content

Commit

Permalink
Merge pull request #244 from AthennaIO/develop
Browse files Browse the repository at this point in the history
feat(web): add docs about SSR
  • Loading branch information
jlenon7 authored Jan 16, 2025
2 parents bdff97a + dabf7cd commit 7d288e0
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 16 deletions.
5 changes: 5 additions & 0 deletions docs/getting-started/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ using [Edge.js](https://edgejs.dev/docs/introduction) as template engine
to serve static HTML from the server.
- `WEB REACT` application is ideal for creating full-stack applications using
[React](https://react.dev/).
- `WEB REACT SSR` application is ideal for creating full-stack applications using
[React](https://react.dev/) applying [SSR (Server Side Rendering)](https://www.sanity.io/glossary/server-side-rendering)
techniques for faster page loads and to allow search engines to crawl your
pages for [SEO (Search Engine Optimization)(https://searchengineland.com/guide/what-is-seo)
purposes.

## Running your application

Expand Down
162 changes: 146 additions & 16 deletions docs/rest-api-application/web-application.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ athenna new my-web-app

:::note

Don't forget to select `WEB EDGE` or `WEB REACT` when prompted about the
application type.
Don't forget to select `WEB EDGE`, `WEB REACT` or `WEB REACT SSR` when
prompted about the application type.

:::

Expand All @@ -63,6 +63,15 @@ imports. Each entry point will result in a separate output bundle.
Also, if needed, you can define multiple entrypoints. For example, an
entry point for your user-facing app and another for the admin panel.

#### assetsUrl

It contains the URL to prefix when generating links for assets in
production. If you upload the Vite output to a CDN, then the value
of this property should be the CDN server URL.

Ensure you update the backend configuration to use the same `assetsUrl`
value.

#### buildDirectory

The `buildDirectory` option defines a relative path to the output
Expand All @@ -72,7 +81,7 @@ If you decide to change the default value, make sure also to update the
`buildDirectory` path in the `vite` object inside <Path father="config" child="http.ts" />
configuration file.

Default: `public/assets`
Default: `Path.public('assets')`

#### reload

Expand All @@ -81,15 +90,6 @@ on file change. By default, we watch for Edge templates in `WEB EDGE`
application and `.tsx` files on `WEB REACT`. However, you can
configure additional patterns as well.

#### assetsUrl

It contains the URL to prefix when generating links for assets in
production. If you upload the Vite output to a CDN, then the value
of this property should be the CDN server URL.

Ensure you update the backend configuration to use the same `assetsUrl`
value.

### Vite backend configuration

#### dev
Expand All @@ -99,17 +99,33 @@ By default, this is controlled by the `Config.get('app.environment')`
configuration which points to the `APP_ENV` environment variable
defined in your `.env` file.

#### assetsUrl

The URL to prefix when generating links for assets in production.
If you upload the Vite output to a CDN, then the value of this
property should be the CDN server URL.

#### buildDirectory

It contains the path to the Vite's build output directory.
You must also update this backend config if you change the
default value inside the `vite.config.ts` file.

#### assetsUrl
#### ssrEntrypoint

The URL to prefix when generating links for assets in production.
If you upload the Vite output to a CDN, then the value of this
property should be the CDN server URL.
With this option set, SSR will be turn on into your application.
This defines where Vite needs to look when compiling your server
entrypoint files and when searching for the default entrypoint to
render when using `response.render()` method.

Default: `src/resources/app/app.tsx`

#### ssrBuildDirectory

It contains the path to the Vite's SSR build output directory, which
needs to export the components so the server could import and serve it.

Default: `Path.public('assets/server')`

#### scriptAttributes

Expand Down Expand Up @@ -343,6 +359,120 @@ export default {
}
```

## Server Side Rendering (SSR)

SSR, short for Server-Side Rendering, is a technique in web development
where the webpage's content is rendered on the server instead of the client's
browser. The primary advantage of SSR lies in its ability to significantly
enhance user experience by facilitating faster page transitions and quick
loading times.

If you use `WEB EDGE` application type you will be already using
SSR by default, but you can't use nice frameworks like React without some heavy
configuration.

That's why Athenna exposes the `WEB REACT SSR` application type that will come
with everything configured for you to start building your application. The key
difference from `WEB REACT` and `WEB REACT SSR` is that instead of letting the
client create and load React root, we do that on the server and just hydrate the
root in the client, which is way less expensive for the client machine.

### Configurations

The configurations in your `vite` object of <Path father="config" child="http.ts" />
that make your application understand you want to use some framework
with SSR are the following:

```typescript
export default {
vite: {
// ...

ssrEntrypoint: 'src/resources/app/app.tsx',
ssrBuildDirectory: Path.public('assets/server')
}
}
```

- `ssrEntrypoint` will map your server entrypoint for serving your
component.
- `ssrBuildDirectory` will map where the server entrypoint compiled
code should be stored. This property also defines where the manifest
file of your server code will stored, in this case our manifest file
would be stored inside <Path father="public" child="assets/server/.vite/manifest.json" />.

:::note

Vite never will compile your backend code, this will still be done by
`tsc`. The `ssrEntrypoint` file is the entrypoint of your backend
code to the client code, Vite compiles your entrypoint in runtime
(in development) so we avoid adding features to `tsc` to load files
like CSS, JSX, SASS and etc.

:::

### Hydrate part

In the <Path father="resources" child="app/root.tsx" /> we are
hydrating the root element using React API:

```typescript
import { App } from '#app/app'
import { hydrateRoot } from 'react-dom/client'

hydrateRoot(document.getElementById('root'), <App />)
```

:::note

For now Athenna has integration only with React for SSR. If you want
support for other frameworks, please [open a discussion](https://github.com/orgs/AthennaIO/discussions).

:::

### Rendering React components

The `@athenna/vite` package exposes the `React` helper which you
can use to load and render components inside your backend routes.
The following example is the default example that comes with the
`WEB REACT SSR` application type:

```typescript
import { React } from '@athenna/vite'
import { Controller, type Context } from '@athenna/http'

@Controller()
export class AppController {
public async index({ request, response }: Context) {
const { createApp } = await React.loadEntrypoint()

const element = await React.renderComponent(createApp(request.baseUrl))

return response.view('index', { element })
}
}
```

1. First we use the `loadEntrypoint()` method that internally will
use Vite to compile (or search in manifest file) the content of your
`ssrEntrypoint` file. After that the module is imported and you can
use all the resources from the file.
2. After importing the `createApp()` function from our entrypoint,
we call the function to create our `<App/>` component and send as
parameter to the `renderComponent()` method which will use `react-dom/server`
to transform the component to an HTML string.
3. Now is simple, we just need to send our element to `index.edge`
view which will render all the elements.

#### Importing other components

In case you want to import other components beside the entrypoint
you can use the `loadComponent()` method:

```typescript
const { createApp } = await React.loadComponent('src/resources/app/app.tsx')
```

## Manifest file

Vite generates the manifest file alongside the production build
Expand Down

0 comments on commit 7d288e0

Please sign in to comment.