Skip to content

Commit

Permalink
Externalize prepare template
Browse files Browse the repository at this point in the history
  • Loading branch information
Willy Brauner committed Nov 17, 2022
1 parent 7f83490 commit 72ae8d5
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 50 deletions.
2 changes: 1 addition & 1 deletion docs/02.vite-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Vite's configuration is managed by two main files:

### <a name="Entrypoints"></a>Entry points

By default, the single application entrypoint is [src/index.tsx](src/index.tsx). It initializes a react App.
By default, the single application entrypoint is [src/index.tsx](src/index-client.tsx). It initializes a react App.
But this file can be changed as `index.ts` or `index.js`. In case this filename or type change, [config/config.js](config/config.js)
`input` array need to be modified.

Expand Down
2 changes: 1 addition & 1 deletion docs/03.vite-simple-spa-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In order to always keep the same folder structure, this config generates statics
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
<script type="module" src="/src/index-client.tsx"></script>
</body>
</html>
```
Expand Down
2 changes: 1 addition & 1 deletion docs/09.php-service-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
- Add `./composer-install.sh` script in the project root.
- Add docker apache volume in `docker-compose.yml`
- Remove ssr ssg files
- [server.js](../server.js)
- [server.js](../server/server.js)
- [vite.scripts.config.js](../vite.scripts.config.js)
- [index.html](index.html)
- Update [config/config.js](../config/config.js)
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

<body>
<div id="root"><!--app-html--></div>
<script type="module" src="/src/index.tsx"></script>
<script type="module" src="/src/index-client.tsx"></script>
<script type="text/javascript">
window.__SSR_STATIC_PROPS__ = "<!--ssr-static-props-->"
window.__GLOBAL_DATA__ = "<!--ssr-global-data-->"
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
"description": "Web base Boilerplate for cher-ami projects.",
"version": "0.5.0",
"author": "cher-ami",
"main": "src/index.tsx",
"main": "src/index-client.tsx",
"type": "module",
"scripts": {
"dev": "node server.js",
"dev": "node server/server.js",
"build:client": "vite build --outDir dist/front/client",
"build:server": "vite build --ssr src/index-server.tsx --outDir dist/front/server",
"build:scripts": "vite build -c vite.scripts.config.ts",
Expand Down
19 changes: 7 additions & 12 deletions prerender/prerender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { render } from "~/index-server"
import config from "../config/config.js"
import palette from "../config/helpers/palette.js"
import { isRouteIndex } from "./helpers/isRouteIndex"
import { prepareTemplate } from "../server/prepareTemplate.js"

export const prerender = async (urls: string[], outDirStatic = config.outDirStatic) => {
console.log("URLs to generate", urls)
Expand All @@ -30,18 +31,12 @@ export const prerender = async (urls: string[], outDirStatic = config.outDirStat
// Case url is index of root or of index of a group
if (isRouteIndex(preparedUrl, urls)) preparedUrl = `${preparedUrl}/index`

// include it in the template
const template = layout
? layout
.replaceAll(`<!--meta-title-->`, meta?.title ?? "")
.replaceAll(`<!--meta-description-->`, meta?.description ?? "")
.replaceAll(`<!--meta-imageUrl-->`, meta?.imageUrl ?? "")
.replaceAll(`<!--meta-url-->`, meta?.url ?? "")
.replaceAll(`<!--meta-siteName-->`, meta?.siteName ?? "")
.replace(`<!--app-html-->`, renderToString)
.replace(`"<!--ssr-static-props-->"`, JSON.stringify(ssrStaticProps))
.replace(`"<!--ssr-global-data-->"`, JSON.stringify(globalData))
: ""
const template = prepareTemplate(layout, {
app: renderToString,
ssrStaticProps,
globalData,
meta,
})

// prepare sub folder templates if exist
const routePath = path.resolve(`${outDirStatic}/${preparedUrl}`)
Expand Down
21 changes: 21 additions & 0 deletions server/prepareTemplate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Replace strings
* @param layout
* @param meta
* @param app
* @param ssrStaticProps
* @param globalData
* @return {string}
*/
export const prepareTemplate = (layout, { meta, app, ssrStaticProps, globalData }) => {
if (!layout) return ""
return layout
.replaceAll(`<!--meta-title-->`, meta?.title ?? "")
.replaceAll(`<!--meta-description-->`, meta?.description ?? "")
.replaceAll(`<!--meta-imageUrl-->`, meta?.imageUrl ?? "")
.replaceAll(`<!--meta-url-->`, meta?.url ?? "")
.replaceAll(`<!--meta-siteName-->`, meta?.siteName ?? "")
.replace(`<!--app-html-->`, app)
.replace(`"<!--ssr-static-props-->"`, JSON.stringify(ssrStaticProps))
.replace(`"<!--ssr-global-data-->"`, JSON.stringify(globalData))
}
61 changes: 30 additions & 31 deletions server.js → server/server.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import * as mfs from "./config/helpers/mfs.js"
import * as mfs from "../config/helpers/mfs.js"
import { resolve } from "path"
import express from "express"
import { createServer as createViteServer } from "vite"
import compression from "compression"
import portFinderSync from "portfinder-sync"
import config from "./config/config.js"
import config from "../config/config.js"
import { prepareTemplate } from "./prepareTemplate.js"
import debug from "@wbe/debug"
const log = debug("server:server")

/**
* Create development server
*
*
*
*/

async function createDevServer() {
const app = express()

Expand All @@ -33,36 +36,30 @@ async function createDevServer() {

try {
// 1. Read index.html
let template = await mfs.readFile(resolve("index.html"))
//console.log('template', template)
let layout = await mfs.readFile(resolve("index.html"))

// 2. Apply Vite HTML transforms. This injects the Vite HMR client, and
// also applies HTML transforms from Vite plugins, e.g. global preambles
// from @vitejs/plugin-react
template = await vite.transformIndexHtml(url, template)
layout = await vite.transformIndexHtml(url, layout)

// 3. Load the server entry. vite.ssrLoadModule automatically transforms
// your ESM source code to be usable in Node.js! There is no bundling
// required, and provides efficient invalidation similar to HMR.
const { render } = await vite.ssrLoadModule(`${config.srcDir}/index-server.tsx`)

// 4. render the app HTML. This assumes entry-server.js's exported `render`
// function calls appropriate framework SSR APIs,
// e.g. ReactDOMServer.renderToString()
// function calls appropriate framework SSR APIs
const { meta, renderToString, ssrStaticProps, globalData } = await render(url)

log({ url, renderToString, ssrStaticProps, globalData })

// 5. Inject the app-rendered HTML into the template.
let html = template
.replaceAll(`<!--meta-title-->`, meta?.title ?? "")
.replaceAll(`<!--meta-description-->`, meta?.description ?? "")
.replaceAll(`<!--meta-imageUrl-->`, meta?.imageUrl ?? "")
.replaceAll(`<!--meta-url-->`, meta?.url ?? "")
.replaceAll(`<!--meta-siteName-->`, meta?.siteName ?? "")
.replace(`<!--app-html-->`, renderToString)
.replace(`"<!--ssr-static-props-->"`, JSON.stringify(ssrStaticProps))
.replace(`"<!--ssr-global-data-->"`, JSON.stringify(globalData))
const html = prepareTemplate(layout, {
app: renderToString,
ssrStaticProps,
globalData,
meta,
})

// 6. Send the rendered HTML back.
res.status(200).set({ "Content-Type": "text/html" }).end(html)
Expand All @@ -79,6 +76,8 @@ async function createDevServer() {

/**
* Create production server
*
*
*/
async function createProdServer() {
console.log("prod server")
Expand All @@ -90,17 +89,19 @@ async function createProdServer() {
appType: "custom", // don't include Vite's default HTML handling middlewares
})

app.use(compression())
// @ts-ignore
app.use(serveStatic(config.outDirClient), { index: false })

app.use((await import("compression")).default())
app.use("*", async (req, res) => {
try {
const url = req.originalUrl
const template = await mfs.readFile(`${config.outDirClient}/index.html`)
const { render } = require(`${config.outDirServer}/index-server.js`)
const appHtml = render(url)
const html = template.replace(`<!--app-html-->`, appHtml)
const layout = await mfs.readFile(`${config.outDirClient}/index.html`)
const { render } = await import(`${config.outDirServer}/index-server.js`)
const { meta, renderToString, ssrStaticProps, globalData } = await render(url)
const html = prepareTemplate(layout, {
app: renderToString,
ssrStaticProps,
globalData,
meta,
})
res.status(200).set({ "Content-Type": "text/html" }).end(html)
} catch (e) {
console.log(e.stack)
Expand All @@ -117,8 +118,6 @@ async function createProdServer() {
const isProd = process.env.NODE_ENV === "production"
const port = process.env.DOCKER_NODE_PORT ?? portFinderSync.getPort(3000)

if (!isProd) {
createDevServer().then(({ app }) => app.listen(port))
} else {
createProdServer().then(({ app }) => app.listen(port))
}
isProd
? createProdServer().then(({ app }) => app.listen(port))
: createDevServer().then(({ app }) => app.listen(port))
File renamed without changes.
2 changes: 1 addition & 1 deletion vite.scripts.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default defineConfig(({ command, mode }) => {
},
rollupOptions: {
input: [
resolve("server.js"),
resolve("server/server.js"),
resolve("prerender/prerender.ts"),
resolve("prerender/exe-prerender-server.ts"),
resolve("prerender/exe-prerender.ts"),
Expand Down

0 comments on commit 72ae8d5

Please sign in to comment.