egg-view-nrssr
v1.0.13
Published
[![NPM version][npm-image]][npm-url] [![build status][travis-image]][travis-url] [![Test coverage][codecov-image]][codecov-url] [![David deps][david-image]][david-url] [![Known Vulnerabilities][snyk-image]][snyk-url] [![npm download][download-image]][down
Downloads
19
Maintainers
Readme
egg-view-nrssr
依赖说明
依赖的 egg 版本
egg-view-nrssr 版本 | egg 1.x --- | --- 1.x | 😁 0.x | ❌
开启插件
// config/plugin.js
exports.nrssr = {
enable: true,
package: 'egg-view-nrssr',
};
使用场景
此插件主要用于使用
nunjucks
作为html
模板的react
同构应用。
它运用nunjucks
的自定义扩展能力,将服务端渲染的结果输出到html
中。使用方法:
在
eggjs
框架中启用该模板插件// config/plugin.js exports.nrssr = { enable: true, package: 'egg-view-nrssr', };
配置
egg-view-nrssr
// config/config.default.js module.exports = () => { const config = {}; config.nrssr = { customTagName: 'pagelet', hydrate: 'hydrate', manifestPath: path.join(process.cwd(), 'app/public/manifest.json'), ...otherConfig, }; config.view = { defaultViewEngine: 'nrssr', defaultExtension: '.html', }; return config; };
在
controller
中渲染nunjucks
模板// app/controller/home.js class HomeController extends Controller { async index() { const props = await ctx.service.home.getProps(); const body = await ctx.renderView('index', { pageletProps: { home: { ...props, } } }); } }
在
view
定义nunjucks
模板<!-- app/view/index.html --> <!DOCTYPE html> <html> <head> <title>My App</title> <meta charset="utf-8"> </head> <body> {% pagelet 'home' %} </body> </html>
controller
中的pageletProps
会传给egg-view-nrssr
,egg-view-nrssr
解析app/view/index.html
模板,
解析到{% pagelet 'home' %}
时,renderToString
会寻找home
组件,将pageletProps['home']
作为props
渲染home
组件得到html
替换{% pagelet 'home' %}
得到最终的html
。
详细配置
/**
* @property {Boolean} noCache - nunjucks配置,不使用缓存,每次都重新编译
* @property {Function} getLoadableBundles - react-loadable服务端渲染需要。获取当前页面懒加载的bundle打包后的文件名,以便提前插入到html中。
* 因为react-loadable懒加载应该用于前端路由变化时,在由服务端渲染页面时,
* 应该先在服务端通过preloadAll方法提前加载所有bundle,直接渲染当前页面完整内容。
* 然后在客户端先由script标签提前加载所有bundle,接着通过preloadReady方法告知bundle已经提前加载,
* 从而客户端混合时是和服务端一致的完整页面。
* 该方法接收一个参数modules,它是当前页面所有bundle名的数组。
* 当前页面所有bundle名要在服务端渲染页面时通过react-loadable提供的Capture高阶组件捕获。
* 具体参见react-loadable文档。
* @property {String} basename - react-router的basename。如果使用了react-router,服务端渲染react应用时需要此配置,以渲染出正确的内容
* @property {AsyncFunction} beforeStart - 在应用启动前执行。可以将服务端渲染时耗时长的操作放到这里提前执行。
* 比如把react组件提前通过babel编译读入内存;提前执行react-loadable的preloadAll等,以减少服务端渲染的时长
* @property {String} customTagName - nunjucks自定义扩展的tag标识符,我们称一个自定义扩展tag形成的块为pagelet。
* @property {Function | AsyncFunction} renderToString - 服务端渲染方法。渲染pagelet。
* 接收的参数:pageletProps 该页面所有pagelet的属性
* name 当前pagelet的名称
* reactRouterContext react-router服务端渲染的context,
* 用于Redirect在服务端渲染时的重定向等。
* 具体参见react-router Server Rendering文档
* loadableModules 收集当前页面react-loadable所有懒加载bundle名的数组
* ctx 当前请求的上下文,包含eggjs的ctx
* basename react-router的basename
* @property {String} hydrate - 用于客户端混合react的文件名
* @property {String} manifestPath - webpack打包生成的manifest文件路径。用于根据源码文件名找到打包后的文件名,打包后的文件名可能带有hash值。
* 本地开发时,manifest文件是从webpack虚拟文件系统读取,请使用的egg-webpack插件
* @property {String} commonFiles - webpack通过splitChunks分离出来的公共文件名。一般都是第三方库文件,这些文件需要提前注入到html中
* @property {String} renderHtml - nunjucks编译完后最后一次改变html的机会,原始需求是替换react-document-title生成的title。具体见react-document-title服务端渲染的文档
*/
exports.nrssr = {
noCache: false, // default false
getLoadableBundles: modules => [], // default () => [], required only if react-loadable used
basename: '', // default '', required only if react-router used
beforeStart: async app => [], // no default, not required
customTagName: 'pagelet', // no default, required
renderToString: async ({
pageletProps: {
[pagelet]: {}
},
name: '',
reactRouterContext: {},
loadableModules: [],
ctx: {
ctx: {
app
}
},
basename: '',
}) => html, // no default, required
hydrate: 'hydrate', // no default, required
manifestPath: '/path/to/app/public/mainfest.json', // no default, reqiured
commonFiles: [
'react',
'react-dom',
], // no default, not required
renderHtml: html => html // no default, not required
};
- 其中
noCache
是nunjunks
的配置,你还可以使用任何其他的nunjunks配置
注意事项
webpack
打包需要将React
组件文件和hydrate
文件导出为commonjs
模块。因为为了减少客户端全局变量,我们使用了唯一全局变量exports
。参考如下配置:
output: {
filename: '[name].js',
libraryTarget: 'commonjs',
library: '[name]',
libraryExport: 'default',
}
提问交流
请到 egg-view-nrssr issues 异步交流。