Skip to content
This repository has been archived by the owner on Jun 13, 2022. It is now read-only.

Commit

Permalink
feat: 优化静态资源缓存;优化缓存;挂载文档
Browse files Browse the repository at this point in the history
  • Loading branch information
CaoMeiYouRen committed May 28, 2020
1 parent f4e19cb commit 9cadc17
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 25 deletions.
10 changes: 8 additions & 2 deletions .env
Expand Up @@ -10,19 +10,25 @@ TOKEN='123456'

# 返回的item项数
ITEM_LIMIT=10

# 限流区间,每多少秒
LIMIT_INTERVAL=60
# 限流值,每个区间内可访问多少次
LIMIT_MAX=30

# 静态文件缓存时间(秒)
STATIC_MAX_AGE=86400

# 缓存类型 redis/memory
CACHE_TYPE='redis'
CACHE_TYPE='memory'
# 缓存时间(秒)
CACHE_AGE=300
# cache的最大长度,默认无穷大
CACHE_MAX=''

# Redis配置
REDIS_PORT=6379
REDIS_HOST='127.0.0.1'
REDIS_PASSWORD=''
# 前缀
# Redis前缀
REDIS_KEY_PREFIX='my-redis-'
2 changes: 1 addition & 1 deletion .eslintignore
@@ -1,5 +1,5 @@
dist
*.js
/*.js
/test/unit/coverage/
/test/unit/specs/
/build/
Expand Down
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -8,6 +8,8 @@ install:
- npm install
script:
- npm run build
- npm run docs:changelog
- npm run docs:build

deploy:
provider: script
Expand Down
17 changes: 15 additions & 2 deletions README.md
Expand Up @@ -5,7 +5,7 @@
设计目标:

- 将任何能搜索的网页的搜索结果处理成标准的RSS规范格式。
同时支持json和xml。
- 同时支持json和xml。
- 返回结果以json优先,xml通过转换产生
- 目标并不是支持RSS阅读器,而是将搜索结果转换为一种统一的格式,方便进行二次开发。仅参考RSS规范进行设计
- 项目的dist文件应当可以在node.js环境下直接运行,无需其他依赖【除redis缓存外】
Expand Down Expand Up @@ -47,10 +47,11 @@ routes规范约定
- 文件夹下必须有 index.ts
- index.ts 中只允许挂载路由,业务逻辑请在其他文件完成
- 路由一律采用默认导出的形式,即`export default router`
- 路由名称同文件夹名称,若文件夹名称为` example`,则挂载路由为`router.use('/example', example.routes(), example.allowedMethods())`

文档约定【待补充】


# 开发流程

## 使用

Expand All @@ -77,6 +78,18 @@ npm run build
npm run lint
```

## 文档开发

```sh
npm run docs:dev
```

## 文档编译

```sh
docs:build
```

## 提交变更

```sh
Expand Down
20 changes: 17 additions & 3 deletions package.json
Expand Up @@ -13,6 +13,11 @@
"build": "webpack --config ./webpack.config.js",
"prebuild": "rimraf dist",
"build:test": "tsc && webpack --config ./webpack.config.js && node dist/index.js",
"docs:dev": "nodemon --ext md,vue --watch docs --watch docs/.vuepress--exec vuepress dev docs",
"docs:dev2": "vuepress dev docs",
"docs:build": "vuepress build docs",
"predocs:build": "rimraf public",
"docs:changelog": "conventional-changelog -p cmyr-config -i docs/changelog/README.md -s -r 0",
"rm": "rimraf node_modules",
"debug": "cross-env DEBUG=koa:* npm run dev",
"commit": "git add . && git cz && git push",
Expand All @@ -35,6 +40,11 @@
"path": "cz-conventional-changelog"
}
},
"husky": {
"hooks": {
"commit-msg": "validate-commit-msg"
}
},
"lint-staged": {
".{ts,js}": [
"npm run lint",
Expand All @@ -46,6 +56,7 @@
},
"dependencies": {
"@koa/cors": "^3.1.0",
"@types/koa-static": "^4.0.1",
"axios": "^0.19.2",
"body-parser": "^1.19.0",
"cheerio": "^1.0.0-rc.3",
Expand All @@ -67,13 +78,14 @@
"koa-logger": "^3.2.1",
"koa-mount": "^4.0.0",
"koa-router": "^8.0.8",
"koa-static": "^5.0.0",
"koa2-ratelimit": "git+https://github.com/CaoMeiYouRen/koa2-ratelimit.git",
"lodash": "^4.17.15",
"lru-cache": "^5.1.1",
"mime": "^2.4.6",
"mockjs": "^1.1.0",
"module-alias": "^2.2.2",
"moment": "^2.26.0",
"morgan": "^1.10.0",
"require-all": "^3.0.0",
"rimraf": "^3.0.2",
"ts-loader": "^7.0.4",
Expand Down Expand Up @@ -109,10 +121,11 @@
"@types/lru-cache": "^5.1.0",
"@types/mockjs": "^1.0.2",
"@types/module-alias": "^2.0.0",
"@types/morgan": "^1.9.0",
"@types/node": "^14.0.5",
"@typescript-eslint/eslint-plugin": "^3.0.0",
"@typescript-eslint/parser": "^3.0.0",
"@vuepress/plugin-back-to-top": "^1.5.0",
"@vuepress/plugin-google-analytics": "^1.5.0",
"babel-eslint": "^10.1.0",
"commitizen": "^4.1.2",
"conventional-changelog-cli": "^2.0.34",
Expand All @@ -126,6 +139,7 @@
"semantic-release-docker": "^2.2.0",
"should": "^13.2.3",
"ts-node-dev": "^1.0.0-pre.44",
"validate-commit-msg": "^2.14.0"
"validate-commit-msg": "^2.14.0",
"vuepress": "^1.5.0"
}
}
17 changes: 13 additions & 4 deletions src/app.ts
@@ -1,17 +1,20 @@
import path = require('path')
import fs = require('fs-extra')
import Koa = require('koa')
import Router = require('koa-router')
// import Logger = require('koa-logger')
import bodyParser = require('koa-bodyparser')
// import favicon = require('koa-favicon')
// import mount from 'koa-mount'
import cors = require('@koa/cors')
import serve from 'koa-static'
import cacheControl from 'koa-cache-control'
// import favicon = require('koa-favicon')
// import Logger = require('koa-logger')
// import mount from 'koa-mount'
import {
responseFormat, responseTime, timeout, catchError, limiter,
appLogger, cache, requestTransform,
} from './middleware'
import routes from './routes'
import { ROOT_URL, CACHE } from './config'
import { ROOT_URL, CACHE, STATIC_MAX_AGE } from './config'

const app = new Koa()
const router = new Router()
Expand All @@ -25,6 +28,12 @@ app.use(timeout)
app.use(bodyParser())
app.use(limiter)
app.use(cors())
if (fs.pathExistsSync(path.join(__dirname, '../public'))) {
// 文档并非必须,如果有则挂载
app.use(serve(path.join(__dirname, '../public'), {
maxAge: STATIC_MAX_AGE * 1000,
}))
}
app.use(cacheControl({
maxAge: CACHE.CACHE_AGE,
}))
Expand Down
2 changes: 2 additions & 0 deletions src/config/index.ts
Expand Up @@ -37,6 +37,8 @@ export const LIMIT = {
LIMIT_MAX: Number(env.LIMIT_MAX || 30),
}

export const STATIC_MAX_AGE = Number(env.STATIC_MAX_AGE || 0)

/**
* 内存缓存
*/
Expand Down
10 changes: 4 additions & 6 deletions src/middleware/cache.ts
Expand Up @@ -4,7 +4,7 @@ import Redis = require('ioredis')
import { md5 } from '@/utils'
import { KoaCache } from '@/types'
import { CACHE, REDIS_CONFIG, IS_DEBUG } from '@/config'
export const globalCache: KoaCache = {
const globalCache: KoaCache = {
async get(key) {
throw new Error('globalCache.get not implemented.')
},
Expand Down Expand Up @@ -74,13 +74,14 @@ if (CACHE.CACHE_TYPE === CACHE.CACHE_TYPE_MEMORY) {
* @param {Koa.Next} next
*/
export async function cache(ctx: Koa.Context, next: Koa.Next) {
ctx.cache = globalCache
// 需要缓存的方法
const methods = ['GET', 'HEAD']
const hash = md5(ctx.url)
// 是否禁用缓存
const nocache = ctx.params?.nocache || ctx.query?.nocache || ctx.request.body?.nocache || IS_DEBUG
if (methods.includes(ctx.method) && !nocache) {
let value = await globalCache.get(hash)
let value = await ctx.cache.get(hash)
if (value) {
try {
value = JSON.parse(value)
Expand All @@ -90,14 +91,11 @@ export async function cache(ctx: Koa.Context, next: Koa.Next) {
ctx.set({
'X-Koa-Cache': 'true',
})
// ctx.cacheControl = {
// maxAge: CACHE.CACHE_AGE,
// }
return
}
}
await next()
if (methods.includes(ctx.method) && !nocache && ctx.body) {
await globalCache.set(hash, ctx.body)
await ctx.cache.set(hash, ctx.body)
}
}
2 changes: 1 addition & 1 deletion src/middleware/catchError.ts
Expand Up @@ -13,7 +13,7 @@ export async function catchError(ctx: Koa.Context, next: Koa.Next) {
message = e.message
statusCode = e.statusCode
} else if (e instanceof Error) {
// 开发阶段打印堆栈信息,否则打印message
// 开发阶段打印堆栈信息,否则打印 message
message = IS_DEBUG ? e.stack : e.message
}
if (statusCode >= 500) {
Expand Down
4 changes: 3 additions & 1 deletion src/middleware/response.ts
@@ -1,4 +1,5 @@
import Koa = require('koa')
import mime from 'mime'
import status from 'http-status'
import _ from 'lodash'
import { Log } from '@/utils'
Expand All @@ -15,7 +16,8 @@ import { RssChannel } from '@/models'
*/
export async function responseFormat(ctx: Koa.Context, next: Koa.Next) {
await next()
if (ctx.body) {

if (mime.getExtension(ctx.type) === 'json' && ctx.body) { // 格式化错误和json
const statusCode = ctx.status || 500
const error = ctx.status >= 400 ? status[ctx.status] : undefined
const message = ctx.body?.message
Expand Down
2 changes: 1 addition & 1 deletion src/types/index.d.ts
Expand Up @@ -5,6 +5,6 @@ declare interface KoaCache {
}
declare module 'koa' {
interface Context {
cache?: Cache
cache?: KoaCache
}
}
8 changes: 4 additions & 4 deletions src/utils/helper.ts
@@ -1,4 +1,4 @@
import moment = require('moment')
import moment from 'moment'
import colors = require('colors')
import { IS_DEBUG } from '@/config'
/**
Expand Down Expand Up @@ -39,14 +39,14 @@ export function printTime(str: any) {
export const Log = {
log(msg: any) {
if (IS_DEBUG) {
console.log(`${colors.yellow(timeFormat(Date.now(), 'HH:mm:ss.SSS'))} : ${colors.green(typeof msg === 'string' ? msg : JSON.stringify(msg))}`)
console.log(`${colors.yellow(timeFormat(Date.now(), 'HH:mm:ss.SSS'))}: ${colors.green(typeof msg === 'string' ? msg : JSON.stringify(msg))}`)
}
// else {
// accessLogger.log(msg)
// }
},
info(msg: any) {
console.info(`${colors.yellow(timeFormat(Date.now(), 'HH:mm:ss.SSS'))} : ${colors.green(typeof msg === 'string' ? msg : JSON.stringify(msg))}`)
console.info(`${colors.yellow(timeFormat(Date.now(), 'HH:mm:ss.SSS'))}: ${colors.green(typeof msg === 'string' ? msg : JSON.stringify(msg))}`)
},
/**
* 打印错误到控制台
Expand All @@ -56,6 +56,6 @@ export const Log = {
* @param {*} msg
*/
error(msg: any) {
console.error(`${colors.yellow(timeFormat(Date.now(), 'HH:mm:ss.SSS'))} :`, colors.red(msg))
console.error(`${colors.yellow(timeFormat(Date.now(), 'HH:mm:ss.SSS'))}:`, colors.red(msg))
},
}

0 comments on commit 9cadc17

Please sign in to comment.