一、需求

使用 nodejs 实现一个根据路由加载显示 html 页面功能的 server 端。

要求能够加载 html 页面,能够加载 html 中的图片,如果无法访问,则返回 404 文件。

只是加载 html 内容,不干其他任何事情。
纯测试玩具 不具有任何实际应用意义。

二、实现

主要实现三个部分:

  • 一个 server 端
  • 一个 路由配置(可以说配置,但是糅杂了一些文件读取方法)
  • 一些模板 html

文件目录:

1.jpg

1、 routes 的实现

文件目录:[routes/index.js]

这个文件中我没有将文件读写分离出来,只是为了方便而已。
文件读写使用了异步读取的方式,因此在回调中处理 res.write() 的时候,是需要传入 res 的,否则无法使用。

所有非规定的路由均走 other 规则,但是如果是图片,则走的规则和其他的是不一样的,非图片,则走 404 规则,也就是说,如果是 css/js 文件,则也可以这么搞,从而能够涉猎 css/js 等多种文件

const fs = require('fs');
const path = require('path');

// 模板文件存储的基本文件夹
const basePath = {
  html:path.resolve(__dirname,'../views/'),
  img:path.resolve(__dirname,'../static/images/')
};

// 路由的配置项目 
const routes ={
  '/index' : (res)=>{
    readFileView('./index.html',res);
  },
  '/login' : (res)=>{
    readFileView('./login.html',res);
  },
  '/register' : (res)=>{
    readFileView('./register.html',res);
  },
  'other' : (pathname,res)=>{
    // 判断如果是图片,则走不一样的图片读取规则
    const imgFlag = pathname.split('.')[pathname.split('.').length -1 ].match(/(jpg|jpeg|png|bmp|svg)/) ? true : false;
    if(imgFlag){
      readFileView(pathname,res,true);
    }else{
      readFileView('./notfound.html',res);
    }
  }
};


/**
 * @name readFileView
 * @description 根据文件名 读取 html 模板内容并且显示在网页中 
 * @param {String} filePath 
 * @param {Response} res (通过 server 传入的 res)
 * @param {Boolean} img 如果是  true 则返回 image/jpeg
 */
function readFileView(filePath,res,img=false){
  // 图片的读取规则和html文件的读取目录是不一样的
  distPath = img ? path.resolve(basePath.img,filePath.substr(1,filePath.length)) : path.resolve(basePath.html,filePath);
  fs.readFile(distPath,(err,data)=>{
    if(err){
      console.error(err);
      res.end();
    }else{
      // 图片需要更新设置 content-type
      if(img) res.setHeader('Content-Type','image/jpeg');
      res.write(data);
      res.end();
    }
  });
}

module.exports = routes;

2、模板文件

文件目录:[views/xxx.html]

所有的 html 均存放在这里

 3、server 端

文件目录:[server.js]

实际上 switch 也应该分装成方法然后分离出去。

需要注意的是,我这里除了规定的route之外,其他的请求均走 other 的 route 规则。

const http = require('http');
const url = require('url');

const routes = require('./routes');

http.createServer((req, res)=>{

  // 获取 pathname
  const pathname = url.parse(req.url).pathname;
  // 去掉 /favicon.ico
  if(pathname === '/favicon.ico') return false;
  
  console.log(`[访问]:${pathname}`);
  
  res.setHeader('Content-Type','text/html;charset=utf-8');
  
  // 应当将这个分离开才对
  switch(pathname){
    case '/index' || '/' : routes[pathname](res);break;
    case '/login' : routes[pathname](res);break;
    case '/register' : routes[pathname](res);break;
    default : routes['other'](pathname,res);break;
  }

}).listen(8080);

console.log('[Server at] : http://127.0.0.1:8080');

4. 给出 notfound.html 的文件内容

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,user-scalable=no, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>首页</title>
</head>
<body>
  <ul>
    <li><a href="/index">首页</a></li>
    <li><a href="/login">登录</a></li>
    <li><a href="/register">注册</a></li>
    <li><a href="./notfound.jpg" target="_blank">只跳转图片</a></li>
    <li><a href="/asdasd">未注册的路由</a></li>
  </ul>
  <hr>
  <img src="./notfound.jpg" alt="" width="200px;">
  <h1>404 Not Found</h1>
</body>
</html>

三、效果

2.jpg