构建静态站
Analog 在构建部署时支持静态站点生成。这包括将提供的路由预渲染到静态 HTML 以及客户端应用。
静态站点生成
从路由列表
要预渲染页面,请使用 prerender
属性来配置在构建时的要渲染的路由。预渲染的路由也可以通过异步的方式提供。
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
plugins: [
analog({
prerender: {
routes: async () => [
'/',
'/about',
'/blog',
'/blog/posts/2023-02-01-my-first-post',
],
},
}),
],
}));
从内容目录
也许你想将所有的内容目录的路由都进行预渲染。
例如你有一个博客并且所有的文章都是位于 contents
目录的 Markdown 文件。
在这种情况下,你可以在 routes
配置里添加一个对象来渲染一个目录下的所有内容。
请注意,目录结构可能不会完全跟应用的路径完全匹配。
因此,您必须传递一个将文件路径映射到 URL 的 transform
函数。
返回的字符串应该是应用中的 URL 路径
transform
函数还可以通过返回 false
的方式过滤掉一些不想预渲染的路由。
例如在前言部分被标记为 draft
的文件将不会被进行预渲染处理
配置对象的 contentDir
值可以是一个 glob 范式,也可以只是一个目录。
import { defineConfig } from 'vite';
import analog, { type PrerenderContentFile } from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
plugins: [
analog({
prerender: {
routes: async () => [
'/',
'/blog',
{
contentDir: 'src/content/blog',
transform: (file: PrerenderContentFile) => {
// do not include files marked as draft in frontmatter
if (file.attributes.draft) {
return false;
}
// use the slug from frontmatter if defined, otherwise use the files basename
const slug = file.attributes.slug || file.name;
return `/blog/${slug}`;
},
},
],
},
}),
],
}));
仅渲染静态页
要只渲染静态页,使用 static: true
标记。
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
plugins: [
analog({
static: true,
prerender: {
routes: async () => [
'/',
'/about',
'/blog',
'/blog/posts/2023-02-01-my-first-post',
],
},
}),
],
}));
静态页可以从 dist/analog/public
目录来部署。
网站地图生成
Analog 同样支持自动的网站地图生成。如果指定了网站地图配置,生成的网站地图位于 dist/analog/public
目录。
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
plugins: [
analog({
prerender: {
routes: async () => ['/', '/blog'],
sitemap: {
host: 'https://analogjs.org/',
},
},
}),
],
}));
只要提供了路由,Analog 会生成包含页面的 <loc>
和 <lastmod>
属性的 sitemap.xml
文件。
<?xml version="1.0" encoding="UTF-8"?>
<urlset...>
<!--This file was automatically generated by Analog.-->
<url>
<loc>https://analogjs.org/</loc>
<lastmod>2023-07-01</lastmod>
</url>
<url>
<loc>https://analogjs.org/blog</loc>
<lastmod>2023-07-01</lastmod>
</url>
</urlset...>
Post-rendering 钩子
Ananlog 支持预渲染处理过程中的 post-rendering 钩子。通过 post-rendering 钩子可以用来在 HTML 文件里执行内联关键 CSS,添加/删除脚本等操作。
下面的例子展示了如何在代码中使用 postRenderingHooks
:
import analog from '@analogjs/platform';
import { defineConfig } from 'vite';
import { PrerenderRoute } from 'nitropack';
// https://vitejs.dev/config/
export default defineConfig(() => {
return {
publicDir: 'src/public',
build: {
target: ['es2020'],
},
plugins: [
analog({
static: true,
prerender: {
routes: async () => [],
postRenderingHooks: [
async (route: PrerenderRoute) => console.log(route),
],
},
}),
],
};
});
PrerenderRoute
提供了关于 route
,contents
,data
以及fileName
的信息,这些信息对于在预渲染阶段更改内容很有用。
下面是一个小例子,我们可以使用 postRenderingHooks
在预渲染过程中附加一个脚本来包含 Google Analytics:
/// <reference types="vitest" />
import analog from '@analogjs/platform';
import { defineConfig, splitVendorChunkPlugin } from 'vite';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { PrerenderRoute } from 'nitropack';
// https://vitejs.dev/config/
export default defineConfig(() => {
return {
publicDir: 'src/public',
build: {
target: ['es2020'],
},
plugins: [
analog({
static: true,
prerender: {
routes: async () => ['/', '/aboutus'],
postRenderingHooks: [
async (route: PrerenderRoute) => {
const gTag = `<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-xxxxxx-1', 'auto');
ga('send', 'pageview');
</script>`;
if (route.route === '/aboutus') {
route.contents = route.contents?.concat(gTag);
}
},
],
},
}),
],
};
});