百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
P

point-of-view

> 编程语言
开源

快速化模板渲染插件

378 stars0 点赞2 次浏览
访问官网GitHub

工具介绍

快速化模板渲染插件

@fastify/view

Templates rendering plugin support for Fastify.

@fastify/view decorates the reply interface with the view and viewAsync methods for managing view engines, which can be used to render templated responses.

Currently supports the following templates engines:

  • ejs
  • nunjucks
  • pug
  • handlebars
  • mustache
  • twig
  • liquid
  • doT
  • eta
  • edge
  • squirrelly

In production mode, @fastify/view will heavily cache the templates file and functions, while in development will reload every time the template file and function.

Note: For Fastify v3 support, please use point-of-view 5.x (npm i point-of-view@5).

Note that at least Fastify v2.0.0 is needed.

Recent Changes

Note: reply.viewAsync added as a replacement for reply.view and fastify.view. See Migrating from view to viewAsync.

Note: ejs-mate support has been dropped.

Note: marko support has been dropped. Please use @marko/fastify instead.

Benchmarks

The benchmarks were run with the files in the benchmark folder with the ejs engine. The data has been taken with: autocannon -c 100 -d 5 -p 10 localhost:3000

  • Express: 8.8k req/sec
  • Fastify: 15.6k req/sec

Install

npm i @fastify/view

Quick start

fastify.register is used to register @fastify/view. By default, It will decorate the reply object with a view method that takes at least two arguments:

  • the template to be rendered
  • the data that should be available to the template during rendering

This example will render the template using the EJS engine and provide a variable name to be used inside the template:


  
  
    
Hello, !

  
// index.js:
const fastify = require("fastify")()
const fastifyView = require("@fastify/view")

fastify.register(fastifyView, {
  engine: {
    ejs: require("ejs")
  }
})

// synchronous handler:
fastify.get("/", (req, reply) => {
  reply.view("index.ejs", { name: "User" });
})

// asynchronous handler:
fastify.get("/", async (req, reply) => {
  return reply.viewAsync("index.ejs", { name: "User" });
})

fastify.listen({ port: 3000 }, (err) => {
  if (err) throw err;
  console.log(`server listening on ${fastify.server.address().port}`);
})

Configuration

Options

Option Description Default
engine Required. The template engine object - pass in the return value of require('')
production Enables caching of template files and render functions NODE_ENV === "production"
maxCache In production mode, maximum number of cached template files and render functions 100
defaultContext Template variables available to all views. Variables provided on render have precedence and will override this if they have the same name.

Example: { siteName: "MyAwesomeSite" } | {} | | propertyName | The property that should be used to decorate reply and fastify

E.g. reply.view() and fastify.view() where "view" is the property name | "view" | | asyncPropertyName | The property that should be used to decorate reply for async handler

Defaults to ${propertyName}Async if propertyName is defined | "viewAsync" | | root | The root path of your templates folder. The template name or path passed to the render function will be resolved relative to this path | "./" | | charset | Default charset used when setting Content-Type header | "utf-8" | | includeViewExtension | Automatically append the default extension for the used template engine if omitted from the template name. So instead of template.hbs, just template can be used | false | | viewExt | Override the default extension for a given template engine. This has precedence over includeViewExtension and will lead to the same behavior, just with a custom extension.

Example: "handlebars" | "" | | layout | See Layouts

This option lets you specify a global layout file to be used when rendering your templates. Settings like root or viewExt apply as for any other template file.

Example: ./templates/layouts/main.hbs | | | options | See Engine-specific settings | {} |

Example

…

Layouts

@fastify/view supports layouts for EJS, Handlebars, Eta and doT. When a layout is specified, the request template is first rendered, then the layout template is rendered with the request-rendered html set on body.

Example


  
  
    
    
    

  
// index.js:
fastify.register(fastifyView, {
  engine: { ejs },
  layout: "layout.ejs"
})

fastify.get('/', (req, reply) => {
  const data = { text: "Hello!"}
  reply.view('template.ejs', data)
})

Providing a layout on render

Please note: Global layouts and providing layouts on render are mutually exclusive. They can not be mixed.

fastify.get('/', (req, reply) => {
  const data = { text: "Hello!"}
  reply.view('template.ejs', data, { layout: 'layout.ejs' })
})

Setting request-global variables

Sometimes, several templates should have access to the same request-specific variables. E.g. when setting the current username.

If you want to provide data, which will be depended on by a request and available in all views, you have to add property locals to reply object, like in the example below:

fastify.addHook("preHandler", function (request, reply, done) {
  reply.locals = {
    text: getTextFromRequest(request), // it will be available in all views
  };

  done();
});

Properties from reply.locals will override those from defaultContext, but not from data parameter provided to reply.view(template, data) function.

Rendering the template into a variable

The fastify object is decorated the same way as reply and allows you to just render a view into a variable (without request-global variables) instead of sending the result back to the browser:

// Promise based, using async/await
const html = await fastify.view("/templates/index.ejs", { text: "text" });

// Callback based
fastify.view("/templates/index.ejs", { text: "text" }, (err, html) => {
  // Handle error
  // Do something with `html`
});

If called within a request hook and you need request-global variables, see Migrating from view to viewAsync.

Registering multiple engines

Registering multiple engines with different configurations is supported. They are distinguished via their propertyName:

…

Rendering a template from a string ("raw" template)

The reply.view({ raw }) option allows you to render a template from a string instead of a file. This is useful when you want to render a template that is not stored in a file, or when you want to use a template that is generated dynamically.

fastify.get('/', (req, reply) => {
  fs.readFile('./templates/index.mustache', 'utf8', (err, file) => {
    if (err) {
      reply.send(err)
    } else {
      reply.view({ raw: file }, data)
    }
  })
})

Note that by using the raw option, you are considering the template as trusted - @fastify/view does not perform any validation on the template content.

DO NOT USE raw with untrusted content, or you will make yourself vulnerable to Remote Code Execution (RCE) attacks.

Minifying HTML on render

To utilize html-minifier-terser in the rendering process, you can add the option useHtmlMinifier with a reference to html-minifier-terser, and the optional htmlMinifierOptions option is used to specify the html-minifier-terser options:

// get a reference to html-minifier-terser
const minifier = require('html-minifier-terser')
// optionally defined the html-minifier-terser options
const minifierOpts = {
  removeComments: true,
  removeCommentsFromCDATA: true,
  collapseWhitespace: true,
  collapseBooleanAttributes: true,
  removeAttributeQuotes: true,
  removeEmptyAttributes: true
}
// in template engine options configure the use of html-minifier
  options: {
    useHtmlMinifier: minifier,
    htmlMinifierOptions: minifierOpts
  }

To exclude paths from minification, you can add the option pathsToExcludeHtmlMinifier with a list of paths:

// get a reference to html-minifier-terser
const minifier = require('html-minifier-terser')
// in options configure the use of html-minifier-terser and set paths to exclude from minification
const options = {
  useHtmlMinifier: minifier,
  pathsToExcludeHtmlMinifier: ['/test']
}

fastify.register(require("@fastify/view"), {
  engine: {
    ejs: require('ejs')
  },
  options
});

// This path is excluded from minification
fastify.get("/test", (req, reply) => {
  reply.view("./template/index.ejs", { text: "text" });
});

Engine-specific settings

Mustache

To use partials in mustache you will need to pass the names and paths in the options parameter:

  options: {
    partials: {
      header: 'header.mustache',
      footer: 'footer.mustache'
    }
  }
fastify.get('/', (req, reply) => {
  reply.view('./templates/index.mustache', data)
})
fastify.get('/', (req, reply) => {
  fs.readFile('./templates/index.mustache', 'utf8', (err, file) => {
    if (err) {
      reply.send(err)
    } else {
      const render = mustache.render.bind(mustache, file)
      reply.view(render, data)
    }
  })
})
fastify.get('/', (req, reply) => {
  fs.readFile('./templates/index.mustache', 'utf8', (err, file) => {
    if (err) {
      reply.send(err)
    } else {
      reply.view({ raw: file }, data)
    }
  })
})

Handlebars

To use partials in handlebars you will need to pass the names and paths in the options parameter:

  options: {
    partials: {
      header: 'header.hbs',
      footer: 'footer.hbs'
    }
  }

You can specify compile options as well:

  options: {
    compileOptions: {
      preventIndent: true
    }
  }

To access defaultContext and reply.locals as @data variables:

  options: {
    useDataVariables: true
  }

To use layouts in handlebars you will need to pass the layout parameter:

fastify.register(require("@fastify/view"), {
  engine: {
    handlebars: require("handlebars"),
  },
  layout: "./templates/layout.hbs",
});

fastify.get("/", (req, reply) => {
  reply.view("./templates/index.hbs", { text: "text" });
});
fastify.get('/', (req, reply) => {
  fs.readFile('./templates/index.hbs', 'utf8', (err, file) => {
    if (err) {
      reply.send(err)
    } else {
      const render = handlebars.compile(file)
      reply.view(render, data)
    }
  })
})
fastify.get('/', (req, reply) => {
  fs.readFile('./templates/index.hbs', 'utf8', (err, file) => {
    if (err) {
      reply.send(err)
    } else {
      reply.view({ raw: file }, data)
    }
  })
})

Nunjucks

You can load templates from multiple paths when using the nunjucks engine:

fastify.register(require("@fastify/view"), {
  engine: {
    nunjucks: re

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

JavaScriptfastifyfastify-pluginspeedtemplates

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月17日
分类编程语言
定价开源

> 相关工具

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言