From a26231c31fead7d8bd38497a0b2730fea42e152c Mon Sep 17 00:00:00 2001 From: jlenon7 Date: Thu, 16 Jan 2025 13:06:58 -0300 Subject: [PATCH 1/3] feat(web): add docs about SSR --- docs/getting-started/installation.mdx | 5 + docs/rest-api-application/web-application.mdx | 139 ++++++++++++++++-- 2 files changed, 128 insertions(+), 16 deletions(-) diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index 35b041b1..d3cf028e 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -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 diff --git a/docs/rest-api-application/web-application.mdx b/docs/rest-api-application/web-application.mdx index 82b70e68..aa64ee01 100644 --- a/docs/rest-api-application/web-application.mdx +++ b/docs/rest-api-application/web-application.mdx @@ -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. ::: @@ -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 @@ -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 configuration file. -Default: `public/assets` +Default: `Path.public('assets')` #### reload @@ -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 @@ -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 @@ -343,6 +359,97 @@ export default { } ``` +## Server Side Rendering (SSR) + +:::note + +If you want to use SSR we recommend bootstrapping an application choosing +`WEB REACT SSR` application type which will come with everything already +configured for you. + +::: + +If you bootstrap your project using the `WEB REACT` application type +your application will not be using SSR by default and would require +some configurations: + +#### Add SSR properties + +In your `vite` object inside , +add the SSR properties: + +```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 . + +:::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. + +::: + +### 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 `` 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 From b948b9ff46118da45852021a173d3f559948b6fa Mon Sep 17 00:00:00 2001 From: jlenon7 Date: Thu, 16 Jan 2025 13:07:18 -0300 Subject: [PATCH 2/3] feat(web): add docs about SSR --- docs/rest-api-application/web-application.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/rest-api-application/web-application.mdx b/docs/rest-api-application/web-application.mdx index aa64ee01..c92bea8a 100644 --- a/docs/rest-api-application/web-application.mdx +++ b/docs/rest-api-application/web-application.mdx @@ -440,7 +440,6 @@ 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 From dabf7cdb452bfb030115f9675fa06aec0c5602dc Mon Sep 17 00:00:00 2001 From: jlenon7 Date: Thu, 16 Jan 2025 13:26:33 -0300 Subject: [PATCH 3/3] feat(web): add docs about SSR --- docs/rest-api-application/web-application.mdx | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/docs/rest-api-application/web-application.mdx b/docs/rest-api-application/web-application.mdx index c92bea8a..97250401 100644 --- a/docs/rest-api-application/web-application.mdx +++ b/docs/rest-api-application/web-application.mdx @@ -361,22 +361,27 @@ export default { ## Server Side Rendering (SSR) -:::note - -If you want to use SSR we recommend bootstrapping an application choosing -`WEB REACT SSR` application type which will come with everything already -configured for you. +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. -If you bootstrap your project using the `WEB REACT` application type -your application will not be using SSR by default and would require -some configurations: +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. -#### Add SSR properties +### Configurations -In your `vite` object inside , -add the SSR properties: +The configurations in your `vite` object of +that make your application understand you want to use some framework +with SSR are the following: ```typescript export default { @@ -406,6 +411,25 @@ like CSS, JSX, SASS and etc. ::: +### Hydrate part + +In the 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'), ) +``` + +:::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