Skip to content

Commit

Permalink
feat: support asset render
Browse files Browse the repository at this point in the history
  • Loading branch information
hubcarl committed Dec 13, 2018
1 parent 816dc8f commit 857fb54
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 22 deletions.
57 changes: 40 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ vue server side render solution for egg.

- support vue server side render and static resource inject html
- support vue server side render error, auto try client render
- support asset render layout by nunjucks or ejs enigne

## Install

```bash
$ npm i egg-view-vue-ssr --save
```

## Document

https://www.yuque.com/easy-team/egg-vue

## Usage

```js
Expand All @@ -40,17 +45,6 @@ exports.vuessr = {
package: 'egg-view-vue-ssr',
};
```
## Version

#### 1.x.x-2.x.x

egg-view-vue-ssr depends on egg-view-vue plugin

#### 3.x.x

- 3.x.x(egg-view-vue-ssr) no longer depends on egg-view-vue plugin, egg-view-vue-ssr has an independent function that can run on its own

- vue and vue-server-renderer are not inside in plugin dependence

## Configuration

Expand Down Expand Up @@ -105,28 +99,57 @@ exports.vuessr = {

## Render

### Server Render, call `render` method
### Server Render, Call `render`

> when server render bundle error, will try client render**
**Note: when server render bundle error, will try client render**
> https://www.yuque.com/easy-team/egg-vue/node
```js
// controller/home.js
exports.index = function* (ctx) {
yield ctx.render('index/index.js', Model.getPage(1, 10));
yield ctx.render('index/index.js', { message: 'egg vue server side render'});
};
```

### Client Render, Call `renderClient` or build static html to `egg-static` dir by Webpack.
### Client Render, Call `renderClient`, Use Vue render layout

> https://www.yuque.com/easy-team/egg-vue/web
when client render , the template is `exports.vuessr.layout`
> when client render, render layout `exports.vuessr.layout` by Vue
```js
// controller/home.js
exports.client = function* (ctx) {
yield ctx.renderClient('index/index.js', Model.getPage(1, 10));
yield ctx.renderClient('index/index.js',{ message: 'egg vue client render'});
};
```

### Asset Render, Call `renderAsset`, Use render layout by viewEngine, default `nunjucks`

> https://www.yuque.com/easy-team/egg-vue/asset
- when asset render, you can render layout `exports.vuessr.layout` by viewEngine, default use `egg-view-nunjucks`
- you must install the specified engine dependence, such as `egg-view-nunjucks` or `egg-view-ejs`
- The context provides an `asset` object that can get `js`, `css`, `state` information. [layout template](https://www.yuque.com/easy-team/egg-vue/asset)

#### use default viewEngine nunjucks

```js
// controller/home.js
exports.asset = function* (ctx) {
yield ctx.renderAsset('index/index.js', { message: 'egg vue asset render'});
};
```

#### current render viewEngine config

```js
// controller/home.js
exports.asset = function* (ctx) {
yield ctx.renderAsset('index/index.js', { message: 'egg vue asset render'}, { viewEngine: 'ejs' });
};
```

see [config/config.default.js](config/config.default.js) for more detail.

Expand Down
2 changes: 2 additions & 0 deletions config/config.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ module.exports = app => {
* url {String} inline file absolution path
* @property {Boolean} [mergeLocals] whether merge ctx locals, default true
* @property {Boolean|String} [crossorigin] js cross domain support for cdn js error catch, default false
* @property {String} [viewEngine] egg-view render engine, only valid when renderAsset rendering,default nunjucks
* @property {Object} [cache] lru-cache options @see https://www.npmjs.com/package/lru-cache
* @property {Object} [renderOptions] @see https://ssr.vuejs.org/en/api.html#renderer-options
* renderOptions.template will override layout template
Expand All @@ -43,6 +44,7 @@ module.exports = app => {
crossorigin: false,
mergeLocals: true,
fallbackToClient: true, // fallback to client rendering if server render failed,
viewEngine: 'nunjucks', // only valid when renderAsset rendering
cache: {
max: 1000,
maxAge: 1000 * 3600 * 24 * 7,
Expand Down
4 changes: 3 additions & 1 deletion lib/engine.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';
const fs = require('fs');
const assert = require('assert');
const Vue = require('vue');
const LRU = require('lru-cache');
const serialize = require('serialize-javascript');
Expand Down Expand Up @@ -64,7 +65,7 @@ class Engine {
return {
js: res.js || [],
css: res.css || [],
state: serialize(state || {}, { isJSON: true })
state: serialize(state || {}, { isJSON: true }),
};
}

Expand Down Expand Up @@ -161,6 +162,7 @@ class Engine {
const state = Object.assign({}, ctx.locals, locals);
const asset = this.getAsset(name, state);
const template = this.getTemplate(options);
assert(template, 'layout is missing, please set vuessr.layout or options.layout');
const context = Object.assign({}, locals, { asset });
// egg-view 自动合并 ctx, request, response, helper
return ctx.renderString(template, context, { viewEngine });
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "egg-view-vue-ssr",
"version": "3.1.3",
"version": "3.2.0",
"description": "vue server side render solution for egg",
"eggPlugin": {
"name": "vuessr"
Expand Down Expand Up @@ -28,6 +28,7 @@
"egg-bin": "^3.7.0",
"egg-ci": "^1.5.0",
"egg-mock": "^3.2.0",
"egg-view-nunjucks": "^2.2.0",
"eslint": "^3.18.0",
"eslint-config-egg": "^3.2.0",
"supertest": "^3.0.0",
Expand Down
12 changes: 10 additions & 2 deletions test/fixtures/apps/view-vue-ssr-test/app/controller/view.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

const path = require('path');
exports.renderString = function* (ctx) {
ctx.body = yield ctx.renderString('<div>name:{{name}},desc:{{desc}}</div>', {
name: 'egg-vue-view',
Expand Down Expand Up @@ -43,5 +43,13 @@ exports.renderClient = function* (ctx) {
};

exports.renderVueClient = function* (ctx) {
yield ctx.renderVueClient('test/test.js', { message: 'vue server side render!' });
this.body = yield ctx.renderVueClient('test/test.js', { message: 'vue server side render!' });
};

exports.renderAsset = function* (ctx) {
yield ctx.renderAsset('app/app.js', { title: 'renderAsset', message: 'vue server side render!' }, { layout: path.join(ctx.app.baseDir, 'app/view/layout_asset.html')});
};

exports.renderVueAsset = function* (ctx) {
this.body = yield ctx.renderVueAsset('app/app.js', { title: 'renderAsset', message: 'vue server side render!' }, { layout: path.join(ctx.app.baseDir, 'app/view/layout_asset.html')});
};
2 changes: 2 additions & 0 deletions test/fixtures/apps/view-vue-ssr-test/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ module.exports = app => {
app.get('/renderLocals', app.controller.view.renderLocals);
app.get('/renderString', app.controller.view.renderString);
app.get('/renderClient', app.controller.view.renderClient);
app.get('/renderAsset', app.controller.view.renderAsset);
app.get('/renderVueAsset', app.controller.view.renderVueAsset);
app.get('/renderVueClient', app.controller.view.renderVueClient);
app.get('/renderServerError', app.controller.view.renderServerError);
};
23 changes: 23 additions & 0 deletions test/fixtures/apps/view-vue-ssr-test/app/view/layout_asset.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang='en'>
<head>
<title>{{title}}</title>
<meta name='keywords'>
<meta name='description'>
<meta http-equiv='content-type' content='text/html;charset=utf-8'>
<meta name='viewport' content='initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui'>
<link rel='shortcut icon' href='/favicon.ico' type='image/x-icon' />
{% for item in asset.css %}
<link rel="stylesheet" href='{{item}}' />
{% endfor %}
</head>
<body>
<div id='app'></div>
{% for item in asset.js %}
<script type="text/javascript" src="{{item}}"></script>
{% endfor %}
<script type="text/javascript">
window.__INITIAL_STATE__ = {{ asset.state | safe }};
</script>
</body>
</html>
6 changes: 5 additions & 1 deletion test/fixtures/apps/view-vue-ssr-test/config/plugin.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
'use strict';
exports.static = true;
exports.static = true;
exports.nunjucks = {
enable: true,
package: 'egg-view-nunjucks',
};
23 changes: 23 additions & 0 deletions test/view-vue-ssr.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,29 @@ describe('test/view-vue-ssr.test.js', () => {
});
});

it('should GET /renderAsset', () => {
return request(app.callback())
.get('/renderAsset')
.expect(200)
.expect(res => {
assert(res.text.indexOf('<title>renderAsset</title>') > -1);
assert(res.text.indexOf('/public/js/runtime.js') > -1);
assert(res.text.indexOf('/public/js/vendor.js"') > -1);
assert(res.text.indexOf('/public/js/app/app.js"') > -1);
});
});

it('should GET /renderVueAsset', () => {
return request(app.callback())
.get('/renderVueAsset')
.expect(200)
.expect(res => {
assert(res.text.indexOf('<title>renderAsset</title>') > -1);
assert(res.text.indexOf('/public/js/runtime.js') > -1);
assert(res.text.indexOf('/public/js/vendor.js"') > -1);
assert(res.text.indexOf('/public/js/app/app.js"') > -1);
});
});

it('should GET /renderVueClient', () => {
return request(app.callback())
Expand Down

0 comments on commit 857fb54

Please sign in to comment.