Template rendering
This component is used to render ejs and nunjucks templates using the server in midway system.
Related information:
Web support | |
---|---|
@midwayjs/koa | ✅ |
@midwayjs/faas | ✅ |
@midwayjs/web | ✅ |
@midwayjs/express | ❌ |
Use ejs
Installation dependency
Select the corresponding template installation dependency.
$ npm i @midwayjs/view-ejs@3 --save
Or reinstall the following dependencies in package.json
.
{
"dependencies": {
"@midwayjs/view-ejs": "^3.0.0",
// ...
},
"devDependencies": {
// ...
}
}
Introducing components
First, introduce components and import them in configuration.ts
:
import { Configuration } from '@midwayjs/core';
import * as view from '@midwayjs/view-ejs';
import { join } from 'path'
@Configuration({
imports: [
View // import ejs components
],
importConfigs: [
join(__dirname, 'config')
]
})
export class MainConfiguration {
}
Configuration
Configure suffixes to map to the specified engine.
// src/config/config.default.ts
export default {
// ...
view: {
mapping: {
'.ejs': 'ejs',
},
},
// ejs config
ejs: {}
}
Use
Note that the default view directory is ${appDir}/view
. Create a hello.ejs
file in the view directory.
The directory structure is as follows:
➜ my_midway_app tree
.
├── src
│ └── controller ## Controller directory
│ └── home.ts
├── view ## Template directory
│ └── hello.ejs
├── test
├── package.json
└── tsconfig.json
We write some ejs format content in the template, such:
// view/hello.ejs
hello <%= data %>
Rendering in Controller.
import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
@Controller('/')
export class HomeController {
@Inject()
ctx: Context;
@Get('/')
async render() {
await this.ctx.render('hello.ejs', {
data: 'world',
});
}
}
Configure suffix
The default suffix is .html
. In order to change the suffix to .ejs
, we can add a defaultExtension
configuration.
// src/config/config.default.ts
export default {
// ...
view: {
defaultExtension: '.ejs',
mapping: {
'.ejs': 'ejs',
},
},
// ejs config
ejs: {}
}
In this way, we do not need to add suffixes when rendering.
@Controller('/')
export class HomeController {
@Inject()
ctx: Context;
@Get('/')
async render() {
await this.ctx.render('hello', {
data: 'world',
});
}
}
Default rendering engine
We can set the default rendering engine by defaultViewEngine
.
Its role is to use the engine specified by the defaultViewEngine
field to render when the template suffix encountered, such as .html
is not found in the mapping
field of the configuration.
// src/config/config.default.ts
export default {
// ...
view: {
defaultViewEngine: 'ejs',
mapping: {
'.ejs': 'ejs',
},
},
// ejs config
ejs: {}
}
In this way, if the template is a suffix of .html
, ejs
will still be used for rendering because it is not specified in the mapping
.
Configure multiple template directories
If we need to encapsulate the code as a component, we need to support different template directories.
The default template directory is ${appDir}/view
. We can add other directories to rootDir
fields.
// src/config/config.default.ts
// Modify the default directory of the default view component
export default {
// ...
view: {
rootDir: {
default: path.join(__dirname, './view')
}
},
}
// Other components need to add directory configuration
export default {
// ...
// Configuration of view components
view: {
rootDir: {
anotherRoot: path.join(__dirname, './view')
}
},
}
Through the object merging mechanism, all rootDir
can be merged together, and values are obtained inside the component for matching.
Use Nunjucks
Similar to ejs, just introduce the corresponding components.
- Select the corresponding template installation dependency.
$ npm i @midwayjs/view-nunjucks@3 --save
Or reinstall the following dependencies in package.json
.
{
"dependencies": {
"@midwayjs/view-nunjucks": "^3.0.0",
// ...
},
"devDependencies": {
// ...
}
}
- Introduce components and import them in
configuration.ts
:
import { Configuration } from '@midwayjs/core';
import * as view from '@midwayjs/view-nunjucks';
import { join } from 'path'
@Configuration({
imports: [
view // import nunjucks components
],
importConfigs: [
join(__dirname, 'config')
]
})
export class MainConfiguration {
}
- Add nunjucks configuration, such as default nunjucks.
export default {
// ...
view: {
defaultViewEngine: 'nunjucks',
mapping: {
'.nj': 'nunjucks',
},
},
}
- Add templates to the view directory
// view/test.nj
hi, {{ user }}
Rendering in Controller.
import { Inject, Provide } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
@Controller('/')
export class HomeController {
@Inject()
ctx: Context;
@Get('/')
async render() {
await ctx.render('test.nj', { user: 'midway' });
}
}
After the access, hi, midway
is output.
If you need a custom filter, you can add it at the entrance. For example, a filter named hello
is added below.
import { App, Configuration, Inject } from '@midwayjs/core';
import * as view from '@midwayjs/view-nunjucks';
import { join } from 'path'
@Configuration({
imports: [view],
importConfigs: [join(__dirname, 'config')]
})
export class MainConfiguration {
@App()
app;
@Inject()
env: view.NunjucksEnvironment;
async onReady() {
this.env.addFilter('hello', (str) => {
return 'hi, '+ str;
});
}
}
Can be used in the template
{{name | hello}}
Then render
// controller
// ...
await ctx.render('test.nj', { name: 'midway' });
hi, midway
is also output.
Custom template engine
By default, we only provide ejs and nunjucks template engines. You can also write your own template engine code.
Implement template engine
First, you need to create a template engine class for request scope, which will be initialized when each request is executed. You need to implement the render
and renderString
methods. If your template engine does not support a method, you can throw an exception.
// lib/view.ts
import { Provide, Config } from '@midwayjs/core';
import { IViewEngine } from '@midwayjs/view';
@Provide()
export class MyView implements IViewEngine {
@Config('xxxx')
viewConfig;
async render(name: string, locals?: Record<string, any>, options?: RenderOptions) {
return myengine.render(name, locals, options);
}
async renderString(tpl: string,
locals?: Record<string, any>,
options?: RenderOptions) {
throw new Error('not implement');
}
};
These two methods accept three similar parameters, renderString
the first parameter needs to pass in the template content to be parsed, while the render
method parses the template file.
render(name, locals, viewOptions)
- name: the path from the
root
(default is/view
). - Locals: data required by the template
- viewOptions: The template parameters for each rendering, the overridden configuration, can be overridden in the configuration file, which contains several parameters:
- root: the absolute path of the template
- Name: The original name value that calls the render method.
- locals: the original locals value that calls the render method.
renderString(tpl, locals, viewOptions)
- tpl: template name
- Locals: Same as
render
- viewOptions: Same as
render
Register template engine
After implementing the custom template engine, we need to register it at the startup portal.
By introducing ViewManager
, we can use the use
method to register a custom template engine.
// src/configuration.ts
import { Configuration, Inject, Provide } from '@midwayjs/core';
import * as koa from '@midwayjs/koa';
import * as view from '@midwayjs/view';
import { MyView } from './lib/my';
@Configuration({
imports: [koa, view],
importConfigs: [join(__dirname, 'config')]
})
export class MainConfiguration {
@Inject()
viewManager: view.ViewManager;
async onReady() {
this.viewManager.use('ejs', MyView);
}
}
Precautions
To use in egg(@midwayjs/web) scenarios, close view and its related plug-ins in plugin.ts
.
import { EggPlugin } from 'egg';
export default {
// ...
view: false
} as EggPlugin;
Otherwise, the following similar errors will occur.
TypeError: Cannot set property view of #<EggApplication> which has only a getter