# vuepress-plugin-dehydrate
Dehydrate generated HTML files of your VuePress site.
# Installation
npm install -D vuepress-plugin-dehydrate
# Usage
// .vuepress/config.js
module.exports = {
plugins: [
'vuepress-plugin-dehydrate',
{
// disable SSR
noSSR: '404.html',
// remove scripts
noScript: [
// support glob patterns
'foo/*.html',
'**/static.html',
],
},
],
}
# Configs
# noSSR
- type:
string | string[]
- default:
'404.html'
A list of files to disable SSR, with glob patterns supported.
# noScript
- type:
string | string[]
- default:
[]
A list of files to remove scripts, with glob patterns supported.
# globOptions
- type:
object
- default:
{}
Options for fast-glob.
# noEmptyLine
- type:
boolean
- default:
true
Whether to delete extra blank lines in HTML.
# Why we need this plugin
# SSR Mismatch
VuePress will try to redirect unknown request /foo
to /foo.html
and /foo/
. Other scenarios include redirecting /
to /zh/
or /en/
based on navigator language.
Although Vuepress functions properly under most circumstances, if the page redirects before rendering, the pre-rendered parts will be structured differently from the target page of redirection, leading to a problem called SSR mismatch.
# An example to explain the mismatch
You request /foo
in the browser, but the server can't find a direct match (without certain config), so a NotFound
page /404.html
will be returned. The beforeEach
hook registered in handleRedirectForCleanUrls
will redirect the router to /foo.html
. Note that the DOM remains unchanged but the VDOM is replaced with /foo.html
's. Normally, /404.html
is a plain page without navbar and sidebar, but the new VDOM is a document page with such components. The DOM fails to match the VDOM, causing rendering error and the view will not be updated. This is an SSR Mismatch and its consequence.
Reference:
# Using "Pure" HTML
Sometimes we want to output a HTML page without all the fancy preload, prefetch and hydration script/styles. We can just use Vue / markdown files as a way to organize the static website structure. We can do CSS by setting a <link>
that points to the CSS in the <head>
. We don't need JS at runtime.
Reference:
# Solution
It may be amazing, but the solutions to these two problems are similar. VuePress uses ssrTemplate
as a template for SSR rendering. All we have to do is delete part of them. For the first problem, since all redirections where SSR mismatches occur take place on the 404 page, we only need to disable the SSR for that page. Since 404 pages are usually simple and not so necessary to be SEO friendly, this solution is reasonable. On the contrary, in the second case, we merely need to remove the the scripts for "hydration" rather than delete SSR pre-rendered HTML. This plugin provides both of these capabilities, allowing us to control every page effectively.
# Demo
A normally generated HTML file will be like this:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>VuePress</title>
<meta name="description" content="" />
<link rel="preload" href="/assets/css/0.styles.53e4595a.css" as="style" />
<link rel="preload" href="/assets/js/app.3fe70f2e.js" as="script" />
<link rel="preload" href="/assets/js/3.db027a4f.js" as="script" />
<link rel="preload" href="/assets/js/5.222ba868.js" as="script" />
<link rel="prefetch" href="/assets/js/2.418462f5.js" />
<link rel="prefetch" href="/assets/js/4.f6ba1d08.js" />
<link rel="prefetch" href="/assets/js/6.d7ad24ac.js" />
<link rel="stylesheet" href="/assets/css/0.styles.53e4595a.css" />
</head>
<body>
<div id="app" data-server-rendered="true">
<div class="content default"><p>readme</p></div>
<div class="global-ui"></div>
</div>
<script src="/assets/js/app.3fe70f2e.js" defer></script>
<script src="/assets/js/3.db027a4f.js" defer></script>
<script src="/assets/js/5.222ba868.js" defer></script>
</body>
</html>
When we use the noSSR
mode, VuePress will generate such HTML:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>VuePress</title>
<meta name="description" content="" />
<link rel="preload" href="/assets/css/0.styles.53e4595a.css" as="style" />
<link rel="preload" href="/assets/js/app.3fe70f2e.js" as="script" />
<link rel="preload" href="/assets/js/3.db027a4f.js" as="script" />
<link rel="preload" href="/assets/js/5.222ba868.js" as="script" />
<link rel="prefetch" href="/assets/js/2.418462f5.js" />
<link rel="prefetch" href="/assets/js/4.f6ba1d08.js" />
<link rel="prefetch" href="/assets/js/6.d7ad24ac.js" />
<link rel="stylesheet" href="/assets/css/0.styles.53e4595a.css" />
</head>
<body>
<div id="app"><!-- see here --></div>
<script src="/assets/js/app.3fe70f2e.js" defer></script>
<script src="/assets/js/3.db027a4f.js" defer></script>
<script src="/assets/js/5.222ba868.js" defer></script>
</body>
</html>
When we use the noScript
mode, VuePress will generate such HTML:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>VuePress</title>
<meta name="description" content="" />
<!-- see here -->
<link rel="stylesheet" href="/assets/css/0.styles.53e4595a.css" />
</head>
<body>
<div id="app">
<div class="content default"><p>readme</p></div>
<div class="global-ui"></div>
</div>
<!-- see here -->
</body>
</html>