在前端开发中,使用缓存技术可以大大提高网站的性能和用户体验。但是,对于一些小规模的网站或应用,使用像 Redis 这样的外部缓存服务器可能过于复杂和昂贵,这时候我们可以选择使用内存作为本地缓存。
在这篇文章中,我将介绍如何使用 Koa2 框架,实现一个利用内存的本地缓存服务。在本文中,我将说明如何从零开始构建这个服务,包括使用 Koa2 来创建一个简单的 Web 应用程序,实现基本的缓存逻辑,并进行简单的测试。本文的内容详细且有深度和学习以及指导意义。
准备工作
在开始之前,您需要安装 Node.js(v8.0.0+)和 NPM(v6.0.0+)。我也将使用 Koa2 和 Jest,所以需要安装这些模块:
# 安装 Koa2 npm install koa koa-body-parser # 安装 Jest(测) npm install --save-dev jest
我还将使用 Babel 来编译代码以确保它在所有环境中都能运行。安装 Babel 及其插件:
npm install --save-dev @babel/core @babel/cli @babel/preset-env
手动搭建 Koa2 项目
我们从创建一个新的 Node.js 项目开始。创建一个名为 koa-cache
的文件夹并在其中初始化项目:
mkdir koa-cache cd koa-cache npm init -y
然后安装必要的依赖项:
npm install koa koa-body-parser --save npm install --save-dev @babel/core @babel/cli @babel/preset-env jest
创建一个 src
目录,并在其中创建 index.js
文件。这是我们的主要应用程序逻辑代码。
mkdir src && cd src touch index.js
在 index.js
中,我们将使用 Koa2 来创建一个简单的 Web 服务器。它将监听在端口 3000
上,并在我们的应用程序中添加一个 /get/:key
和 /set
的路由。当收到 /get/:key
请求时,服务器将在内存中查找指定的缓存 key
,并返回该键对应的值(如果有)。当收到 /set
请求时,服务器将在内存中设置指定的缓存键值对。
// javascriptcn.com 代码示例 import Koa from 'koa'; import bodyParser from 'koa-body-parser'; const app = new Koa(); app.use(bodyParser()); const cache = {}; app.use(async (ctx, next) => { ctx.set('Access-Control-Allow-Origin', '*'); ctx.set('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE'); ctx.set('Access-Control-Allow-Headers', 'Content-Type'); await next(); }); app.use(async (ctx, next) => { const { method, url } = ctx.request; console.log(`${method} ${url}`); await next(); }); app.use(async (ctx) => { const { method, path, query, body } = ctx.request; switch (path) { case '/get/:key': { ctx.body = cache[query.key]; break; } case '/set': { const { key, value } = body; cache[key] = value; ctx.body = 'OK'; break; } default: { ctx.throw(404); break; } } }); const PORT = process.env.PORT || 3000; app.listen(PORT).on('listening', () => { console.log(`Server running on port ${PORT}`); });
现在我们可以使用以下命令启动服务器:
npx babel-node src/index.js
服务器将开始监听端口 3000
,现在您可以尝试使用 curl 或 Postman 测试 /get
和 /set
路由。例如:
# 设置一个名为 "foo" 的缓存项 curl --header "Content-Type: application/json" \ --request POST \ --data '{"key":"foo","value":"bar"}' \ http://localhost:3000/set # 尝试获取名为 "foo" 的缓存项的值 curl http://localhost:3000/get/foo
测试代码的实现
首先,在项目的根目录下创建一个名为 __tests__
的目录。在该目录中,创建一个名为 index.test.js
的文件。在此文件中,我们将使用 Jest 进行测试。
mkdir __tests__ cd __tests__ touch index.test.js
在 index.test.js
中,我们将编写几个简单的测试用例,以确保我们的服务器代码处理缓存逻辑是否正确。
// javascriptcn.com 代码示例 import axios from 'axios'; const SERVER_URL = 'http://localhost:3000'; describe('/get/:key', () => { it('should return cached value for the given key', async () => { const key = 'test-key'; const expectedValue = 'test-value'; await axios.post(`${SERVER_URL}/set`, { key, value: expectedValue }); const res = await axios.get(`${SERVER_URL}/get/${key}`); expect(res.data).toEqual(expectedValue); }); it('should return undefined if the key is not found', async () => { const key = 'non-existent-key'; const res = await axios.get(`${SERVER_URL}/get/${key}`); expect(res.data).toBeUndefined(); }); }); describe('/set', () => { it('should set a new value for the given key', async () => { const key = 'new-key'; const value = 'new-value'; const res = await axios.post(`${SERVER_URL}/set`, { key, value }); expect(res.data).toEqual('OK'); const getRes = await axios.get(`${SERVER_URL}/get/${key}`); expect(getRes.data).toEqual(value); }); });
在这个测试代码中,我们使用 Jest 的断言库 expect
来测试我们的服务器代码是否按预期工作。
构建代码
现在,我们已经创建了一些测试,让我们将所有代码编译成可在生产环境中运行的 ES6 代码。
在项目的根目录下创建一个名为 babel.config.js
的文件,用于配置 Babel 编译过程。
touch babel.config.js
在 babel.config.js
中,我们将使用 @babel/preset-env 来编译代码。
// javascriptcn.com 代码示例 module.exports = { presets: [ [ '@babel/preset-env', { targets: { node: 'current', }, }, ], ], };
我们还需要在 package.json
文件中添加一个脚本来编译代码。这个脚本将把源代码写入到一个新的 dist
目录中。
"scripts": { "build": "rm -rf dist && npx babel src --out-dir dist", "start": "npm run build && node dist/index.js", "test": "jest --verbose", }
现在运行 npm run build
,它将编译所有代码并将其放在 dist/
目录下。
总结
在本文中,我们使用 Koa2 编写了一些缓存逻辑,并通过实现 /get/:key
和 /set
路由创建了一个缓存服务器。然后,我们使用 Jest 编写了几个简单的测试用例,以确保我们的代码按预期工作。最后,我们使用 Babel 将所有代码编译成 ES6 代码。
这个应用程序只是一个例子,并不是一个完整的解决方案。使用类似于内存缓存的方案只适用于小规模应用程序。如果您的应用程序需要持久化和高可用性,那么 Redis 或 Memcached 等外部缓存解决方案可能是正确的选择。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653040957d4982a6eb1aeced