本节我们将分享如何引入 koa-static 提供静态资源的处理。
外部样式和图片显示的问题
我们基于上一节的index.html文件继续进行,大家都知道在HTML中有三种使用CSS的方式,分别是:
- 内联样式,在开始标签内使用style属性,请看我们在index.html文件中的h1标签示例(修改后页面内容标题变成红色):
<h1 style="color: red">学习真快乐!</h1>
- 内部样式,在head部分使用style标签,写入css样式表,示例如下(修改后页面内容标题的背景色变为蓝色):
<style>
h1 {
background-color: blue
}
</style>
- 外部样式,在head部分使用link标签引入外部写入css样式表的文件,示例如下:
<link href="index.css" rel="stylesheet">
同时,在项目根目录下创建index.css文件,并写入如下样式表:
body {
background-color: green
}
修改后我们刷新页面,发现页面背景色没有变成绿色, 不仅如此,我们在h1标签后面引入一张图片:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>学习koa</title>
<link href="index.css" rel="stylesheet">
<style>
h1 {
background-color: blue
}
</style>
</head>
<body>
<h1>学习真快乐!</h1>
<img src="skills.jpg" alt="前端技能图">
</body>
</html>
我们发现,不仅引入的外部样式表不起作用,图片也同样无法正常显示。这是为什么呢?
当然,我们不能光想,而是要去分析,我们打开chrome浏览器的开发者模式(英文输入法下按 F12或右击选择检查模式),在右侧找到 network并点击查看 该页面的有关请求,如果没有在刷新一下,我们可以看到浏览器为了渲染页面发了三次请求:
- 第一个请求的是'/‘, 服务器给我们返回了index.html文件;
- 第二个请求的是'/index.css', 但返回内容还是index.html文件;
- 第三个请求的是'/skills.jpg', 但返回内容还是index.html文件;
这是为什么呢?我们先看看当下 index.js文件中内容处理的部分:
app.use(ctx => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('index.html');
});
可以看到,无论我们请求的是什么内容,因为 我们的静态服务器 没有对 css 和 图片 类型 进行处理,返回的都是index.html文件。如何解决呢?
方式一:自己硬干
app.use(ctx => {
const url = ctx.url == '/' ? '/index.html' : ctx.url
const fileType = path.extname( url ).slice(1);
if (fileType ==='html') {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream('index.html');
} else if (fileType ==='css') {
ctx.response.type = 'css';
ctx.response.body = fs.createReadStream('index.css');
} else if (fileType ==='jpg') {
ctx.response.type = 'image/jpg';
ctx.response.body = fs.createReadStream('skills.jpg');
} else {
ctx.response.body = '文件不存在';
}
});
可以看到,外部样式和图片都正常了,但是其他文件类型或图片类型的处理呢?如果我们想再添加一张png的图片,又会不正常,还得需要去更新代码。
显然,在实际工作中,如果所有功能都需要自己去实现的话,效率会很低,不仅会延期,还会有很多未知的bug。有没有更好的方式呢?
方式二:拿来主义
有经验的老司机通常会选择一些靠谱的依赖库去实现我们常用的功能,对于基于koa开发的web应用,我们一般使用koa-static:
- 安装依赖库:
npm install koa-static
- 在index.js引入依赖库:
const KoaStatic = require('koa-static');
- 使用koastatic, 我们在index.js注掉方式一的代码,在其后添加如下代码:
app.use(KoaStatic('./'));
重启服务器上,我们看到一切都正常,外部样式和图片都能正常展示,而且我们显示任何类型的图片,基本都没问题。和方式一相比,1 行 代码 vs n行代码,没有对比就没有伤害。
多重样式的优先级
高兴之余,细心的朋友是否也有这样的疑虑呢?当同一个 样式表属性 在三个地方都定义的时候,浏览该如何显示呢?比如:
- 我们在head部分的内部样式表也设置h1的color属性,比如设为白色;
- 同时在外部样式文件index.css文件中也设置h1的color属性,比如设为黄色;
修改后,刷新页面,我们发现依然还是红色,但是:
- 我们把h1标签内的style属性删除后,显示为白色;
- 再把head部分的内部样式表中h1的color属性删除,则为黄色;
- 最后再删除外部样式文件index.css文件中h1的color属性,则为黑色。
于是我们知道发现了多重样式的规律了,他们的优先级如下:
内联样式)Inline style > (内部样式)Internal style sheet >(外部样式)External style sheet > 浏览器默认样式
依赖库中的定时炸弹
无忌妈妈告诉我们,漂亮的妹妹不可轻信。同样,使用依赖库时,用时爽,bug发生了,就先定时炸弹,会让你爽歪歪。。。
拿来主义是有代价的,方式 2 一行代码就解决了我们的静态资源处理,但你是否有同样的疑惑?为何我们的请求url中并不包含index.html文件,浏览器请求服务器的根路径就返回了该文件,并正常展示了呢?
请看下节的源码分析,本节到此结束。