zoukankan      html  css  js  c++  java
  • 使用 Koa 搭建前端服务

    环境准备

    1. node 环境

    Koa 依赖 node v7.6.0 或 ES2015及更高版本和 async 方法支持,我本地的node环境为 v14.4.0

    image

    快速开始

    使用koa启动本地静态资源主要需要解决两个问题,一个是使用history路由时,刷新页面使之能正常进入页面,另一个就是请求能正常代理到目标服务,这里如果为了方便可以直接使用 koa 脚手架,也可以自己手动搭建。下面分别介绍一下这两种方法的使用。

    从零搭建

    ① 初始化 package.json

    $ npm init
    

    输入该命令后,一路回车,会生成一个package.json文件

    ② 安装 koa
    这里可以在当前目录安装,也可进行以全局安装

    // 在当前目录安装
    $ npm install koa -S
    
    // 或全局安装
    $ npm install koa-generator -g
    

    ③ 新建app.js

    const Koa = require('koa')   
    const app = new Koa()   
    
    app.use(async ctx => {
      ctx.body = 'Hello World';
    });
    app.listen(9999, () => {
      console.log('服务已启动,请访问:http://127.0.0.1:9999 或 localhost:9999');
    }) 
    
    //打开终端
    $ node app.js
    

    终端如下,记住之后每次添加依赖后都需要重启服务:

    image

    此时在浏览器中访问该地址后,可看到打印出的 “Hello World” 文本,这时一个简单的服务就搭建起来了~

    此时服务是启动了,但是浏览器怎么能打印某个文件的内容呢? 首先新建 dist 文件夹,然后建几个文件index.html、todo.html、404.html、img.png

    
    //app.js 
    const Koa = require('koa')   
    const app = new Koa()   
    
    //要涉及读文件的功能,所以引入node 的 fs 文件系统
    const fs = require('fs')
    
    /**
     * 用Promise封装异步读取文件方法
     * @param  {string} page html文件名称
     * @return {promise}      
     */
    function render( page ) {
      return new Promise(( resolve, reject ) => {
        let distUrl = `./dist/${page}`
        fs.readFile(distUrl, "binary", ( err, data ) => {
          if ( err ) {
            reject( err )
          } else {
            resolve( data )
          }
        })
      })
    }
    
    /**
     * 根据URL获取HTML内容
     * @param  {string} url koa2上下文的url,ctx.url
     * @return {string}     获取HTML文件内容
     */
    async function route( url ) {
      let dist = '404.html'
      switch ( url ) {
        case '/': 
        case '/index':
          dist = 'index.html'
          break
        case '/todo':
          dist = 'todo.html'
          break
        case '/404':
          dist = '404.html'
          break
        default:
          break
      }
      let html = await render( dist )
      return html
    }
    
    app.use(async ctx => {
      let url = ctx.request.url
      let html = await route( url )
      ctx.body = html
    });
    app.listen(9999, () => {
      console.log('服务已启动,请访问:http://127.0.0.1:9999 或 localhost:9999');
    }) 
    
    
    
    // dist/index.html 文件
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>index</title>
    </head>
    <body>
       <h1>koa2 demo index page</h1>
        <p>this is a index page</p>
        <ul>
          <li><a href="/">/</a></li>
          <li><a href="/index">/index</a></li>
          <li><a href="/todo">/todo</a></li>
          <li><a href="/404">/404</a></li>
        </ul>
        <img src="https://i.loli.net/2021/01/04/UMwA2d1QtKu4cWl.png" alt="" width="100" height="100">
        <img src="./img.png" alt="" width="100" height="100">
    </body>
    </html>
    

    此时访问 http://127.0.0.1:9999http://127.0.0.1:9999/index,http://127.0.0.1:9999/todo 都可以进入对应页面
    效果:

    image

    现在可以访问文件内容了,但是本地静态资源却不能访问,这时 koa-static 就可以解决这个问题

    $ npm install koa-static -S
    
    //改装 app.js ,将所有文件作为静态资源访问且指向入口 ./dist/index.html上 
    const Koa = require('koa')    
    const app = new Koa()
    
    app.use(require("koa-static")(__dirname + "/dist"));
    
    app.listen(9999, () => {
      console.log('服务已启动,请访问:http://127.0.0.1:9999 或 localhost:9999');
    }) 
    

    重启后文件访问到啦,此时所有文件都作为静态资源访问,所以进入子页面时需要带全文件名称,否则是访问不到的呢~

    image

    有没有发现,如果依靠 ctx.request.url 手动处理路由,将会写很多处理代码,这时候就需要对应的路由的中间件对路由进行控制,这里介绍一个比较好用的路由中间件 koa-router (由于目标项目中使用的是单页面应用,所以这里暂不多介绍)

    $ npm install koa-router@7 -S
    

    此时可以上手我们的项目了,把已写好的项目打包完成并替换 dist 文件
    可以看到已经访问到项目主页了~

    image

    此时发现一个问题,当再次刷新的时候,竟然404!这是因为vue-router使用history模式返回index.html,仅能通过入口文件去加载其子路由。

    而koa2的一个中间件,专治SPA应用程序的history模式路由问题,那就是 koa2-connect-history-api-fallback

    $ npm install koa2-connect-history-api-fallback -S
    
    //app.js
    const Koa = require('koa')    
    const { historyApiFallback } = require('koa2-connect-history-api-fallback');
    
    const app = new Koa()
    
    app.use(historyApiFallback());
    app.use(require("koa-static")(__dirname + "/dist"));
    
    app.listen(9999, () => {
      console.log('服务已启动,请访问:http://127.0.0.1:9999 或 localhost:9999');
    }) 
    

    继续测试,发现不管什么路由都可以正常访问到啦~

    这时候又遇到问题了,接口请求全部 404,那是因为请求走的都是http://127.0.0.1:9999,那404是必然的啦,那如何把请求代理转发到其他服务器呢? http-proxy-middleware 可以解决这个问题。

    $ npm install http-proxy-middleware -S
    $ npm i koa2-connect -S
    
     //app.js
    const Koa = require('koa')   
    const Router = require('koa-router')  
    const { historyApiFallback } = require('koa2-connect-history-api-fallback');
    const { createProxyMiddleware } = require('http-proxy-middleware')
    const c2k = require('koa2-connect')
    
    const app = new Koa()
    
    app.use(historyApiFallback());
    app.use(require("koa-static")(__dirname + "/dist"));
    
    var router = new Router()
    var target = 'https://222.222.222.222:8080' // 要代理的目标地址,vue项目写 vue.config.js 里的 target 地址
    router.get(
      '*',
      c2k(
        createProxyMiddleware({
          target,
          changeOrigin: true,
          ws: true
        })
      )
    )
    app.use(router.routes())
    
    app.listen(9999, () => {
      console.log('服务已启动,请访问:http://127.0.0.1:9999 或 localhost:9999');
    }) 
    

    这时发现请求已经代理成功了,GET 请求的 HTTP 码返回了200,但是 POST、PUT 等其它请求方式依旧 404,那是因为咱仅给GET方法添加了target 地址,再将各种方式都补齐:

    const Koa = require('koa') 
    const Router = require('koa-router') 
    const { createProxyMiddleware } = require('http-proxy-middleware')
    const { historyApiFallback } = require('koa2-connect-history-api-fallback');
    const c2k = require('koa2-connect')
    
    const app = new Koa() 
    
    app.use(historyApiFallback());
    app.use(require("koa-static")(__dirname + "/dist"));
    
    var router = new Router()
    var target = 'https://abc.com' // 修改成你要代理的目标地址,vue项目写 vue.config.js 里的 target 地址
    
    //项目一共使用5种请求方式: get post put patch delete  /* 'head','connect','options','trace','patch' */
    let method = ['get', 'post', 'put', 'patch','delete']
    method.forEach(item => {
      router[item](
        '*',
        c2k(
          createProxyMiddleware({
            target,
            changeOrigin: true,
            ws: true
          })
        )
      )
    })
    
    app.use(router.routes()) 
    app.listen(9999) 
    

    image

    使用 Koa 搭建前端服务大功告成!如果要用 Koa 脚手架搭建的话更加简单,执行以下命令、再安装上述依赖即可。

    $ koa koaServer
    

    总结一下,项目依赖一共包括以下几个:

    "dependencies": {
        "http-proxy-middleware": "^1.0.6",
        "koa": "^2.13.0",
        "koa-router": "^7.4.0",
        "koa-static": "^5.0.0",
        "koa2-connect": "^1.0.2",
        "koa2-connect-history-api-fallback": "^0.1.3"
      }
    

    tips:

    1. 如果习惯使用 npm run serve 或者 yarn serve 启动项目的话,可以为 package.json 文件的 scripts 属性添加一条:"serve":"node app.js" 即可
      "scripts": {
          "serve":"node app.js",
          "test": "echo "Error: no test specified" && exit 1"
      },
      
    2. koa2与koa1的最大区别是koa2实现异步是通过async/awaite,koa1实现异步是通过generator/yield,而express实现异步是通过回调函数的方式。
  • 相关阅读:
    HDOJ 2095 find your present (2)
    HDOJ 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
    九度 1337 寻找最长合法括号序列
    九度 1357 疯狂地Jobdu序列
    HDOJ 1280 前m大的数
    九度 1343 城际公路网
    九度 1347 孤岛连通工程
    HDOJ 2151 Worm
    九度 1342 寻找最长合法括号序列II
    九度 1346 会员积分排序
  • 原文地址:https://www.cnblogs.com/geekfeier/p/14238426.html
Copyright © 2011-2022 走看看