mirror of
https://github.com/Aviortheking/nextjs-clone.git
synced 2025-04-22 02:42:10 +00:00
feat: updated
Signed-off-by: Avior <f.bouillon@aptatio.com>
This commit is contained in:
parent
c467bccbe6
commit
e19db6ee5c
@ -1,5 +0,0 @@
|
||||
import ReactDOM from 'react-dom/client'
|
||||
|
||||
document.addEventListener('load', async () => {
|
||||
ReactDOM.hydrateRoot(document.body, )
|
||||
})
|
@ -8,6 +8,6 @@
|
||||
</head>
|
||||
<body>
|
||||
<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>
|
||||
</html>
|
69
main.ts
69
main.ts
@ -1,17 +1,29 @@
|
||||
import express, { Request } from 'express'
|
||||
import { createServer } from 'vite'
|
||||
import { createServer, ViteDevServer } from 'vite'
|
||||
import fs from 'fs/promises'
|
||||
|
||||
// const isProd = process.env.NODE_ENV === 'production'
|
||||
const isProd = true
|
||||
const isProd = process.env.NODE_ENV === 'production'
|
||||
// const isProd = false //true
|
||||
|
||||
// if (isProd) {
|
||||
// process.env.NODE_ENV = 'production'
|
||||
// } else {
|
||||
// process.env.NODE_ENV = 'development'
|
||||
|
||||
// }
|
||||
|
||||
let vite: ViteDevServer | null = null
|
||||
|
||||
;(async () => {
|
||||
const server = express()
|
||||
|
||||
const vite = await createServer({
|
||||
server: {middlewareMode: true},
|
||||
appType: 'custom'
|
||||
})
|
||||
|
||||
if (!isProd) {
|
||||
vite = await createServer({
|
||||
server: {middlewareMode: true},
|
||||
appType: 'custom'
|
||||
})
|
||||
server.use(vite.middlewares)
|
||||
}
|
||||
|
||||
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')
|
||||
}
|
||||
|
||||
server.use(vite.middlewares)
|
||||
|
||||
if (isProd) {
|
||||
server.use('/assets', express.static('./dist/client/assets'))
|
||||
}
|
||||
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) => {
|
||||
|
||||
const url = req.originalUrl
|
||||
|
||||
const template = await vite.transformIndexHtml(url, index)
|
||||
|
||||
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 {
|
||||
const route = await vite.ssrLoadModule('/src/entry-server.tsx')
|
||||
render = route.render
|
||||
}
|
||||
|
||||
if (!render) {
|
||||
return res.status(500).end('Error')
|
||||
let template: string = index
|
||||
if (vite) {
|
||||
template = await vite.transformIndexHtml(url, index)
|
||||
}
|
||||
|
||||
if (!render) {
|
||||
throw new Error('Renderer not found :O')
|
||||
}
|
||||
|
||||
const appHtml = await render(req)
|
||||
|
||||
|
5218
package-lock.json
generated
5218
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -3,14 +3,16 @@
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"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: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": {
|
||||
"@dzeio/config": "^1.1.8",
|
||||
"@tcgdex/sdk": "^2.4.7",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
@ -2,7 +2,7 @@ import fs from 'fs/promises'
|
||||
|
||||
export async function exists(path: string): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(path + `.tsx`)
|
||||
await fs.access(path)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
|
11
src/entry-client.tsx
Normal file
11
src/entry-client.tsx
Normal 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} />)
|
||||
})()
|
@ -7,15 +7,17 @@ import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const ext = process.env.NODE_ENV === 'production' ? '.js' : '.tsx'
|
||||
|
||||
export const render = async (req: Request) => {
|
||||
const path = `${__dirname}/pages${req.path}`
|
||||
console.log(req.path, __dirname)
|
||||
const path = `${__dirname}/pages${req.path}${ext}`
|
||||
const is404 = !(await exists(path))
|
||||
console.log(req.path, path, is404)
|
||||
if (is404) {
|
||||
return '404'
|
||||
}
|
||||
const route = await import(`${__dirname}/pages${req.path}.tsx`)
|
||||
/* @vite-ignore */
|
||||
const route = await import(path)
|
||||
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
4
src/interfaces.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
export interface CommProps {
|
||||
pageProps: any
|
||||
path: string
|
||||
}
|
@ -1,22 +1,24 @@
|
||||
import React from 'react'
|
||||
import type { CommProps } from '../interfaces'
|
||||
|
||||
interface AppProps {
|
||||
children: React.ReactNode
|
||||
component: any
|
||||
path: string
|
||||
pageProps: any
|
||||
}
|
||||
|
||||
export default class App extends React.Component<AppProps> {
|
||||
public render = () => (
|
||||
<>
|
||||
<html>
|
||||
<head>
|
||||
<script
|
||||
type='application/json'
|
||||
id="__PROPS"
|
||||
dangerouslySetInnerHTML={{__html: JSON.stringify(this.props)}}
|
||||
></script>
|
||||
</head>
|
||||
<body>{this.props.children}</body>
|
||||
</html>
|
||||
<script
|
||||
type='application/json'
|
||||
id="__PROPS"
|
||||
dangerouslySetInnerHTML={{__html: JSON.stringify({
|
||||
pageProps: this.props.pageProps,
|
||||
path: this.props.path
|
||||
} as CommProps)}}
|
||||
></script>
|
||||
<this.props.component {...this.props.pageProps} />
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,16 +1,20 @@
|
||||
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}> {
|
||||
|
||||
public componentDidMount(): void {
|
||||
console.log('YaY')
|
||||
}
|
||||
|
||||
public render = () => (
|
||||
<div>{this.props.card.name}</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export const getServerProps = async () => {
|
||||
const tcgdex = new TCGdex()
|
||||
const tcgdex = new TCGdex.default()
|
||||
return {
|
||||
card: await tcgdex.fetchCard('bw1-1')
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
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}> {
|
||||
|
||||
|
@ -5,7 +5,32 @@
|
||||
"outDir": "dist",
|
||||
"target": "ES2022",
|
||||
"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": [
|
||||
"main.ts"
|
||||
|
11
tsconfig.pages.json
Normal file
11
tsconfig.pages.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"files": [],
|
||||
"include": [
|
||||
"src/pages"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"outDir": "dist/server/pages",
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "./node_modules/@dzeio/config/tsconfig.esm.json"
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user