自己写的类koa-static
- 上一章我已经分析了中间件的基本机构,现在来写一写 类koa-static功能的插件
- 所谓的类koa-static功能的插件,就是 和koa-static功能基本一样,大致上就是自己定义一个存放静态资源的文件夹,然后把左右的静态资源文件存放进去,然后获取静态资源的时候,可以直接去静态资源的文件夹找到然后直接返回
- 这个插件,我叫做他 static-resource
来看看大致的构架
module.exports = function(){
return async function static(ctx,next){
// 代码的实现
}
}
- 首先是参数的确认,第一个参数肯定是自己设置的要存放静态资源的文件夹的路径,也可以是文件夹,第二个参数就是选项参数,这个可有可无,但是为了以后的更多的配置,还是要形式上的添加上,于是架构就变成了这样子
/**
* @params static_path 存放静态资源的路径或者文件夹 string
* @params options 更多的参数配置对象 object
*/
module.exports = function(static_path,options){
return async function static(ctx,next){
// 代码的实现
}
}
- 当然啦,主要还是第一个参数,存放静态资源的路径(或者说文件夹),在这里,如果说没有传递参数,那么第一个参数(也就是存放静态资源的路径)会默认是在项目的根目录下的static文件夹里,如果有参数,那就是自己自定义的文件夹里
- 在这里会遇到一个问题就是怎么获取项目的根目录
获取项目根目录的代码
// 判断是不是 Desktop
function isDesktop(url){
var arr = url.split("\\")
return arr[arr.length-2] === "Desktop"
}
// 获取根目录
function rootpath(url){
var s = "/"
var cache = []
while(!isDesktop(url)){
s += "../"
cache.push(url)
url = path.join(__dirname,s)
}
return cache.pop()
}
- 这个代码实际上是有局限性的,适用于所有在桌面上创建的项目,在其他地方创建的项目就不适用了,至于这个获取项目根目录的问题,之后我再去研究更全面的在任何地方创建项目都可以获取项目更目录的方法,现在主要还是要实现static-resource
const path = require("path")
/**
* @params static_path 存放静态资源的路径或者文件夹 string
* @params options 更多的参数配置对象 object
*/
module.exports = function(static_path,options){
var staticpath = static_path && path.join(rootpath(__dirname),static_path) ||
path.join(rootpath(__dirname),"/static") // 默认会在更目录下的static文件夹下
return async function static(ctx,next){
// 代码的实现
}
}
- 接下来就是主要的代码实现
- 首先要判断一个http请求的是不是静态资源,静态资源可以是一个js文件,css文件,一张图片等等,现在创建一个总体的对象fileType 来包括所有可能用到的静态资源。
const fileType = {
'css': 'text/css',
'less': 'text/css',
'gif': 'image/gif',
'html': 'text/html',
'ico': 'image/x-icon',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'json': 'application/json',
'pdf': 'application/pdf',
'png': 'image/png',
'svg': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
'tiff': 'image/tiff',
'txt': 'text/plain',
'wav': 'audio/x-wav',
'wma': 'audio/x-ms-wma',
'wmv': 'video/x-ms-wmv',
'xml': 'text/xml'
}
- 可以看见,对象的key就是静态资源的扩展名,而对应的值value就是相应的文件形式,实际上就是 Content-Type的值
- 所以判断是不是静态资源的方法很简单,就是:请求的url地址的扩展名有没有出现在 fileType 里边,如果有,那就是要获取静态资源,如果没有,那说明请求不是获取静态资源
说到这里,那怎怎么获取url的扩展名?
function parseFileType(url){
var extname = path.extname(url)
extname = extname ? extname.slice(1) : "unkown"
return fileType[extname]
}
const path = require("path")
const fs = require("fs")
/**
* @params static_path 存放静态资源的路径或者文件夹 string
* @params options 更多的参数配置对象 object
*/
module.exports = function(static_path,options){
var staticpath = static_path && path.join(rootpath(__dirname),static_path) ||
path.join(rootpath(__dirname),"/static")
return async function static(ctx,next){
// 代码的实现
var type = parseFileType(ctx.url)
if(type){
// 说明是在请求静态资源
ctx.type = type // 设置返回的文件类型
ctx.body = fs.createReadStream(staticpath + ctx.url)
// 从存储静态资源的文件夹里读取静态资源然后返回
}
await next()
}
}
- 到这里,static-resource基本上已经完成了
这是全部的代码
const path = require("path")
const fs = require("fs")
const fileType = {
'css': 'text/css',
'less': 'text/css',
'gif': 'image/gif',
'html': 'text/html',
'ico': 'image/x-icon',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'text/javascript',
'json': 'application/json',
'pdf': 'application/pdf',
'png': 'image/png',
'svg': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
'tiff': 'image/tiff',
'txt': 'text/plain',
'wav': 'audio/x-wav',
'wma': 'audio/x-ms-wma',
'wmv': 'video/x-ms-wmv',
'xml': 'text/xml'
}
/**
* @params static_path 存放静态资源的路径或者文件夹 string
* @params options 更多的参数配置对象 object
*/
module.exports = function(static_path,options){
var staticpath = static_path && path.join(rootpath(__dirname),static_path) || path.join(rootpath(__dirname),"/static")
return async function static(ctx,next){
// 代码的实现
var type = parseFileType(ctx.url)
if(type){
// 说明是在请求静态资源
ctx.type = type // 设置返回的文件类型
ctx.body = fs.createReadStream(staticpath + ctx.url) // 从存储静态资源的文件夹里读取静态资源然后返回
}
await next()
}
}
function parseFileType(url){
var extname = path.extname(url)
extname = extname ? extname.slice(1) : "unkown"
return fileType[extname]
}
function isDesktop(url){
var arr = url.split("\\")
return arr[arr.length-2] === "Desktop"
}
// 获取根目录
function rootpath(url){
var s = "/"
var cache = []
while(!isDesktop(url)){
s += "../"
cache.push(url)
url = path.join(__dirname,s)
}
return cache.pop()
}
这个插件我已经上传到npm里了
npm i static-resource-plugin