Skip to content

Commit 983c26e

Browse files
committed
first commit
0 parents  commit 983c26e

File tree

10 files changed

+373
-0
lines changed

10 files changed

+373
-0
lines changed

.eslintrc.js

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module.exports = {
2+
parser: '@typescript-eslint/parser',
3+
plugins: [
4+
'typescript',
5+
'@typescript-eslint',
6+
],
7+
extends: ['airbnb-base'],
8+
rules: {
9+
// allow debugger during development
10+
'linebreak-style': 0,
11+
indent: [2, 4, {
12+
SwitchCase: 1,
13+
}],
14+
'max-len': [2, { code: 160, ignoreUrls: true }],
15+
radix: ['error', 'as-needed'],
16+
'object-shorthand': ['error', 'methods'],
17+
'no-unused-expressions': ['error', {
18+
allowShortCircuit: true,
19+
}],
20+
'no-bitwise': ['error', {
21+
allow: ['~'],
22+
}],
23+
'import/extensions': 0,
24+
'import/no-unresolved': 0,
25+
'import/prefer-default-export': 0,
26+
'import/no-dynamic-require': 0,
27+
'object-curly-newline': 0,
28+
'consistent-return': 0,
29+
'no-shadow': 0,
30+
'no-redeclare': 0,
31+
'no-unused-vars': 0,
32+
'no-useless-constructor': 0,
33+
'no-empty-function': 0,
34+
'class-methods-use-this': 0,
35+
'import/no-extraneous-dependencies': 0,
36+
'@typescript-eslint/no-shadow': 2,
37+
'@typescript-eslint/no-redeclare': 2,
38+
'@typescript-eslint/no-unused-vars': 2,
39+
'@typescript-eslint/no-useless-constructor': 2,
40+
'no-restricted-syntax': 0,
41+
'no-param-reassign': 0,
42+
'no-return-await': 0,
43+
'no-use-before-define': 0,
44+
'no-await-in-loop': 0,
45+
'no-continue': 0,
46+
'no-plusplus': 0,
47+
'no-debugger': 0,
48+
'no-console': 0,
49+
'no-bitwise': 0,
50+
'padding-line-between-statements': [
51+
'warn',
52+
{ blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
53+
{ blankLine: 'any', prev: ['const', 'let', 'var'], next: ['const', 'let', 'var'] },
54+
{ blankLine: 'always', prev: '*', next: 'return' },
55+
{ blankLine: 'always', prev: 'block-like', next: '*' },
56+
{ blankLine: 'always', prev: 'block', next: '*' },
57+
{ blankLine: 'always', prev: 'function', next: '*' },
58+
],
59+
},
60+
};

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
lib
3+
yarn.lock
4+
package-lock.json

.vscode/launch.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Run app",
9+
"type": "node",
10+
"request": "launch",
11+
"program": "${workspaceRoot}/node_modules/ts-node/dist/bin.js",
12+
"args": [
13+
"src/app.ts"
14+
],
15+
"cwd": "${workspaceRoot}",
16+
"protocol": "inspector"
17+
}
18+
]
19+
}

README.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# @umajs/plugin-vue-ssr
2+
> 针对Umajs提供vue服务端渲染模式的插件,插件基于服务端渲染骨架工具[Srejs](https://github.com/dazjean/srejs)开发。
3+
4+
## 插件介绍
5+
`plugin-vue-ssr`插件扩展了`Umajs`中提供的统一返回处理`Result`对象,新增了`vue`页面组件渲染方法,可在`controller`自由调用,使用类似传统模板引擎;也同时将方法挂载到了koa中间件中的`ctx`对象上;当一些公关的页面组件,比如404、异常提示页面、登录或者需要在中间件中拦截跳转时可以在`middleware`中调用。
6+
7+
## 插件安装
8+
9+
```
10+
yarn add @umajs/plugin-vue-ssr --save
11+
```
12+
## 插件配置
13+
```ts
14+
// plugin.config.ts
15+
export default <{ [key: string]: TPluginConfig }>{
16+
vue: {
17+
enable:true,
18+
options:{
19+
rootDir:'web', // 客户端页面组件根文件夹
20+
rootNode:'app', // 客户端页面挂载根元素ID
21+
ssr: true, // 全局开启服务端渲染
22+
cache: false, // 全局使用服务端渲染缓存 开发环境设置true无效
23+
prefixCDN: '/' // 客户端代码部署CDN前缀
24+
}
25+
}
26+
};
27+
```
28+
29+
## 插件使用
30+
```ts
31+
import { BaseController, Path } from '@umajs/core';
32+
import { Result } from '../plugins/vue-ssr';
33+
34+
export default class Index extends BaseController {
35+
@Path('/')
36+
index() {
37+
return Result.vue('index', { title: 'umajs-vue-ssr'});
38+
}
39+
}
40+
41+
```
42+
43+
## **[开发使用文档](https://umajs.gitee.io/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%B8%B2%E6%9F%93/vue-ssr.html)**
44+
45+
## 案例
46+
- [css-module](https://github.com/dazjean/Srejs/tree/mian/example/uma--vue-css-module)
47+
- [vuex](https://github.com/dazjean/Srejs/tree/mian/example/uma-vue-vuex)
48+
- [vue-router](https://github.com/dazjean/Srejs/tree/mian/example/uma-vue-router)
49+
- [elementUI](https://github.com/dazjean/Srejs/tree/mian/example/uma-elementUI)
50+
- [ant-design-vue](https://github.com/dazjean/Srejs/tree/mian/example/uma-ant-design-vue)

__tests__/app.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import * as path from 'path';
2+
import * as shell from "shelljs";
3+
import Uma from '@umajs/core';
4+
import { Router } from '@umajs/router';
5+
6+
const pluginDir = path.resolve(__dirname, './plugins');
7+
shell.rm(pluginDir);
8+
shell.mkdir(pluginDir);
9+
shell.ln('-sf', path.resolve(__dirname, '../src'), path.resolve(__dirname, './plugins/vue-ssr'));
10+
11+
const uma = Uma.instance({
12+
Router,
13+
bodyParser: { multipart: true },
14+
ROOT: __dirname,
15+
env: process.argv.indexOf('production') > -1 ? 'production' : 'development',
16+
});
17+
18+
uma.start(8058);

__tests__/config/plugin.config.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export default {
2+
'vue-ssr': {
3+
options: {
4+
test: 1,
5+
},
6+
},
7+
};
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { BaseController, Result } from '@umajs/core';
2+
3+
export default class Index extends BaseController {
4+
index() {
5+
return Result.send('This is index.');
6+
}
7+
}

package.json

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
{
2+
"name": "@umajs/plugin-vue-ssr",
3+
"version": "0.0.1",
4+
"description": "In umajs, Vue is used to develop the plug-in of spa and MPa, which supports server-side rendering and client-side rendering",
5+
"author": "[email protected]",
6+
"keywords": [
7+
"vue",
8+
"ssr",
9+
"vue ssr",
10+
"Nuxtjs",
11+
"Nuxt",
12+
"umajs",
13+
"umajs-vue-ssr",
14+
"@umajs/plugin-vue-ssr"
15+
],
16+
"license": "MIT",
17+
"main": "lib/index.js",
18+
"directories": {
19+
"lib": "lib",
20+
"test": "__tests__"
21+
},
22+
"files": [
23+
"lib",
24+
"index.d.ts"
25+
],
26+
"publishConfig": {
27+
"registry": "http://registry.npmjs.org",
28+
"access": "public"
29+
},
30+
"scripts": {
31+
"fix": "esw src --fix --ext .ts",
32+
"lint": "npx eslint src --ext .ts",
33+
"lint-w": "esw src --clear --color -w --ext .ts",
34+
"build-w": "tsc -w --inlineSourceMap",
35+
"start": "run-p lint-w build-w",
36+
"prebuild": "npm run lint",
37+
"build": "tsc",
38+
"prepublish": "npm run build"
39+
},
40+
"dependencies": {
41+
"@srejs/vue": "^1.0.0-alpha.2",
42+
"@umajs/core": "^1.2.1",
43+
"consolidate": "^0.16.0",
44+
"get-stream": "^6.0.1"
45+
},
46+
"devDependencies": {
47+
"@types/jest": "^26.0.19",
48+
"@types/koa": "^2.0.48",
49+
"@types/node": "^12.20.16",
50+
"@types/shelljs": "^0.8.7",
51+
"@typescript-eslint/eslint-plugin": "^4.20.0",
52+
"@typescript-eslint/parser": "^4.20.0",
53+
"@umajs/core": "^1.1.2",
54+
"@umajs/router": "^1.1.2",
55+
"eslint": "^7.15.0",
56+
"eslint-config-airbnb-base": "^14.2.0",
57+
"eslint-plugin-import": "^2.22.1",
58+
"eslint-plugin-node": "^11.1.0",
59+
"eslint-plugin-promise": "^4.2.1",
60+
"eslint-plugin-typescript": "^0.14.0",
61+
"eslint-watch": "^7.0.0",
62+
"koa": "^2.11.0",
63+
"npm-run-all": "^4.1.5",
64+
"shelljs": "^0.8.3",
65+
"ts-node": "^8.8.1",
66+
"ts-node-dev": "^1.0.0-pre.44",
67+
"typescript": "^3.8.3"
68+
},
69+
"repository": {
70+
"type": "git",
71+
"url": "[email protected]:Umajs/plugin-vue-ssr.git"
72+
},
73+
"bugs": {
74+
"url": "https://github.com/Umajs/plugin-vue-ssr"
75+
},
76+
"homepage": "https://github.com/Umajs/plugin-vue-ssr#readme"
77+
}

src/index.ts

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { IContext, TPlugin, Result as R, Uma, TPluginConfig } from '@umajs/core';
2+
import * as engineSource from 'consolidate';
3+
import * as getStream from 'get-stream';
4+
import Srejs from '@srejs/vue';
5+
6+
interface TviewOptions{
7+
ssr?: boolean, // 全局开启服务端渲染
8+
cache?: boolean, // 全局使用服务端渲染缓存
9+
useEngine?:boolean // 渲染自定义html的页面组件时,选择性开启使用模板引擎
10+
}
11+
12+
export interface TssrPluginOptions extends TviewOptions {
13+
rootDir?:string, // 客户端页面组件根文件夹
14+
rootNode?:string, // 客户端页面挂载根元素ID
15+
defaultRouter?:boolean, // 开启默认文件路由
16+
prefixCDN?:string, // 构建后静态资源CDN地址前缀
17+
prefixRouter?:string // 默认页面路由前缀(在defaultRouter设置为true时有效)
18+
}
19+
20+
interface IvueViewParms{
21+
viewName :string;
22+
initProps : any,
23+
options:TviewOptions
24+
}
25+
export class Result<T> extends R<T> {
26+
/**
27+
*
28+
* @param viewName 页面标识
29+
* @param initProps 初始化数据上下文(模板和组件props可直接接收),如果传递state则自动注入到vuex初始化state中
30+
* @param options 页面组件标识
31+
* @returns
32+
*/
33+
static vue(viewName: string, initProps?: any, options?:TviewOptions) {
34+
return new Result<IvueViewParms>({
35+
type: 'vueView',
36+
data: {
37+
viewName,
38+
initProps,
39+
options,
40+
},
41+
});
42+
}
43+
}
44+
const NODE_ENV = (process.env && process.env.NODE_ENV) || 'development';
45+
let SrejsInstance;
46+
47+
/** 插件配置读取放到了@srejs/vue框架中进行兼容,在生产环境部署前构建阶段不会执行插件 */
48+
let opt:TssrPluginOptions = Uma.config?.ssr || {}; // ssr.config.ts
49+
const vueSsrPlugin = <TPluginConfig>Uma.config?.plugin?.vue || <TPluginConfig>Uma.config?.plugin['vue-ssr'];
50+
51+
if (vueSsrPlugin?.options) {
52+
opt = vueSsrPlugin.options;
53+
}
54+
55+
let defaultRouter = false;
56+
57+
// eslint-disable-next-line no-prototype-builtins
58+
if (opt.hasOwnProperty('defaultRouter')) {
59+
defaultRouter = opt.defaultRouter;
60+
}
61+
62+
try {
63+
SrejsInstance = new Srejs(Uma.app, NODE_ENV === 'development', defaultRouter, opt);
64+
} catch (error) {
65+
console.error(error);
66+
}
67+
68+
const renderView = async (ctx:IContext, viewName:string, initProps?:any, options?:TviewOptions) => {
69+
let html = await SrejsInstance.render(ctx, viewName, initProps, options);
70+
71+
const viewPlugin = <TPluginConfig>Uma.config?.plugin.views; // use @umajs/plugin-views
72+
73+
if (viewPlugin?.enable && options.useEngine) {
74+
const { opts } = viewPlugin.options;
75+
const { map } = opts;
76+
const engineName = map?.html;
77+
78+
console.assert(engineName, '@umajs/plugin-views must be setting; eg====> map:{html:"nunjucks"}');
79+
const engine = engineSource[engineName];
80+
const state = { ...options, ...ctx.state || {}, ...initProps };
81+
82+
if (typeof html === 'object' && html.readable && options.cache) {
83+
// when cache model ,html return a file stream
84+
html = await getStream(html);
85+
}
86+
87+
html = await engine.render(html, state);
88+
}
89+
90+
ctx.type = 'text/html';
91+
ctx.body = html;
92+
};
93+
94+
export default (): TPlugin => ({
95+
results: {
96+
async vueView(ctx: IContext, data: IvueViewParms) {
97+
const {
98+
viewName,
99+
initProps = {},
100+
options = {},
101+
} = data;
102+
103+
await renderView(ctx, viewName, initProps, options);
104+
},
105+
},
106+
context: {
107+
async vue(viewName:string, initProps?:any, options?:TviewOptions) {
108+
await renderView(this, viewName, initProps, options);
109+
},
110+
},
111+
112+
});

tsconfig.json

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"target": "es2017",
5+
"noImplicitAny": false,
6+
"sourceMap": false,
7+
"rootDir":"./src",
8+
"outDir":"./lib",
9+
"watch":false,
10+
"declaration": true,
11+
"alwaysStrict": true,
12+
"removeComments": true,
13+
"preserveWatchOutput": true,
14+
"experimentalDecorators": true
15+
},
16+
"include":[
17+
"./src/**/*"
18+
]
19+
}

0 commit comments

Comments
 (0)