# 性能优化实战(二)
没分段,后面补
之前的面向对象的server告一段落,采用ioc的方式进行内容注入
先将app.js中 的路由注入删掉
import 'module-alias/register';
import Koa from 'koa';
const app = new Koa();
import config from '@config';
import render from 'koa-swig';
import { wrap } from 'co';
import serve from 'koa-static';
import errorHandler from "./middlewares/errorHandler";
const { error } = errorHandler;
import { configure, getLogger } from 'log4js';
const { viewDir, staticDir, port, cache } = config;
configure({
appenders: { cheese: { type: 'file', filename: __dirname + '/logs/yd.log' } },
categories: { default: { appenders: ['cheese'], level: 'error' } }
});
const logger = getLogger('cheese');
app.context.logger = logger;
app.context.render = wrap(render({
root: viewDir,
autoescape: true,
cache,
ext: 'html',
writeBody: false
}))
app.use(serve(staticDir));
error(app);
// -------------------被删了---------------------------
// 路由的注册中心
// controllersInit(app);
app.listen(port, () => {
console.log('服务启动成功!!');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
然后BooksController.js中的model也删掉
import cheerio from 'cheerio';
import {Readable} from 'stream';
class BookController {
async actionIndex(ctx, next) {
ctx.status = 200;
ctx.type = 'html';
const result = await $model.getList();
const html = await ctx.render('books/pages/list', {
result
});
if(ctx.request.header["x-pjax"]){
console.log('站内切');
const $ = cheerio.load(html);
// let _result = '';
$('.pjaxcontent').each(function() {
ctx.res.write($(this).html());
})
$('.lazyload-js').each(function() {
ctx.res.write(`<script src="${$(this).attr("src")}"></script>`);
})
// ctx.body = _result;
ctx.res.end();
} else {
// console.log('直接刷新');
// ctx.body = html;
function createSSRStream() {
return new Promise((resolve, reject) => {
const htmlStream = new Readable();
htmlStream.push(html);
htmlStream.push(null);
htmlStream.on('error',err => {reject(err)}).pipe(ctx.res);
})
}
await createSSRStream();
}
// console.log("返回的值", result);
// ctx.body = html;
}
async actionCreate(ctx, next) {
ctx.body = await ctx.render('books/pages/create');
}
}
export default BookController;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
controllers中没用的index.js和BaseController.js也可以删掉了
安装两个包
yarn add awilix awilix-koa
1
在app.js中进行注入
import 'module-alias/register';
import Koa from 'koa';
const app = new Koa();
import config from '@config';
import render from 'koa-swig';
import { wrap } from 'co';
import serve from 'koa-static';
import errorHandler from "./middlewares/errorHandler";
const { error } = errorHandler;
import { configure, getLogger } from 'log4js';
const { viewDir, staticDir, port, cache } = config;
import { createContainer, Lifetime } from 'awilix';
import { loadControllers, scopePerRequest } from 'awilix-koa';
// 构建容器
const container = createContainer();
container.loadModules([__dirname + ["/services/*.js"]], {
resolverOptions: {
lifetime: Lifetime.SCOPED
}
})
// 把容器和路由最终合并到一起
app.use(scopePerRequest(container));
configure({
appenders: { cheese: { type: 'file', filename: __dirname + '/logs/yd.log' } },
categories: { default: { appenders: ['cheese'], level: 'error' } }
});
const logger = getLogger('cheese');
app.context.logger = logger;
app.context.render = wrap(render({
root: viewDir,
autoescape: true,
cache,
ext: 'html',
writeBody: false
}))
app.use(serve(staticDir));
error(app);
// 加载所有的路由
loadControllers(__dirname + '/controllers/*.js');
app.listen(port, () => {
console.log('服务启动成功!!');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
把 modle文件夹改名为 services,Books改名为 BooksServices.js
在 controllers/BooksController.js中添加注入
import cheerio from 'cheerio';
import {Readable} from 'stream';
class BookController {
// -----------------------------------
constructor({booksServices}) {
this.booksServices = booksServices;
}
// -----------------------------------
async actionIndex(ctx, next) {
ctx.status = 200;
ctx.type = 'html';
// -----------------------------------
const result = await this.booksServices.getList();
// -----------------------------------
const html = await ctx.render('books/pages/list', {
result
});
if(ctx.request.header["x-pjax"]){
console.log('站内切');
const $ = cheerio.load(html);
// let _result = '';
$('.pjaxcontent').each(function() {
ctx.res.write($(this).html());
})
$('.lazyload-js').each(function() {
ctx.res.write(`<script src="${$(this).attr("src")}"></script>`);
})
// ctx.body = _result;
ctx.res.end();
} else {
// console.log('直接刷新');
// ctx.body = html;
function createSSRStream() {
return new Promise((resolve, reject) => {
const htmlStream = new Readable();
htmlStream.push(html);
htmlStream.push(null);
htmlStream.on('error',err => {reject(err)}).pipe(ctx.res);
})
}
await createSSRStream();
}
// console.log("返回的值", result);
// ctx.body = html;
}
async actionCreate(ctx, next) {
ctx.body = await ctx.render('books/pages/create');
}
}
export default BookController;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
再在app.js中
import 'module-alias/register';
import Koa from 'koa';
const app = new Koa();
import config from '@config';
import render from 'koa-swig';
import { wrap } from 'co';
import serve from 'koa-static';
import errorHandler from "./middlewares/errorHandler";
const { error } = errorHandler;
import { configure, getLogger } from 'log4js';
const { viewDir, staticDir, port, cache } = config;
// --------------------------------------------------------
import { createContainer, Lifetime } from 'awilix';
import { loadControllers, scopePerRequest } from 'awilix-koa';
// 构建容器
const container = createContainer();
container.loadModules([__dirname + ["/services/*.js"]], {
// --------------------------------------------------------
formatName: 'camelCase',
// --------------------------------------------------------
resolverOptions: {
lifetime: Lifetime.SCOPED
}
})
// 把容器和路由最终合并到一起
app.use(scopePerRequest(container));
// --------------------------------------------------------
configure({
appenders: { cheese: { type: 'file', filename: __dirname + '/logs/yd.log' } },
categories: { default: { appenders: ['cheese'], level: 'error' } }
});
const logger = getLogger('cheese');
app.context.logger = logger;
app.context.render = wrap(render({
root: viewDir,
autoescape: true,
cache,
ext: 'html',
writeBody: false
}))
app.use(serve(staticDir));
error(app);
// 加载所有的路由
app.use(loadControllers(__dirname + '/controllers/*.js'));
app.listen(port, () => {
console.log('服务启动成功!!');
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
到此就完成了依赖注入
接下来添加路由 BooksController.js
import cheerio from 'cheerio';
import {Readable} from 'stream';
// ---------------------------------------
import {route, GET} from 'awilix-koa';
// ---------------------------------------
@route('/books')
class BookController {
constructor({booksServices}) {
this.booksServices = booksServices;
}
// ---------------------------------------
@route('/list')
@GET()
// ---------------------------------------
async actionIndex(ctx, next) {
ctx.status = 200;
ctx.type = 'html';
const result = await this.booksServices.getList();
const html = await ctx.render('books/pages/list', {
result
});
if(ctx.request.header["x-pjax"]){
console.log('站内切');
const $ = cheerio.load(html);
// let _result = '';
$('.pjaxcontent').each(function() {
ctx.res.write($(this).html());
})
$('.lazyload-js').each(function() {
ctx.res.write(`<script src="${$(this).attr("src")}"></script>`);
})
// ctx.body = _result;
ctx.res.end();
} else {
// console.log('直接刷新');
// ctx.body = html;
function createSSRStream() {
return new Promise((resolve, reject) => {
const htmlStream = new Readable();
htmlStream.push(html);
htmlStream.push(null);
htmlStream.on('error',err => {reject(err)}).pipe(ctx.res);
})
}
await createSSRStream();
}
// console.log("返回的值", result);
// ctx.body = html;
}
// ---------------------------------------
@route('/create')
@GET()
// ---------------------------------------
async actionCreate(ctx, next) {
ctx.body = await ctx.render('books/pages/create');
}
}
export default BookController;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
IndexController.js
import Controller from './BaseController';
const fs = require('fs');
const {resolve} = require('path');
import {route, GET} from 'awilix-koa';
@route('/')
class IndexController extends Controller{
constructor() {
super()
}
@route('/')
@GET()
async actionIndex(ctx, next) {
// ctx.body = await ctx.render('Index/index')
ctx.body = {
home: '首页数据'
}
}
@route('/test')
@GET()
async testIndex(ctx, next) {
ctx.status = 200;
ctx.type = 'html';
const task1 = () => {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(`<script>addHTML("part1", "第一次输出<br/>")</script>`)
}, 1000);
})
}
const task2 = () => {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(`<script>addHTML("part2", "第二次输出<br/>")</script>`)
}, 2000);
})
}
const filename = resolve(__dirname, 'index.html');
const file1 = fs.readFileSync(filename ,'utf-8');
// ctx.body = file1;
// ctx.res.write(file1);
// ctx.res.end();
/* function createSSRStream() {
return new Promise((resolve, reject) => {
const stream = fs.createReadStream(filename);
stream.on('data', chunk => {ctx.res.write(chunk)});
stream.on('end', () => {
ctx.res.end();
})
stream.on('error',err => {reject(err)});
})
}
await createSSRStream(); */
ctx.res.write(file1);
const result1 = await task1();
ctx.res.write(result1);
const result2 = await task2();
ctx.res.write(result2);
ctx.res.end();
}
}
export default IndexController;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
此时打包报错,gulp不支持装饰器 再装个装饰器的插件
yarn add @babel/plugin-proposal-decorators
1
修改 gulpfile 文件
const gulp = require('gulp');
const watch = require('gulp-watch');
const babel = require('gulp-babel');
const entry = './src/server/**/*.js';
const configEntry = './src/server/config/index.js';
const rollup = require('gulp-rollup');
const replace = require('rollup-plugin-replace');
// 开发环境
function builddev() {
return watch(entry, {ignoreInitial: false}, function() {
gulp.src(entry).pipe(babel({
// 不读取外面的babelrc配置,不需要编译成es5
'babelrc': false,
'plugins': [
// ---------------------------------
["@babel/plugin-proposal-decorators", {
legacy: true
}],
// ---------------------------------
"@babel/plugin-transform-modules-commonjs"
]
}))
.pipe(gulp.dest('dist'));
})
}
// 上线环境
function buildProd() {
return gulp.src(entry).pipe(babel({
// 不读取外面的babelrc配置,不需要编译成es5
'babelrc': false,
'ignore':[configEntry],
'plugins': [
// ---------------------------------
["@babel/plugin-proposal-decorators", {
legacy: true
}],
// ---------------------------------
"@babel/plugin-transform-modules-commonjs"
]
}))
.pipe(gulp.dest('dist'));
}
function buildConfig() {
return gulp.src(entry)
.pipe(rollup({
input: configEntry,
output: {
format: 'cjs'
},
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
}))
.pipe(gulp.dest('./dist'))
}
function buildLint() {
}
let build = gulp.series(builddev);
if (process.env.NODE_ENV == 'production') {
build = gulp.series(buildProd, buildConfig);
}
if (process.env.NODE_ENV == 'lint') {
build = gulp.series(buildLint);
}
gulp.task('default', build);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
会出现点零了吧碎的小错误,把indexController.js中的关于BaseController的都删了 好,启动成功!
← 性能优化实战