feat: updated

Signed-off-by: Avior <f.bouillon@aptatio.com>
This commit is contained in:
Florian Bouillon 2022-11-24 12:07:30 +01:00
parent c467bccbe6
commit e19db6ee5c
Signed by: Florian Bouillon
GPG Key ID: E05B3A94178D3A7C
18 changed files with 2748 additions and 2659 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
#NODE_ENV=production

1
.env.prod Normal file
View File

@ -0,0 +1 @@
NODE_ENV=production

View File

@ -1,5 +0,0 @@
import ReactDOM from 'react-dom/client'
document.addEventListener('load', async () => {
ReactDOM.hydrateRoot(document.body, )
})

View File

@ -8,6 +8,6 @@
</head> </head>
<body> <body>
<div id="app"><!--ssr-outlet--></div> <div id="app"><!--ssr-outlet--></div>
<script type="module" src="/src/entry-client.ts"></script> <script type="module" src="/src/entry-client.tsx"></script>
</body> </body>
</html> </html>

69
main.ts
View File

@ -1,17 +1,29 @@
import express, { Request } from 'express' import express, { Request } from 'express'
import { createServer } from 'vite' import { createServer, ViteDevServer } from 'vite'
import fs from 'fs/promises' import fs from 'fs/promises'
// const isProd = process.env.NODE_ENV === 'production' const isProd = process.env.NODE_ENV === 'production'
const isProd = true // const isProd = false //true
// if (isProd) {
// process.env.NODE_ENV = 'production'
// } else {
// process.env.NODE_ENV = 'development'
// }
let vite: ViteDevServer | null = null
;(async () => { ;(async () => {
const server = express() const server = express()
const vite = await createServer({ if (!isProd) {
server: {middlewareMode: true}, vite = await createServer({
appType: 'custom' server: {middlewareMode: true},
}) appType: 'custom'
})
server.use(vite.middlewares)
}
let index = await fs.readFile('./dist/client/index.html', 'utf-8') let index = await fs.readFile('./dist/client/index.html', 'utf-8')
@ -20,33 +32,40 @@ const isProd = true
index = await fs.readFile('./index.html', 'utf-8') index = await fs.readFile('./index.html', 'utf-8')
} }
server.use(vite.middlewares)
if (isProd) {
server.use('/assets', express.static('./dist/client/assets'))
}
server.use('/', express.static('public')) server.use('/', express.static('public'))
let render: ((url: Request) => Promise<string>) | null = null
if (isProd) {
/** @ts-expect-error why not m*therfucker */
const route: any = await import('./server/entry-server.js')
render = route.render as any
} else if (vite) {
const route = await vite.ssrLoadModule('/src/entry-server.tsx')
render = route.render
}
if (!render) {
throw new Error('Renderer not found :O')
process.exit(1)
}
server.use(async (req, res) => { server.use(async (req, res) => {
const url = req.originalUrl const url = req.originalUrl
const template = await vite.transformIndexHtml(url, index) let template: string = index
if (vite) {
let render: ((url: Request) => Promise<string>) | null = null template = await vite.transformIndexHtml(url, index)
if (isProd) {
/** @ts-expect-error why not m*therfucker */
const route: any = await import('./server/entry-server.js')
render = route.render as any
} else {
const route = await vite.ssrLoadModule('/src/entry-server.tsx')
render = route.render
}
if (!render) {
return res.status(500).end('Error')
} }
if (!render) {
throw new Error('Renderer not found :O')
}
const appHtml = await render(req) const appHtml = await render(req)

5218
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,16 @@
"version": "1.0.0", "version": "1.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "ts-node -T --project tsconfig.json main.tsx", "dev": "NODE_ENV=\"development\" ts-node-esm -T --project tsconfig.json main.ts",
"build": "npm run build:client && npm run build:server", "build": "npm run build:client && npm run build:server",
"build:client": "vite build --outDir dist/client --ssrManifest", "build:client": "vite build --outDir dist/client --ssrManifest",
"build:server": "vite build --outDir dist/server --ssr src/entry-server.tsx && tsc --project tsconfig.json" "build:server": "vite build --outDir dist/server --ssr src/entry-server.tsx && tsc --project tsconfig.pages.json && tsc --project tsconfig.json",
"start": "NODE_ENV=\"production\" node dist/main.js"
}, },
"dependencies": { "dependencies": {
"@dzeio/config": "^1.1.8", "@dzeio/config": "^1.1.8",
"@tcgdex/sdk": "^2.4.7", "@tcgdex/sdk": "^2.4.7",
"dotenv": "^16.0.3",
"express": "^4.18.2", "express": "^4.18.2",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

View File

@ -2,7 +2,7 @@ import fs from 'fs/promises'
export async function exists(path: string): Promise<boolean> { export async function exists(path: string): Promise<boolean> {
try { try {
await fs.access(path + `.tsx`) await fs.access(path)
return true return true
} catch { } catch {
return false return false

View File

11
src/entry-client.tsx Normal file
View File

@ -0,0 +1,11 @@
import React from 'react'
import App from './pages/_app'
import Path from './pages/path'
import { hydrateRoot } from 'react-dom/client'
import type { CommProps } from './interfaces'
(async () => {
const __PROPS: CommProps = JSON.parse((window as any).__PROPS.innerText)
console.log(__PROPS)
hydrateRoot(document.getElementById('app') as HTMLDivElement, <App component={Path} path={__PROPS.path} pageProps={__PROPS.pageProps} />)
})()

View File

@ -7,15 +7,17 @@ import path from 'path'
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url)) const __dirname = path.dirname(fileURLToPath(import.meta.url))
const ext = process.env.NODE_ENV === 'production' ? '.js' : '.tsx'
export const render = async (req: Request) => { export const render = async (req: Request) => {
const path = `${__dirname}/pages${req.path}` const path = `${__dirname}/pages${req.path}${ext}`
console.log(req.path, __dirname)
const is404 = !(await exists(path)) const is404 = !(await exists(path))
console.log(req.path, path, is404)
if (is404) { if (is404) {
return '404' return '404'
} }
const route = await import(`${__dirname}/pages${req.path}.tsx`) /* @vite-ignore */
const route = await import(path)
const props = await route.getServerProps() const props = await route.getServerProps()
return (`<!DOCTYPE html>` + renderToString(<App><route.default {...props} /></App>)) return renderToString(<App component={route.default} path={req.path} pageProps={props} />)
} }

4
src/interfaces.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
export interface CommProps {
pageProps: any
path: string
}

View File

@ -1,22 +1,24 @@
import React from 'react' import React from 'react'
import type { CommProps } from '../interfaces'
interface AppProps { interface AppProps {
children: React.ReactNode component: any
path: string
pageProps: any
} }
export default class App extends React.Component<AppProps> { export default class App extends React.Component<AppProps> {
public render = () => ( public render = () => (
<> <>
<html> <script
<head> type='application/json'
<script id="__PROPS"
type='application/json' dangerouslySetInnerHTML={{__html: JSON.stringify({
id="__PROPS" pageProps: this.props.pageProps,
dangerouslySetInnerHTML={{__html: JSON.stringify(this.props)}} path: this.props.path
></script> } as CommProps)}}
</head> ></script>
<body>{this.props.children}</body> <this.props.component {...this.props.pageProps} />
</html>
</> </>
) )
} }

View File

@ -1,16 +1,20 @@
import React from 'react' import React from 'react'
import TCGdex, { Card } from '@tcgdex/sdk' import TCGdex from '@tcgdex/sdk'
import type { Card } from '@tcgdex/sdk'
export default class Component extends React.Component<{card: Card}> { export default class Component extends React.Component<{card: Card}> {
public componentDidMount(): void {
console.log('YaY')
}
public render = () => ( public render = () => (
<div>{this.props.card.name}</div> <div>{this.props.card.name}</div>
) )
} }
export const getServerProps = async () => { export const getServerProps = async () => {
const tcgdex = new TCGdex() const tcgdex = new TCGdex.default()
return { return {
card: await tcgdex.fetchCard('bw1-1') card: await tcgdex.fetchCard('bw1-1')
} }

View File

@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import TCGdex, { Card, Set } from '@tcgdex/sdk' import type { Set } from '@tcgdex/sdk'
import TCGdex from '@tcgdex/sdk'
export default class Component extends React.Component<{card: Set}> { export default class Component extends React.Component<{card: Set}> {

View File

@ -5,7 +5,32 @@
"outDir": "dist", "outDir": "dist",
"target": "ES2022", "target": "ES2022",
"module": "NodeNext", "module": "NodeNext",
"skipLibCheck": true "skipLibCheck": true,
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"allowJs": true,
"pretty": true,
"allowSyntheticDefaultImports": true,
// Type Checking
"forceConsistentCasingInFileNames": true,
"alwaysStrict": true,
"strict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitAny": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}, },
"files": [ "files": [
"main.ts" "main.ts"

11
tsconfig.pages.json Normal file
View File

@ -0,0 +1,11 @@
{
"extends": "./tsconfig.json",
"files": [],
"include": [
"src/pages"
],
"compilerOptions": {
"baseUrl": "src",
"outDir": "dist/server/pages",
}
}

View File

@ -1,3 +0,0 @@
{
"extends": "./node_modules/@dzeio/config/tsconfig.esm.json"
}