UNPKG

2.28 kBJavaScriptView Raw
1const path = require('path')
2const fs = require('fs-extra')
3const { createBundleRenderer } = require('vue-server-renderer')
4const { minify } = require('html-minifier')
5
6module.exports = async (
7 api,
8 { staticRoutes, serverBundle, clientManifest, htmlSkeletion, resourceHints }
9) => {
10 const routes = [...new Set(['/'].concat(staticRoutes || []))]
11 const renderer = createBundleRenderer(serverBundle, {
12 clientManifest,
13 runInNewContext: false,
14 inject: false,
15 basedir: api.resolveCwd()
16 })
17
18 const generatePage = async route => {
19 const context = { url: route }
20 const app = await renderer.renderToString(context)
21 const {
22 title,
23 htmlAttrs,
24 headAttrs,
25 bodyAttrs,
26 link,
27 style,
28 script,
29 noscript,
30 meta
31 } = context.meta.inject()
32
33 const html = htmlSkeletion
34 .replace(
35 /<title>.*<\/title>/,
36 () => `
37 ${meta.text()}
38 ${title.text()}
39 ${link.text()}
40 ${context.renderStyles()}
41 ${style.text()}
42 ${script.text()}
43 ${noscript.text()}
44 ${resourceHints ? context.renderResourceHints() : ''}
45 `
46 )
47 .replace(
48 /<html(\s+)?(.*)>/,
49 `<html data-poi-ssr ${htmlAttrs.text()}$1$2>`
50 )
51 .replace(/<head(\s+)?(.*)>/, `<head ${headAttrs.text()}$1$2>`)
52 .replace(/<body(\s+)?(.*)>/, `<body ${bodyAttrs.text()}$1$2>`)
53 .replace(
54 '</body>',
55 `${context.renderState()}${context.renderScripts()}</body>`
56 )
57 .replace(`<div id="app"></div>`, app)
58 const outPath = getFilePath(api.resolveOutDir(), route)
59 console.log(`> Rendering ${route}`)
60 await fs.outputFile(
61 outPath,
62 minify(html, {
63 removeComments: true,
64 collapseWhitespace: true,
65 removeRedundantAttributes: true,
66 useShortDoctype: true,
67 removeEmptyAttributes: true,
68 removeStyleLinkTypeAttributes: true,
69 keepClosingSlash: true,
70 minifyJS: true,
71 minifyCSS: true,
72 minifyURLs: true
73 }),
74 'utf8'
75 )
76 }
77
78 await Promise.all(routes.map(route => generatePage(route)))
79}
80
81function getFilePath(outDir, route) {
82 if (!route.endsWith('.html')) {
83 route = route.replace(/(\/)?$/, '/index.html')
84 }
85
86 return path.join(outDir, route)
87}