Koa进阶

作者: hellomyshadow | 来源:发表于2019-04-21 10:41 被阅读0次

Koa脚手架

1. 全局安装脚手架:npm install koa-generator -g
2. 创建项目:koa demo01  --> cd demo01  --> npm install
3. 运行项目:npm start
4. 脚手架创建的项目已经实现了路由的模块化,即项目的模块化。

路由模块化

1. 与Express的路由模块化类似,把不同功能的路由拆分到不同的js文件中,然后再暴露路由对象;
2. 假设项目包含首页(index)、后台管理(admin),配置模板引擎art-template的目录为views
    1. 在根目录下创建routes目录,用于存放路由模块,项目入口为app.js
    2. 创建routes/index.js,routes/admin.js
3. 在index.js中配置index模块的路由,index是根路由的模块
    let router = require('koa-router')();
    router.use(async(ctx, next)=>{ ----> index模块的应用级中间件,在index路由之前匹配
        ......
        await next(); ----> 继续向下匹配index路由
        ......
    })
    router.get('/', async(ctx)=>{
        await ctx.render('index'); -->渲染模板:views/index.html
    })
    router.get('case', async(ctx)=>{  ------> 对于根路由的模块,其子路由不能再加'/'
        await ctx.render('index/case'); -->渲染模板:views/index/case.html
    })
    module.exports = router; ---> 暴露index模块的路由对象
    1. 注意:与Express不同,Koa的根目录匹配已经默认加了'/',其子路由的开头不能再加'/'
4. 在admin.js中配置admin模块的路由
    let router = require('koa-router')();
    router.use(async(ctx, next)=>{ ----> admin模块的应用级中间件,在admin路由之前匹配
        ......
        await next(); ----> 继续向下匹配admin路由
        ......
    })
    router.get('/', async(ctx)=>{
        await ctx.render('admin');
    })
    router.get('/user', async(ctx)=>{
        await ctx.render(admin/user');
    })
    module.exports = router;
5. 在app.js中启用index模块和admin模块的路由
    let router = require('koa-router')();
    let index = require('./routes/index');
    let admin = require('./routes/admin');
    router.use('/', index.routes());  -----> 启用根路由的index模块
    router.use('/admin', admin.routes()); ---> admin模块的路由
    app.use(router.routes()).use(router.allowedMethods);
6. 子路由:在admin路由中继续启用子路由
    1. 创建routes/admin/user.js,配置路由
    let router = require('koa-router')();
    router.get('/', async(ctx)=>{
        await ctx.render('admin/user'); -->渲染模板:views/admin/user.html
    })
    router.get('/add', async(ctx)=>{
        await ctx.render('admin/user/add'); ->渲染模板:views/admin/user/add.html
    })
    module.exports = router;
    2. 在admin.js中引入user.js,并启用user路由
    let user = require('./admin/user');
    router.use('/user', user.routes());
7. router路由的写法不止一种,比如把路由写在对应的路由文件中
    1. app.js:router.use(admin.routes());
    2. admin.js:let Router = require('koa-router');
    let router = new Router({ prefix: '/admin' })

更多补充

1. nodeJs生成验证码:svgCaptcha,支持express和koa
2. 页面自动刷新/跳转
    1. 页面3s后自动刷新:<meta http-equiv="refresh" content="3" />
    2. 3s后页面自动转到指定网址
    <meta http-equiv="refresh" content="3; url=http://www.baidu.com/" />
    3. 登录失败之后,加载错误页面error.html,5s后自动转回登录页
    router.use(async(ctx, next)=>{
        ctx.state.HOST = 'http://'+ctx.request.header.host;  -->设置域名的全局变量
        await next();
    })
    router.post('doLogin', async(ctx)=>{
        if(登录失败){
            await ctx.render('login/error', { url: ctx.state.HOST+'/login' })
        }
    })
    error.html:<meta http-equiv="refresh" content="5; url={{url}}" />
3. art-template自定义日期管道/过滤器
    1. 格式化日期的插件:npm install silly-datetime --save
    2. let sd = require('silly-datetime');
    render(app, {
        root: path.join(__dirname, 'views'),
        extname: '.html',
        debug: process.env.NODE_ENV !== 'production',
        dateFormat: dateFormat=function(value){ -----> 扩展模板里的方法
            return sd.format(new Date(value), 'YYYY-MM-DD HH:mm');
        }
    })
    3. 在art模板中使用过滤器,格式化传递的变量time:<div>{{time | dateFormat}}</div>
4. koa-jsonp:ajax请求返回JSON的中间件,npm install koa-jsonp --save
    1. let jsonp = require('koa-jsonp');  ---> 同时支持处理JSON和jsonp
    2. 配置jsonp中间件:app.use(jsonp());
    3. 一个简单的JSON数据接口:
    router.get('/getMsg', async (ctx) => {
        ctx.body = { message: "请求的数据信息", success: true }
    })
    4. 使用浏览器测试接口:
    http://localhost:3000/getMsg  ---> 如果返回JSON格式的数据,则表示此接口支持JSON
    http://localhost:3000/getMsg?callback=xxx  ---> 测试接口是否支持jsonp
5. ctx.request.headers['referer']:获取上一页的地址
    1. 用全局变量记录上一页的地址
    ctx.state.prevPage = ctx.request.headers['referer'];
    2. 返回上一页:ctx.redirect(ctx.state.prevPage);

文件上传

<form action="{{HOST}}/doUpload" method="post" enctype="multipart/form-data">
    <input type="file" id="pic" name="pic" />
</form>
1. koa-multer:用于处理 multipart/form-data 类型的表单数据,主要用于上传文件;
2. koa-multer基于 multer 模块:npm i koa-multer --save
    let multer = require('koa-multer');
    let storage = multer.diskStorage({
        destination: function(req, file, cb) {
            cb(null, 'upload/pic'); ---> 配置上传文件的目录:当前目录下的upload/pic
        },
        filename: function(req, file, cb) {
            let extname = (file.originalname).split('.');  -->从文件名中切割出后缀名
            cb(null, Date.now()+'.'+extname[extname.length-1]); -->对文件重命名
        }
    });
    let upload = multer({storage: storage});
3. 处理上传文件
    router.post('/doUpload', upload.single('pic'), async (ctx)=>{
        let filename = ctx.req.file.filename;  ---> 上传的文件名
        let form = ctx.req.body; ---> form表单的其他数据
    })
4. upload.single('pic'):pic与<input type="file" name="pic" />的name保持一致;
5. koa-multer也支持多个文件上传,在github上的multer模块中有更多配置信息;
6. koa-body:用于取代 koa-bodyparser 和 koa-multer

路由鉴权

1. koa-jwt:用于路由鉴权、token验证

富文本编辑器

1. ueditor:百度的轻量级、可定制富文本web编辑器,开源基于MIT协议,允许自由使用和修改代码
2. ueditor官方虽然没有提供NodeJs版本,但官方推荐的第三方插件里有nodeJs版本;
    1. 第三方插件直接支持express,不支持koa2
    2. 支持koa2的ueditor插件:npm i koa2-ueditor --save
3. ueditor的基本配置
    1. 在github下载koa2-ueditor的demo,拷贝public/ueditor,粘贴到自己项目的public目录
    2. 在模板中的<head>标签中引入ueditor目录下的静态文件
    <script type="text/javascript" src="/ueditor/ueditor.config.js">
    <script type="text/javascript" src="/ueditor/ueditor.all.min.js">
    <script type="text/javascript" src="/ueditor/lang/zh-cn/zh-ch.js">
    3. 使用ueditor,取代<textarea>的位置
    <script id="editor1" type="text/plain" style="width:800px;height:300px;">
    4. 在<body>标签之后实例化富文本编辑器:
    <script type="text/javascript">
        let ue = UE.getEditor('editor1');
    </script>
    5. 富文本编辑器中的内容最终生成的是带有style样式的html标签,是一个html字符串。
    <form ...>
        <script type="text/plain" id="editor1" name="content" style="...">
    </form>
    router.post('/doUpload', upload.single('pic'), async (ctx)=>{
        let content = ctx.req.body.content; ---> form表单的富文本编辑框中的数据
    })
4. 配置ueditor的图片上传
    const ueditor = require('koa2-ueditor');
    router.all('/editor/controller', ueditor(['public', {
        imageAllowFiles: ['.png', '.jpg', '.jpeg'],
        imagePathFormat: '/upload/ueditor/image/{yyyy}{mm}{dd}/{filename}'
    }]));
    1. '/editor/controller':统一上传的地址,对应ueditor/ueditor.config.js中的配置
    serverUrl: "/editor/controller"  ---> 根据router.all()的实际路由进行修改
    http://localhost:3000/editor/controller  --> 完整的上传地址URI
    2. 'public':上传图片的保存目录,根目录/public/upload/ueditor/image/当前日期/图片名
5. 自定义ueditor编辑框:修改配置文件ueditor/ueditor.config.js
    1. 配置自动增长高度:autoHeightEnabled: false  --> 编辑框的内容过长时自动出现滚动条
    2. 自定义工具栏:修改toolbars节点
6. 为编辑框设置默认内容
    <script type="text/javascript">
        let ue = UE.getEditor('editor1');
        ue.addListener('ready', ()=>{  ----> 监听ueditor准备完成
            ue.setContent(`{{@list.content}}`);  --> art-template模板接收参数的方式
        })  ---> list.content是上一次富文本编辑框中的内容,保存在数据库中
    </script>

SEO优化

1. SEO优化:也称为搜索引擎优化,目的是让搜索引擎优先搜索到自家网站,并展示给用户;
2. 设置网站的必要信息:标题、关键字、描述
    1. 网站标题:<title>标题内容</title>,网站标题变化不能过于频繁,否则百度会认为是作弊;
    2. 网站关键字:<meta name="Keywords" content="关键字内容" />
    3. 网站描述:<meta name="Description" content="描述内容" />
3. 图片<img>必须使用 alt 属性
4. html标签的合理使用,语义化,符合W3C标准
    1. 尤其是 h 系列标签的合理使用,其中,<h1>标签的权重最高,一个页面建议只出现一次;
    2. <h1>标签的内容建议和<title>的内容相同。
5. 内链、外链的合理使用,如友情链接就属于外链,因为搜索引擎会根据内链和外链继续搜索网站;
6. 网站的内容尽量都是原创的;
7. 合理使用长尾关键词:比如,相对与"koa2教程","koa2视频教程"就属于长尾关键词.

API接口

1. NodeJs的异步环境特性,让它最适合写API接口,非常善于处理大数据、高并发;
2. 比如一个返回JSON数据的简单接口
    let jsonp = require('koa-jsonp');
    app.use(jsonp());
    router.get('/getList', async (ctx)=>{
        let result = await (从数据库中获取数据);
        ctx.body = { data: result }
    })

跨域问题

1. 在AJAX请求后台接口数据时,浏览器的同源策略会引起跨域安全问题;
    1. 接口的协议、域名、端口号必须与当前Web应用所处的协议、域名、端口号保持一致;
    2. 比如,访问当前网页的地址为 http://localhost:3000/index,那么,网页中的AJAX请求的
    接口地址必须是http://localhost:3000/xxxx
    3. 协议、域名、端口号三者有任何一个出现不一致,就会导致跨域问题。
2. JSONP的原理:利用<script>可以跨域的特性
    1. 在本地写一个回调函数,在远程执行这个函数,并把远程数据传到本地
    http://localhost:3000/api/getList?callback=xxx ---> xxx被当作远程执行的函数
    2. JSONP跨域请求的前提:服务器必须支持JSONP;第三方koa-jsonp模块同时支持JSONP请求。
3. 除了JSONP实现跨域请求,还可以让后台设置允许跨域:npm i koa2-cors --save
    1. NodeJs后台设置允许跨域请求
    let cors = require('koa2-cors');
    app.use(cors());
    2. AJAX可以直接跨域请求接口,但由此导致的安全性问题,则通过token验证解决。

RESTful API

1. 当前Web应用的趋势就是前后端分离,为了让前端设备与后端更好地通信,出现了很多API结构;
2. RESTful API是目前比较成熟的一套互联网应用程序的API设计理念;
3. 一个优秀的RESTful API所考虑的方面:
    1. 协议:建议使用更安全的https协议
    2. 域名:尽量部署在专属域名下面,如https://a.bcd.com,https://api.bcd.com
    3. 考虑到接口的升级,应该将API的版本号放在URI中
    https://a.bcd.com/api1/list,https://a.bcd.com/api2/list
    https://a1.bcd.com,https://a2.bcd.com
    4. 路径:在RESTful架构中,每个URI代表一种资源,所以URI中使用与数据库表名相对应的名词
    5. 使用合理的HTTP请求方法
4. HTTP的7种请求方法:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS,常用的只有前4种
    1. GET:select,从服务器取出一项或多项资源
    2. POST:create,在服务器新建一个资源
    3. PUT:update,在服务器更新/修改资源
    router.put('/edit', async (ctx)=>{  ---> koa2可以直接识别不同的请求方法
        //修改数据、并返回修改后的完整数据
    })
    4. DELETE:从服务器删除资源
    router.delete('/del', async (ctx)=>{ ---> 响应 delete 方式的请求
        //删除数据
    })
5. 以vueJs的axios为例,axios提供了7种不同的HTTP请求方法。

发布线上

1. 购买域名和服务器:万网(阿里收购)、西部数码...
2. 域名备案:新购买的域名不能直接被解析到服务器,需要在管理局登记域名信息(20个工作日左右)
    1. 每个出售域名的网站上,会有域名备案的流程说明和入口;
    2. 当然,还可以出钱到就近的外包公司备案。
3. 域名解析:让域名和服务器IP地址相关联,在购买域名的网站上配置即可;
    1. DNS服务器:负责域名解析的服务器,返回真实的服务器IP地址;
    2. ping 域名:查看当前域名所指向的真实服务器IP,如果ping失败,可能此域名设置了拒绝。
    ping www.baidu.com
4. nginx:负责转发与负载均衡,从而可以在一台服务器上运行N个nodeJs应用程序。

nginx配置

1. 在当前服务器上有2个nodeJs应用程序,端口号分别为8001、8002
2. 下载nginx应用包,解压,改名为nginx
3. 配置nginx/conf/nginx.conf
    1. 配置http节点:转发规则
    http {
        upstream backaa {
            server 127.0.0.1:8001; ---> 服务器上的nodeJs应用程序的端口号
        }
        upstream backbb {
            server 127.0.0.1:8002;
        }
    }
    2. 配置http节点下的server节点:反向代理/负载均衡
    server {
        listen       80;
        server_name  aa.v123.com;  ---> 域名

        #location / {
        #   root   html;
        #   index  index.html index.htm;
        #}

        location / {
            # 设置主机头和客户端的真实地址,以便服务器获取客户端的真实IP
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #禁用缓存
            proxy_buffering off;
            #反向代理的地址
            proxy_pass http://backaa;  ---> 与upstream相对应
        }
        ......
    }
    server {
        listen       8080;
        server_name  bb.v123.com;  ---> 域名
        
        #location / {
        #   root   html;
        #   index  index.html index.htm;
        #}

        location / {
            # 设置主机头和客户端的真实地址,以便服务器获取客户端的真实IP
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #禁用缓存
            proxy_buffering off;
            #反向代理的地址
            proxy_pass http://backbb;  ---> 与upstream相对应
        }
        ......
    }
5. 启动nginx(windows系统):双击运行nginx/nginx.exe
6. 启动nodeJs应用程序
7. 访问:http://aa.v123.com,http://bb.v123.com

相关文章

  • Koa进阶

    Koa脚手架 路由模块化 更多补充 文件上传 路由鉴权 富文本编辑器 SEO优化 API接口 跨域问题 RESTf...

  • Koa学习资料

    Koa2进阶学习笔记下一代web框架Koajs的在线课程Koa实战深入浅出 Koa Koajs 中文文档和资料

  • 看云文档

    《nginx 入门到进阶的教程》《一起学 koa》《网络爬虫系列》《翻译漫谈——怎样翻译更地道》《The Linu...

  • koa2 用到的中间件

    koa-router //koa路由 koa-bodyparser //post 获取值 koa-stat...

  • koa-router处理URL

    koa-router处理URL koa-router使用的结构const Koa = require('koa')...

  • koa 自学入门

    const Koa = require('koa');const route = require('koa-rou...

  • 初见 Koa 2

    koa 和 koa 2 最大的不同是koa 2 支持 async/await。koa 通过结合 generato...

  • trello01:后端搭建

    开发依赖: koa : 后端的主框架。 koa-router:基于Koa的路由。 koa-static-cache...

  • Koa2教程(常用中间件篇)

    目录一、koa-bodyparser二、koa-router三、koa-views + ejs四、koa-stat...

  • koa2设置跨域

    npm install --save koa2-corsvar Koa = require('koa');var ...

网友评论

      本文标题:Koa进阶

      本文链接:https://www.haomeiwen.com/subject/bpudgqtx.html