mirror of
https://github.com/aelve/guide.git
synced 2024-11-27 00:14:03 +03:00
469b5b5790
* DefferedPromise refactor * Moved defferedPromise to utils folder * Base url moved to app file * Store modules states rewrittten according to vue doc recommendations * Deffered promise usage moved * removed unused packages in entries * Structure refactor, easier building, prod building configured, tsconfig reconfigure removed useless packages * Update front/index.html Co-Authored-By: avele <34437766+avele@users.noreply.github.com> * Update front/postcss.config.js Co-Authored-By: avele <34437766+avele@users.noreply.github.com> * Comment rewritten
128 lines
3.4 KiB
TypeScript
128 lines
3.4 KiB
TypeScript
import fs from 'fs'
|
|
import path from 'path'
|
|
import MemoryFs from 'memory-fs'
|
|
import webpack from 'webpack'
|
|
import { createBundleRenderer } from 'vue-server-renderer'
|
|
import koaWebpack from 'koa-webpack'
|
|
import DeferredPromise from '../utils/DeferredPromise'
|
|
|
|
const fsAsync = fs.promises
|
|
|
|
MemoryFs.prototype.readFileAsync = async function (...args: any) {
|
|
return new Promise((resolve, reject) => {
|
|
this.readFile(...args, (err: any, result: string | Buffer) => {
|
|
if (err) {
|
|
reject(err)
|
|
return
|
|
}
|
|
resolve(result)
|
|
})
|
|
})
|
|
}
|
|
|
|
import serverConfig from '../build/webpack.server.conf'
|
|
import clientConfig from '../build/webpack.client.conf'
|
|
const serverCompiler = webpack(serverConfig)
|
|
const clientCompiler = webpack(clientConfig)
|
|
|
|
const mfs = new MemoryFs()
|
|
|
|
const clientManifestFileName = 'vue-ssr-client-manifest.json'
|
|
const serverBundleFileName = 'vue-ssr-server-bundle.json'
|
|
|
|
// TODO add icon and refactor, change favicon serving
|
|
const urlsToSkip = [
|
|
'/favicon.ico'
|
|
]
|
|
|
|
let bundle: object = null
|
|
let clientManifest: object = null
|
|
let renderer = null
|
|
let template: string = null
|
|
|
|
export default async function setupDevServer (app): Promise<void> {
|
|
const promise = new DeferredPromise()
|
|
|
|
serverCompiler.outputFileSystem = mfs
|
|
serverCompiler.watch({}, async (err: any, stats: any) => {
|
|
logWebpack(err, stats)
|
|
const bundlePath = path.join(serverConfig.output.path, serverBundleFileName)
|
|
bundle = JSON.parse(await mfs.readFileAsync(bundlePath, 'utf-8'))
|
|
updateRenderer(promise.resolve)
|
|
})
|
|
|
|
await Promise.all([setupClientDevMiddlware(app, promise.resolve), setupTemplate()])
|
|
app.use(handler)
|
|
|
|
// @ts-ignore
|
|
return promise
|
|
}
|
|
|
|
async function setupClientDevMiddlware (app, resolveSetup) {
|
|
const clientDevMiddleware = await koaWebpack({
|
|
compiler: clientCompiler
|
|
})
|
|
clientCompiler.hooks.done.tap('updateRender', async (stats: any) => {
|
|
logWebpack(undefined, stats)
|
|
const manifestPath = path.join(clientConfig.output.path, clientManifestFileName)
|
|
const fileSystem = clientDevMiddleware.devMiddleware.fileSystem
|
|
clientManifest = JSON.parse(await fileSystem.readFileAsync(manifestPath, 'utf-8'))
|
|
updateRenderer(resolveSetup)
|
|
})
|
|
app.use(clientDevMiddleware)
|
|
}
|
|
|
|
async function setupTemplate () {
|
|
const templatePath = path.resolve(__dirname, '../index.html')
|
|
template = await fsAsync.readFile(templatePath, 'utf-8') as string
|
|
}
|
|
|
|
function logWebpack (err: Error, stats) {
|
|
if (err) {
|
|
throw err
|
|
}
|
|
stats = stats.toJson()
|
|
stats.errors.forEach((err: any) => console.log(err))
|
|
stats.warnings.forEach((warn: any) => console.log(warn))
|
|
}
|
|
|
|
async function updateRenderer (resolveSetup: () => void) {
|
|
if (!bundle || !clientManifest || !template) {
|
|
return
|
|
}
|
|
|
|
renderer = createBundleRenderer(bundle, {
|
|
clientManifest,
|
|
template,
|
|
runInNewContext: false
|
|
})
|
|
|
|
if (resolveSetup) {
|
|
resolveSetup()
|
|
}
|
|
}
|
|
|
|
async function handler (ctx) {
|
|
const { url } = ctx
|
|
|
|
// TODO add favicon skip favicon.
|
|
if (urlsToSkip.includes(url)) {
|
|
ctx.body = ''
|
|
return
|
|
}
|
|
|
|
if (!bundle || !clientManifest || !renderer) {
|
|
ctx.body = 'Please wait...'
|
|
return
|
|
}
|
|
|
|
try {
|
|
ctx.response.header['Content-Type'] = 'text/html'
|
|
ctx.body = await renderer.renderToString({ url })
|
|
} catch (error) {
|
|
console.error('[Error] SSR render error:', error)
|
|
ctx.body = 500
|
|
ctx.body = error.message || 'Unknown Internal Server Error'
|
|
}
|
|
}
|