Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
BigKoa = BigView + Koa
bigview的生命周期
bigview的生命周期精简
biglet的生命周期
Install
$ npm i -g bigview-cli
Usages
$ bpm a b c
generate ~/a/MyPagelet.js
generate ~/a/index.html
generate ~/a/index.js
generate ~/a/req.js
generate ~/b/MyPagelet.js
generate ~/b/index.html
generate ~/b/index.js
generate ~/b/req.js
generate ~/c/MyPagelet.js
generate ~/c/index.html
generate ~/c/index.js
generate ~/c/req.js
$ npm i -S bigview
const MyBigView = require('./MyBigView')
app.get('/', function (req, res) {
var bigpipe = new MyBigView(req, res, 'basic/index', { title: "测试" })
var Pagelet1 = require('./bpmodules/basic/p1')
var pagelet1 = new Pagelet1()
var Pagelet2 = require('./bpmodules/basic/p2')
var pagelet2 = new Pagelet2()
bigpipe.add(pagelet1)
bigpipe.add(pagelet2)
bigpipe.start()
});
app.get('/nest', function (req, res) {
var bigpipe = new MyBigView(req, res, 'nest/index', { title: "测试" })
var Pagelet1 = require('./bpmodules/nest/p1')
var pagelet1 = new Pagelet1()
var Pagelet2 = require('./bpmodules/nest/p2')
var pagelet2 = new Pagelet2()
pagelet1.addChild(pagelet2)
bigpipe.add(pagelet1)
bigpipe.start()
});
views/nest/index.html是bp的布局文件
<!doctype html>
<html class="no-js">
<head>
<title><%= title %></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<div id="pagelet2" class="pagelet2">load,,,,</div>
<ul>
<% pagelets.forEach(function(p){ %>
<li><%= p.name %> | <%= p.selector %>
<% if (p.children.length) { %>
<ul>
<% p.children.forEach(function(sub){ %>
<li> subPagelet = <%= sub.name %> | <%= sub.selector %>
<% }) %>
</ul>
<% } %>
<% }) %>
</ul>
<% pagelets.forEach(function(p){ %>
<div id="<%= p.location %>" class="<%= p.selector %>">loading...<%= p.name %>...</div>
<% }) %>
<script src="/js/jquery.min.js"></script>
<script src="/js/bigpipe.js"></script>
<script>
var bigpipe=new Bigpipe();
<% pagelets.forEach(function(p){ %>
bigpipe.ready('<%= p.name %>',function(data){
$("#<%= p.location %>").html(data);
})
<% }) %>
bigpipe.ready('pagelet2',function(data){
$("#pagelet2").html(data);
})
</script>
</body>
</html>
遍历pagelets来生成各种页面需要的即可。
views/nest2/index.html是bp的布局文件
<!doctype html>
<html class="no-js">
<head>
<title><%= title %></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<ul>
<% pagelets.forEach(function(p){ %>
<li><%= p.name %> | <%= p.selector %>
<% if (p.children.length) { %>
<ul>
<% p.children.forEach(function(sub){ %>
<li> subPagelet = <%= sub.name %> | <%= sub.selector %>
<% }) %>
</ul>
<% } %>
<% }) %>
</ul>
<% pagelets.forEach(function(p){ %>
<div id="<%= p.location %>" class="<%= p.selector %>">loading...<%= p.name %>...</div>
<% }) %>
<script src="/js/jquery.min.js"></script>
<script src="/js/bigpipe.js"></script>
<script>
var bigpipe=new Bigpipe();
<% pagelets.forEach(function(p){ %>
bigpipe.ready('<%= p.name %>',function(data){
$("#<%= p.location %>").html(data);
})
<% }) %>
</script>
</body>
</html>
此时无任何pagelet2的布局
在bpmodules/nest2/p1/p1.html里,输出pagelet2的布局。
<script>bigpipe.set("pagelet1", '<%= is %>');</script>
<div id="pagelet2" class="pagelet2">load,,,,</div>
<script>
bigpipe.ready('pagelet2',function(data){
$("#pagelet2").html(data);
})
</script>
自定义p1和p2,设置this.immediately = false
'use strict'
const Pagelet = require('../../../../packages/biglet')
module.exports = class MyPagelet extends Pagelet {
constructor () {
super()
this.root = __dirname
this.name = 'pagelet1'
this.data = { is: "pagelet1测试" }
this.selector = 'pagelet1'
this.location = 'pagelet1'
this.tpl = 'p1.html'
this.delay = 4000
this.immediately = false
}
fetch () {
let pagelet = this
return require('./req')(pagelet)
}
}
自定义BigView基类
'use strict'
const BigView = require('../../../packages/bigview')
module.exports = class MyBigView extends BigView {
before () {
let self = this
return new Promise(function(resolve, reject) {
self.showPagelet = self.query.a
resolve(true)
})
}
afterRenderLayout () {
let self = this
if (self.showPagelet === '1') {
self.run('pagelet1')
} else {
self.run('pagelet2')
}
// console.log('afterRenderLayout')
return Promise.resolve(true)
}
}
在bigview
'use strict'
const debug = require('debug')('bigview')
const fs = require('fs')
const MyBigView = require('./MyBigView')
module.exports = function (req, res) {
var bigpipe = new MyBigView(req, res, 'if/index', { title: "条件选择pagelet" })
bigpipe.add(require('./p1'))
bigpipe.add(require('./p2'))
bigpipe.start()
}
var bigpipe = new MyBigView(req, res, 'error/index', { title: "测试" })
// bigpipe.mode = 'render'
bigpipe.add(require('./p1'))
bigpipe.addErrorPagelet(require('./error'))
显示ErrorPagelet,可以在bigview的生命周期,执行子Pagelets之前。reject一个error即可。
比如在afterRenderLayout里,reject
afterRenderLayout() {
let self = this
// console.log('afterRenderLayout')
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject(new Error('xxxxxx'))
// resolve()
}, 0)
})
}
通过addErrorPagelet
设置Error时要显示的模块,如果要包含多个,请使用pagelet子模块。
另外,如果设置了ErrorPagelet,布局的时候可以使用errorPagelet来控制错误显示
<!doctype html>
<html class="no-js">
<head>
<title><%= title %></title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<div id="<%= errorPagelet.location %>" class="<%= errorPagelet.selector %>">
<ul>
<% pagelets.forEach(function(p){ %>
<li><%= p.name %> | <%= p.selector %>
<% }) %>
</ul>
<% pagelets.forEach(function(p){ %>
<div id="<%= p.location %>" class="<%= p.selector %>">loading...<%= p.name %>...</div>
<% }) %>
</div>
<script src="/js/jquery.min.js"></script>
<script src="/js/bigpipe.js"></script>
<script>
var bigpipe=new Bigpipe();
<% pagelets.forEach(function(p){ %>
bigpipe.ready('<%= p.name %>',function(data){
$("#<%= p.location %>").html(data);
})
<% }) %>
bigpipe.ready('<%= errorPagelet.name %>',function(data){
$("#<%= errorPagelet.location %>").html(data);
})
</script>
<script src="/bigconsole.min.js"></script>
</body>
</html>
提供trigger方法,可以触发1个多个多个其他模块,无序并行。结果返回的是Promise
'use strict'
const Pagelet = require('../../../../packages/biglet')
const somePagelet1 = require('./somePagelet1')
const somePagelet2 = require('./somePagelet2')
const somePagelet = require('./somePagelet')
module.exports = class MyPagelet extends Pagelet {
constructor () {
super()
this.root = __dirname
this.name = 'pagelet1'
}
fetch () {
// 触发一个模块
this.trigger(new somePagelet())
// 触发一个模块
this.trigger([new somePagelet1(), new somePagelet2()])
}
}
不允许,直接
return this.trigger([require('./somePagelet1'), require('./somePagelet2')])
这样会有缓存,不会根据业务请求来进行不同处理。
也可以强制的fetch里完成
'use strict'
const Pagelet = require('../../../../packages/biglet')
const somePagelet1 = require('./somePagelet1')
const somePagelet2 = require('./somePagelet2')
const somePagelet = require('./somePagelet')
module.exports = class MyPagelet extends Pagelet {
constructor () {
super()
this.root = __dirname
this.name = 'pagelet1'
}
fetch () {
// 触发多个模块
return this.trigger([new somePagelet1, new somePagelet2()])
}
}
app.get('/', function (req, res) {
var bigpipe = new MyBigView(req, res, 'basic/index', { title: "测试" })
var Pagelet1 = require('./bpmodules/basic/p1')
var pagelet1 = new Pagelet1()
var Pagelet2 = require('./bpmodules/basic/p2')
var pagelet2 = new Pagelet2()
bigpipe.add(pagelet1)
bigpipe.add(pagelet2)
// bigpipe.preview('aaaa.html')
bigpipe.previewFile = 'aaaa.html'
bigpipe.start()
});
方法
'use strict'
const Pagelet = require('../../../../packages/biglet')
module.exports = class MyPagelet extends Pagelet {
constructor () {
super()
this.root = __dirname
this.name = 'pagelet1'
this.data = { is: "pagelet1测试" }
this.location = 'pagelet1'
this.tpl = 'p1.html'
this.selector = 'pagelet1'
this.delay = 2000
}
fetch () {
return new Promise(function(resolve, reject){
setTimeout(function() {
// self.owner.end()
resolve(self.data)
}, 4000);
})
}
}
只需要重写fetch方法,并且返回Promise对象即可。如果想多个,就利用Promise的链式写法解决即可
无论http也好,还是其他方式(rpc)也好,都是需要参数的
所以要做的,依然是上面的fetch方法,由于pagelet是独立的,所以无法直接获取bigview页面的参数。
但是pagelet里有一个owner对象,其实就是bigview对象。
先看一下模块入口
'use strict'
const debug = require('debug')('bigview')
const fs = require('fs')
const MyBigView = require('./MyBigView')
module.exports = function (req, res) {
var bigpipe = new MyBigView(req, res, 'basic/index', { title: "测试" })
var Pagelet1 = require('./p1')
var pagelet1 = new Pagelet1()
var Pagelet2 = require('./p2')
var pagelet2 = new Pagelet2()
bigpipe.add(pagelet1)
bigpipe.add(pagelet2)
// bigpipe.preview('aaaa.html')
bigpipe.isMock = true
bigpipe.previewFile = 'aaaa.html'
bigpipe.start()
}
很明显这就是一个express中间件。
app.get('/', require('./bpmodules/basic'));
所以获取QueryString就很简单了,从req.query里获得就可以了。然后赋值给bigpipe对象。
实际上,bigview已经做了这件事,它自身已经绑定了3个获取参数的属性
所以在req.js里可以这样使用
例子如下
'use strict'
module.exports = function (pagelet) {
console.log(pagelet.owner.query)
pagelet.delay = 1000
return new Promise(function(resolve, reject){
setTimeout(function() {
// self.owner.end()
resolve(pagelet.data)
}, pagelet.delay)
})
}
'use strict'
const Pagelet = require('../../../../packages/biglet')
module.exports = class MyPagelet extends Pagelet {
constructor () {
super()
this.root = __dirname
this.name = 'pagelet1'
this.data = { is: "pagelet1测试" }
this.location = 'pagelet1'
this.tpl = 'p1.html'
this.selector = 'pagelet1'
this.delay = 2000
}
fetch () {
return new Promise(function(resolve, reject){
setTimeout(function() {
// self.owner.end()
resolve(self.data)
}, 4000);
})
}
render (tpl, data) {
const ejs = require('ejs')
let self = this
return new Promise(function(resolve, reject){
ejs.renderFile(tpl, data, self.options, function(err, str){
// str => Rendered HTML string
if (err) {
console.log(err)
reject(err)
}
resolve(str)
})
})
}
}
重写render()方法,如果不重写则采用默认的模板引擎ejs编译。
render方法的参数
.
├── MyBigView.js(实现类,继承自bigview)
├── index.js (返回MyBigView以及p1和p2等pagelet模块的组织)
├── p1(pagelet模块)
│ ├── index.js
│ ├── p1.html
│ └── req.js
└── p2(pagelet模块)
├── index.js
├── p2.html
└── req.js
pagelet的本章是返回模板引擎编译后的html片段。
模板引擎编译(模板 + 数据) = html
唯一比较麻烦的是数据的来源,可能是静态数据,也可能是api请求的数据,所以在设计pagelet的时候,通过集成fetch方法来实现自定义数据。为了进一步
├── p1(pagelet模块)
│ ├── index.js
│ ├── p1.html
│ └── req.js
说明
bigpipe
bigpipe.isMock = true
bigpipe.previewFile = 'aaaa.html'
pagelet带定
var Pagelet1 = require('./bpmodules/basic/p1')
var pagelet1 = new Pagelet1()
pagelet1.mock = true
pagelet1.data = {
xxx: yyy
}
pagelet1.test()
or
$ pt bpmoduless/p1 url
$ pt bpmoduless/p1 aaaa.json
自动跑测试,并给出测试结果
enable gzip:
const bigkoa = new BigKoa({ gzip: true })
pagelet能复用么?
直接请求,也未尝不可
性能改进
与传统Ajax比较
前端优化,参考微博的方式
异步加载显示模块的方式:BigPipe方式降低模块开发成本、管理成本
var FM=function(a,b,c){function bN(b,c){a.clear&&(bN=a.clear)(b,c)}function bM(b,c,d){a.start&&(bM=a.start)(b,c,d)}function bL(a){return a===null?"":Object.prototype.toString.call(a).slice(8,-1).toLowerCase()}function bK(){bv(function(){bH();for(var a in J){if(I[a]){bB(P,I[a]);delete
<script>FM.view({"ns":"pl.common.webim","domid":"pl_common_webim","css":["style/css/module/list/comb_webim.css?version=f25a07f3fbb17183"],"js":["webim_prime/js/common/all.js?version=8fde40d2c1ecd58b"]})</script>
<script>FM.view({"ns":"pl.top.index","domid":"plc_top","css":[],"js":["home/js/pl/top/index.js?version=8fde40d2c1ecd58b"],"html":""})</script>
<script>
pl.trigger('pagelet1',{
css: ['pl1.css'],
js: ['pl1.js'],
data: {},
html:'<span>Here is pagelet1</span>'
});
</script>
模块的css可以采用各种预处理编写,在提供bigpipe打包功能,合并到一起或者单独引入(可以再考虑)。
4种模式
BigPipe的三种模式:
http://velocity.oreilly.com.cn/2011/ppts/WK_velocity.pdf
review
测试独立
render统一(?)
初始化参数
fetch()就够用了,不必before(精简生命周期,fetch后增加parse)
layout:先返回布局(压测)(ok)
out模式:同步
日志
开关
性能
共享内存
约定,所有的数据,只能绑定到data上,改成parse
pagelet(传model)
继承自event,外接日志(基本实现)
静态布局和动态布局说明
bigview指定模板demo
pagelet指定外部模板demo
ng proxy给个头compress,expire-buffer
分享
封装前端bigpipe库
主流程bigview上5秒超时,biglet里fetch、parse等操作默认1秒超时,如果不满足,请设置timeout(单位是毫秒)
当获取数据后,某些模块不必要展示的时候,打破biglet的渲染promise链即可
biglet
移除了show属性,没有意义
FAQs
> BigKoa = BigView + Koa
The npm package bigkoa receives a total of 1 weekly downloads. As such, bigkoa popularity was classified as not popular.
We found that bigkoa demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.