├── .gitignore
├── README.md
├── index.html
├── package.json
├── server.js
└── static
├── index.css
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # nodejs设置缓存demo
2 |
3 | ## 开始
4 | ```
5 | npm install
6 | npm start
7 | ```
8 |
9 | ## 博客
10 | [前端缓存最佳实践](https://juejin.im/post/5c136bd16fb9a049d37efc47)
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Hello World
8 |
9 |
10 |
11 | Hello World
12 |
13 |
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cache-control-nodejs-demo",
3 | "version": "1.0.0",
4 | "description": "cache-control demo for nodejs",
5 | "main": "server.js",
6 | "scripts": {
7 | "start": "node server.js"
8 | },
9 | "author": "",
10 | "license": "MIT",
11 | "dependencies": {
12 | "etag": "^1.8.1",
13 | "fresh": "^0.5.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const fs = require('fs');
3 | const url = require('url');
4 | const path = require('path');
5 | const etag = require('etag');
6 | const fresh = require('fresh');
7 |
8 | const server = http.createServer(function (req, res) {
9 | let filePath, isHtml, isFresh;
10 | const pathname = url.parse(req.url, true).pathname;
11 | //根据请求路径取文件绝对路径
12 | if (pathname === '/') {
13 | filePath = path.join(__dirname, '/index.html');
14 | isHtml = true;
15 | } else {
16 | filePath = path.join(__dirname, 'static', pathname);
17 | isHtml = false;
18 | }
19 |
20 | // 读取文件描述信息,用于计算etag及设置Last-Modified
21 | fs.stat(filePath, function (err, stat) {
22 | if (err) {
23 | res.writeHead(404, 'not found');
24 | res.end('404 Not Found
');
25 | } else {
26 | if (isHtml) {
27 | // html文件使用协商缓存
28 | const lastModified = stat.mtime.toUTCString();
29 | const fileEtag = etag(stat);
30 | res.setHeader('Cache-Control', 'public, max-age=0');
31 | res.setHeader('Last-Modified', lastModified);
32 | res.setHeader('ETag', fileEtag);
33 |
34 | // 根据请求头判断缓存是否是最新的
35 | isFresh = fresh(req.headers, {
36 | 'etag': fileEtag,
37 | 'last-modified': lastModified
38 | });
39 | } else {
40 | // 其他静态资源使用强缓存
41 | res.setHeader('Cache-Control', 'public, max-age=3600');
42 | }
43 |
44 | fs.readFile(filePath, 'utf-8', function (err, fileContent) {
45 | if (err) {
46 | res.writeHead(404, 'not found');
47 | res.end('404 Not Found
');
48 | } else {
49 | if (isHtml && isFresh) {
50 | //如果缓存是最新的 则返回304状态码
51 | //由于其他资源使用了强缓存 所以不会出现304
52 | res.writeHead(304, 'Not Modified');
53 | } else {
54 | res.write(fileContent, 'utf-8');
55 | }
56 |
57 | res.end();
58 | }
59 | });
60 | }
61 | });
62 | });
63 | server.listen(8080);
64 | console.log('server is running on http://localhost:8080/');
--------------------------------------------------------------------------------
/static/index.css:
--------------------------------------------------------------------------------
1 | h1{
2 | color: #F00;
3 | }
--------------------------------------------------------------------------------
/static/index.js:
--------------------------------------------------------------------------------
1 | console.log('hello world');
--------------------------------------------------------------------------------