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实现异步是通过回调函数的方式。
  • 相关阅读:
    Python2 升级Python3
    'builtin_function_or_method' object has no attribute 'translate'
    antd-mobile的DatePicker分钟精度半小时
    Windows10远程报错:由于CredSSP加密Oracle修正
    Nginx配置
    MySQL之索引优化
    Ubuntu下删除VMware的方法
    控制窗体的显示和隐藏
    os模块
    树莓派 使用3.5耳机口输出音频
  • 原文地址:https://www.cnblogs.com/geekfeier/p/14238426.html
Copyright © 2011-2022 走看看