{"id":13487459,"url":"https://github.com/eggjs/view","last_synced_at":"2026-01-23T18:16:16.419Z","repository":{"id":17641364,"uuid":"82399277","full_name":"eggjs/view","owner":"eggjs","description":"Base view plugin for egg","archived":false,"fork":false,"pushed_at":"2025-02-03T16:39:40.000Z","size":68,"stargazers_count":41,"open_issues_count":0,"forks_count":8,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-10-31T13:03:21.416Z","etag":null,"topics":["egg","egg-plugin","egg-view","template-engine","view"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eggjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-18T16:17:22.000Z","updated_at":"2025-02-03T16:39:43.000Z","dependencies_parsed_at":"2025-02-03T17:31:16.996Z","dependency_job_id":"ca1b8718-53d7-4800-a3cc-d1480efc346d","html_url":"https://github.com/eggjs/view","commit_stats":{"total_commits":29,"total_committers":9,"mean_commits":"3.2222222222222223","dds":0.5517241379310345,"last_synced_commit":"0f4e16afb723aa4756d30a4315bebeafd464b175"},"previous_names":["eggjs/view"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/eggjs/view","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eggjs%2Fview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eggjs%2Fview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eggjs%2Fview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eggjs%2Fview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eggjs","download_url":"https://codeload.github.com/eggjs/view/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eggjs%2Fview/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28697428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T17:25:48.045Z","status":"ssl_error","status_checked_at":"2026-01-23T17:25:47.153Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["egg","egg-plugin","egg-view","template-engine","view"],"created_at":"2024-07-31T18:00:59.662Z","updated_at":"2026-01-23T18:16:16.387Z","avatar_url":"https://github.com/eggjs.png","language":"TypeScript","readme":"# @eggjs/view\n\n[![NPM version](https://img.shields.io/npm/v/@eggjs/view.svg?style=flat-square)](https://npmjs.org/package/@eggjs/view)\n[![NPM quality](http://npm.packagequality.com/shield/@eggjs/view.svg?style=flat-square)](http://packagequality.com/#?package=@eggjs/view)\n[![NPM download](https://img.shields.io/npm/dm/@eggjs/view.svg?style=flat-square)](https://npmjs.org/package/@eggjs/view)\n[![Continuous Integration](https://github.com/eggjs/view/actions/workflows/nodejs.yml/badge.svg)](https://github.com/eggjs/view/actions/workflows/nodejs.yml)\n[![Test coverage](https://img.shields.io/codecov/c/github/eggjs/view.svg?style=flat-square)](https://codecov.io/gh/eggjs/view)\n[![Node.js Version](https://img.shields.io/node/v/@eggjs/view.svg?style=flat)](https://nodejs.org/en/download/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://makeapullrequest.com)\n![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/eggjs/view)\n\nBase view plugin for egg\n\n**it's a plugin that has been built-in for egg.**\n\n## Install\n\n```bash\nnpm i @eggjs/view\n```\n\n## Usage\n\n```js\n// {app_root}/config/plugin.js\nexports.view = {\n  enable: true,\n  package: '@eggjs/view',\n};\n```\n\n## Use a template engine\n\n[egg-view] don't have build-in view engine, So you should choose a template engine like [ejs], and install [egg-view-ejs] plugin.\n\nYou can choose a template engine first, link [ejs], so we use [egg-view-ejs] plugin.\n\n`egg-view` is in [eggjs], so you just need configure [egg-view-ejs].\n\n```js\n// config/plugin.js\nexports.ejs = {\n  enable: true,\n  package: 'egg-view-ejs',\n};\n```\n\nConfigure the mapping, the file with `.ejs` extension will be rendered by ejs.\n\n```js\n// config/config.default.js\nexports.view = {\n  mapping: {\n    '.ejs': 'ejs',\n  },\n};\n```\n\nIn controller, you can call `ctx.render`.\n\n```js\nmodule.exports = app =\u003e {\n  return class UserController extends app.Controller {\n    async list() {\n      const { ctx } = this;\n      await ctx.render('user.ejs');\n    }\n  };\n};\n```\n\nIf you call `ctx.renderString`, you should specify viewEngine in viewOptions.\n\n```js\nmodule.exports = app =\u003e {\n  return class UserController extends app.Controller {\n    async list() {\n      const { ctx } = this;\n      ctx.body = await ctx.renderString('\u003c%= user %\u003e', { user: 'popomore' }, {\n        viewEngine: 'ejs',\n      });\n    }\n  };\n};\n```\n\n## Use multiple view engine\n\n[egg-view] support multiple view engine, so you can use more than one template engine in one application.\n\nIf you want add another template engine like [nunjucks], then you can add [egg-view-nunjucks] plugin.\n\nConfigure the plugin and mapping\n\n```js\n// config/config.default.js\nexports.view = {\n  mapping: {\n    '.ejs': 'ejs',\n    '.nj': 'nunjucks',\n  },\n};\n```\n\nYou can simply render the file with `.nj` extension.\n\n```js\nawait ctx.render('user.nj');\n```\n\n## How to write a view plugin\n\nYou can use [egg-view]' API to register a plugin.\n\n### View engine\n\nCreate a view engine class first, and implement `render` and `renderString`, if the template engine don't support, just throw an error. The view engine is context level, so it receive ctx in `constructor`.\n\n```js\n// lib/view.js\nmodule.exports = class MyView {\n  constructor(ctx) {\n    // do some initialize\n    // get the plugin config from `ctx.app.config`\n  }\n\n  async render(fullpath, locals) {\n    return myengine.render(fullpath, locals);\n  }\n\n  async renderString() { throw new Error('not implement'); }\n};\n```\n\n`render` and `renderString` support generator function, async function, or normal function return a promise.\n\nIf the template engine only support callback, you can wrap it by Promise.\n\n```js\nclass MyView {\n  render(fullpath, locals) {\n    return new Promise((resolve, reject) =\u003e {\n      myengine.render(fullpath, locals, (err, result) =\u003e {\n        if (err) {\n          reject(err);\n        } else {\n          resolve(result);\n        }\n      });\n    });\n  }\n};\n```\n\nThese methods receive three arguments, `renderString` will pass tpl as the first argument instead of name in `render`.\n\n`render(name, locals, viewOptions)`\n\n- name: the file path that can resolve from root (`app/view` by default)\n- locals: data used by template\n- viewOptions: the view options for each render, it can override the view default config in `config/config.default.js`. Plugin should implement it if it has config.\n  When you implement view engine, you will receive this options from `render`, the options contain:\n  - root: egg-view will resolve the name to full path, but seperating root and name in viewOptions.\n  - name: the original name when call render\n  - locals: the original locals when call render\n\n`renderString(tpl, locals, viewOptions)`\n\n- tpl: the template string instead of the file, using in `renderString`\n- locals: same as `render`\n- viewOptions: same as `render`\n\n### Register\n\nAfter define a view engine, you can register it.\n\n```js\n// app.js\nmodule.exports = app =\u003e {\n  app.view.use('myName', require('./lib/view'));\n};\n```\n\nYou can define a view engine name, normally it's a template name.\n\n### Configure\n\nDefine plugin name and depend on [egg-view]\n\n```json\n{\n  \"eggPlugin\": {\n    \"name\": \"myName\",\n    \"dependencies\": [ \"view\" ]\n  }\n}\n```\n\nSet default config in `config/config.default.js`, the name is equals to plugin name.\n\n```js\nexports.myName = {},\n```\n\nSee some examples\n\n- [egg-view-ejs]\n- [egg-view-nunjucks]\n\n## Configuration\n\n### Root\n\nRoot is `${baseDir}/app/view` by default, but you can define multiple directory, seperated by `,`. [egg-view] will find a file from all root directories.\n\n```js\nmodule.exports = appInfo =\u003e {\n  const baseDir = appInfo.baseDir;\n  return {\n    view: {\n      root: `${baseDir}/app/view,${baseDir}/app/view2`\n    }\n  }\n}\n```\n\n### defaultExtension\n\nWhen render a file, you should specify a extension that let [egg-view] know whitch engine you want to use. However you can define `defaultExtension` without write the extension.\n\n```js\n// config/config.default.js\nexports.view = {\n  defaultExtension: '.html',\n};\n\n// controller\nmodule.exports = app =\u003e {\n  return class UserController extends app.Controller {\n    async list() {\n      const { ctx } = this;\n      // render user.html\n      await ctx.render('user');\n    }\n  };\n};\n```\n\n### viewEngine and defaultViewEngine\n\nIf you are using `renderString`, you should specify viewEngine in view config, see example above.\n\nHowever, you can define `defaultViewEngine` without set each time.\n\n```js\n// config/config.default.js\nexports.view = {\n  defaultViewEngine: 'ejs',\n};\n```\n\nsee [config/config.default.ts](https://github.com/eggjs/view/blob/master/src/config/config.default.ts) for more detail.\n\n## Questions \u0026 Suggestions\n\nPlease open an issue [here](https://github.com/eggjs/egg/issues).\n\n## License\n\n[MIT](LICENSE)\n\n## Contributors\n\n[![Contributors](https://contrib.rocks/image?repo=eggjs/logrotator)](https://github.com/eggjs/logrotator/graphs/contributors)\n\nMade with [contributors-img](https://contrib.rocks).\n\n[eggjs]: https://eggjs.org\n[ejs]: https://github.com/mde/ejs\n[egg-view-ejs]: https://github.com/eggjs/egg-view-ejs\n[egg-view]: https://github.com/eggjs/view\n[nunjucks]: http://mozilla.github.io/nunjucks\n[egg-view-nunjucks]: https://github.com/eggjs/egg-view-nunjucks\n","funding_links":[],"categories":["仓库"],"sub_categories":["[内置插件](https://eggjs.org/zh-cn/basics/plugin.html#%E6%8F%92%E4%BB%B6%E5%88%97%E8%A1%A8)"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feggjs%2Fview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feggjs%2Fview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feggjs%2Fview/lists"}