egg-view-nrssr

1.0.13 • Public • Published

egg-view-nrssr

NPM version build status Test coverage David deps Known Vulnerabilities npm download

eggjs框架的nunjucks模板插件

依赖说明

依赖的 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-nrssregg-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
};
  • 其中noCachenunjunks的配置,你还可以使用任何其他的nunjunks配置

注意事项

webpack打包需要将React组件文件和hydrate文件导出为commonjs模块。因为为了减少客户端全局变量,我们使用了唯一全局变量exports。参考如下配置:

output: {
  filename: '[name].js',
  libraryTarget: 'commonjs',
  library: '[name]',
  libraryExport: 'default',
}

提问交流

请到 egg-view-nrssr issues 异步交流。

License

MIT

Dependents (1)

Package Sidebar

Install

npm i egg-view-nrssr

Weekly Downloads

0

Version

1.0.13

License

MIT

Unpacked Size

20.1 kB

Total Files

11

Last publish

Collaborators

  • mclemore