在thinkjs中实现Gzip压缩和静态文件缓存

在thinkjs中实现Gzip压缩和静态文件缓存

thinkjs在作者 welefen的努力下即将支持 目前需要实现Gzip压缩需要在github上下载最新版的thinkjs

修改core/View.js的 31-71行附近

 /**
 * 输出模版文件内容
 * @param {[type]} templateFile [description]
 * @param {[type]} charset [description]
 * @param {[type]} contentType [description]
 * @param {[type]} content [description]
 * @return {[type]} [description]
 */
 display: function(templateFile, charset, contentType){
 var self = this;
 return tag('view_init', this.http).then(function(){
 return self.fetch(templateFile);
 }).then(function(content){
 return self.render(content, charset, contentType).then(function(){
 return tag('view_end', self.http, content);
 });
 }).then(function(){
 return self.http.end();
 }).catch(function(err){
 console.error(err.stack);
 return self.http.end();
 });
 },
 /**
 * 渲染模版
 * @param {[type]} content [description]
 * @param {[type]} charset [description]
 * @param {[type]} contentType [description]
 * @return {[type]} [description]
 */
 render: function(content, charset, contentType){
 if (!this.http.cthIsSend) {
 charset = charset || C('encoding');
 contentType = contentType || C('tpl_content_type');
 this.http.setHeader('Content-Type', contentType + '; charset=' + charset);
 }
 if (C('show_exec_time')) {
 this.http.sendTime('Exec-Time');
 }
 return this.http.echo(content || '', charset || C('encoding'));
 },

修改 core/Controller.js 的340行左右

 /**
 * 结束输出,输出完成时一定要调用这个方法
 * @param {[type]} obj [description]
 * @return {[type]} [description]
 */
 end: function(obj, encoding) {
 var self=this;
 if (obj !== undefined) {
 self.echo(obj, encoding).then(function(){
 self.http.end();
 });
 }else{
 self.http.end();
 }
 },

这些相信不久welefen会修改的。 接下来实现tag行为 GzipContentBehavior.js. 我注释掉了deflate压缩去掉注释就可以实现deflate压缩,把文件放到App/Lib/Behavior下面

var zlib = require('zlib');
/**
 * Gzip压缩
 */
module.exports = Behavior(function () {
 return {
 run: function (content) {
 var self = this;
 var deferred = getDefer();
 // if (self.http.headers["accept-encoding"].indexOf("deflate") != -1) {
 // self.deflate(content, self.http, deferred);
 // } else if (self.http.headers["accept-encoding"].indexOf("gzip") != -1) {
 // self.gzip(content, self.http, deferred);
 // } else {
 // return content;
 // }
 if (self.http.headers["accept-encoding"].indexOf("gzip") != -1) {
 self.gzip(content, self.http, deferred);
 } else {
 return content;
 }
 return deferred.promise;
 },
 gzip: function (content, http, deferred) { //检测是否是手机访问
 zlib.gzip(content, function (err, data) {
 if (!err) {
 http.res.setHeader("Content-Encoding", "gzip");
 deferred.resolve(data);
 } else {
 deferred.resolve(content);
 }
 });
 },
 deflate: function (content, http, deferred) { //检测是否是手机访问
 zlib.deflate(content, function (err, data) {
 if (!err) {
 http.res.setHeader("Content-Encoding", "deflate");
 deferred.resolve(data);
 } else {
 deferred.resolve(content);
 }
 });
 },
 }
})

然后在App/Conf/tag.js里面配置一下

//行为
module.exports = {
 resource_check: ['CheckResource'],
 content_write:['GzipContent']
}

看到了CheckResource,它是实现静态文件gzip压缩和缓存的.它使用mime库所以需要npm install mime一下

var fs = require('fs');
var mime = require('mime');
var path = require("path");
var zlib = require('zlib');
/**
 * 静态资源请求
 * @return {[type]} [description]
 */
module.exports = Behavior(function () {
 'use strict';
 return {
 options: {
 'url_resource_on': false
 },
 run: function () {
 if (!RESOURCE_PATH || !this.options.url_resource_on || !this.http.pathname) {
 return false;
 }
 var pathname = this.http.pathname;
 if (pathname.indexOf('/') === 0) {
 pathname = pathname.substr(1);
 }
 var reg = C('url_resource_reg');
 //通过正则判断是否是静态资源请求
 if (!reg.test(pathname)) {
 return false;
 }
 var file = RESOURCE_PATH + '/' + pathname;
 var res = this.http.res;
 var req = this.http.req;
 fs.stat(file, function (err, stats) {
 if (err) {
 res.statusCode = 404;
 res.end();
 } else {
 var contentType = mime.lookup(file);
 var exp_maxage = C('expires_maxAge') || 30 * 24 * 3600;
 var expires = new Date();
 var lastModified = stats.mtime.toUTCString();
 var ifModifiedSince = "If-Modified-Since".toLowerCase();
 var acceptEncoding = "Accept-Encoding".toLowerCase();
 expires.setTime(expires.getTime() + exp_maxage * 1000);
 res.setHeader('Content-Type', contentType || "text/plain");
 res.setHeader("Cache-Control", "max-age=" + exp_maxage);
 res.setHeader("Expires", expires.toUTCString());
 res.setHeader("Last-Modified", lastModified);
 if (req.headers[ifModifiedSince] && lastModified == req.headers[ifModifiedSince]) {
 res.writeHead(304, "Not Modified");
 res.end();
 } else {
 var fileStream = fs.createReadStream(file);
 if ((req.headers[acceptEncoding] || '').indexOf('gzip') != -1&&contentType.match(/(javascript|css)/)) {
 res.setHeader('Content-Encoding', 'gzip');
 var gzip = fileStream.pipe(zlib.createGzip());
 gzip.pipe(res);
 gzip.on('end', function () {
 res.end();
 });
 }else {
 fileStream.pipe(res);
 fileStream.on('end', function () {
 res.end();
 });
 }
 }
 }
 });
 //返回一个pendding promise, 不让后续执行
 return getDefer().promise;
 }
 };
});

至此我们就完成了thinkjs的gzip和浏览器缓存的功能。 刚刚接触thinkjs不久,如果代码中有的地方不对。还望海涵。

w3ctech微信

扫码关注w3ctech微信公众号

共收到2条回复

  • 学习了哈

    不过这个排版怎么这样呢?怎么到处用引用呢?还在头部加了一个标题,哈哈

    回复此楼
  • 最好通过配置项开启

    回复此楼

AltStyle によって変換されたページ (->オリジナル) /