当前位置: 首页 > news >正文

入职第二天:使用koa搭建node server是种怎样的体验

今天是我入职第二天,leader跟我说,昨天配置好了服务端渲染的文件,今天就先研究研究如何使用koa来搭建一个node server吧!

按照惯例,我去koa官网查了一下什么是koa,结果官网很简单的一句话介绍:koa--基于node.js平台的下一代web开发框架。

个人感觉koa官方文档对于前端小白来说,写的不是很友好,建议上手之前先看看阮一峰的koa框架教程和廖雪峰写的关于koa入门文章。

然后引入项目第一步,安装koa:

npm i koa -S

安装完之后,首先在项目根目录下新建一个server文件夹,然后在此文件夹下新建一个server.js文件,然后在里面引入koa:

const Koa = require('koa')
const app = new Koa()
const isDev = process.env.NODE_ENV === 'development'

这里为什么要声明isDev呢?因为服务端渲染是分开发环境和生产环境两种不同的情况。

然后我们继续在server.js里面先写一个中间件来记录所有的请求和抓取的错误,这样可以很好的了解到在服务端渲染的过程中是否出现了一些错误,并及时排查掉错误。

先撸为敬:

app.use(async (ctx, next) => {
 try {
   console.log(`request with path ${ctx.path}`)
   await next()
 } catch (err) {
   console.log(err)
   ctx.status = 500
   if (isDev) {
     ctx.body = err.message
   } else {
     ctx.body = 'please try again later'
   }
 }
})

简单解释一下:在函数前面加一个async,就代表异步处理函数,而参数next表示执行下一个 异步处理的函数。在try循环体内,console打印出请求的路径。如果是isDev为true的情况,可以直接将错误信息写到body里面,这样就可以在页面上直接看到错误信息。如果不是开发环境,可以写一个友善的提醒文字,例如:“please try again later”。

这就是最简单的一个koa中间件,用来记录所有的请求及出现的错误,并且返回一个错误信息。

接下来,聊一聊如何处理服务端渲染。

在处理服务端渲染之前,首先要在terminal里面安装一下koa-router:

npm i koa-router -S

这是koa提供的一个路由的工具。然后在server文件夹下面新建一个routers文件夹,紧接着在里面新建两个文件,一个是dev-ssr.js,另一个是ssr.js。前者是处理开发时服务端渲染的情况,后者是处理正式环境下的情况。

在dev-ssr.js文件中,首先要引入koa-router:

const Router = require('koa-router')

在这里,还需要使用到两个工具,需要安装下:

npm i axios -S
npm i memory-fs -D

在node端发送请求的axios,当然也可以在浏览器端发送请求。在安装的时候记住后面跟的是-S,因为在业务代码中可以用到。

而memory-fs只有在开发的时候才会用到,所以后面跟的是-D。可能有童鞋要问了,这个memory-fs是用来干嘛的?别急,闰土给大家截一张官网图片看看便一目了然了:

图片描述

大意是:一个简单的内存文件系统。将数据保存在JavaScript对象中。

然后,话不多说,先把这两个工具引入进来:

const axios = require('axios')
const MemoryFS = require('memory-fs')

紧接着,再来引入两个工具:

const webpack = require('webpack')
const VueServerRenderer = require('vue-server-renderer')

因为要在node开发环境中打包代码,并且需要服务端渲染。

接下来,要引入serverConfig,就是入职第一天写的那个配置文件webpack.config.server.js:

const serverConfig = require('../../build/webpack.config.server')

然后,如何能在node开发环境中让webpack跑起来呢?

答案是通过serverCompiler:

const serverCompiler = webpack(serverConfig)

然后去new一个mfs实例:

const mfs = new MemoryFS()
serverCompiler.outputFileSystem = mfs

这样就指定了webpack的输出目录在MemoryFS里面。

有了这些配置之后,再去声明一个bundle:

let bundle

用来记录webpack每次打包生成的新的文件。

serverCompiler.watch({}, (err, stats) => {
 if (err) throw err
 stats = stats.toJson()
 stats.erros.forEach(err => console.log(err))
 stats.hasWarnings.forEach(warn => console.warn(err))

 const bundlePath = path.join(
   serverConfig.output.path,
   'vue-ssr-server-bundle.json'
 )
 bundle = JSON.parse(mfs.readFileSync(bundlePath, 'utf-8'))
})

这里使用watch()的好处是:跟使用webpack-dev-server一样,在client目录下每次修改一个文件,它都会重新执行一次打包,然后就可以拿到新的文件了。

serverCompiler.watch()的第一个参数是空对象,第二个参数是一个回调。如果有err直接抛出。

然后stats这块我感觉有点晦涩难懂,leader告诉我说,先照着做,然后有空再去看webpack的文档。

接下来就可以读取生成的bundle文件了,拼接读取文件的路径,设置文件名字,并且制定编码为utf-8,最后通过JSON.parse()将字符串转成JSON。

执行完以上步骤之后,就可以将内容返回给HTML了。

图片描述

在服务端渲染期间,使用ejs模板引擎生成HTML。通过VueServerRenderer的createBundleRenderer()方法帮助生成一个可以直接调用renderer的函数。在这里面接收几个参数,第一个是inject,设置为false,这样它就不会执行其他的注入的操作了。第二个是clientManifest,它会自动生成一个带有script标签的js文件引用的字符串,这样可以直接添加到ejs的内容里面。

最后,dev-ssr.js的完整代码如下:

const Router = require('koa-router')
const axios = require('axios')
const path = require('path')
const fs = require('fs')
const MemoryFS = require('memory-fs')
const webpack = require('webpack')
const VueServerRenderer = require('vue-server-renderer')

const serverConfig = require('../../build/webpack.config.server')

const serverCompiler = webpack(serverConfig)
const mfs = new MemoryFS()
serverCompiler.outputFileSystem = mfs

let bundle
serverCompiler.watch({}, (err, stats) => {
 if (err) throw err
 stats = stats.toJson()
 stats.erros.forEach(err => console.log(err))
 stats.hasWarnings.forEach(warn => console.warn(err))

 const bundlePath = path.join(
   serverConfig.output.path,
   'vue-ssr-server-bundle.json'
 )
 bundle = JSON.parse(mfs.readFileSync(bundlePath, 'utf-8'))
})

const handleSSR = async (ctx) => {
 if (bundle) {
   ctx.body = 'wait a moment...'
   return
 }

 const clientManifestResp = await axios.get(
   'http://127.0.0.1:8080/vue-ssr-client-manifest.json'
 )

 const clientManifest = clientManifestResp.data

 const template = fs.readFileSync(
   path.join(__dirname, '../server.template.ejs')
 )

 const renderer = VueServerRenderer
   .createBundleRenderer(bundle, {
     inject: false,
     clientManifest
   })
}

写在最后

这次使用koa搭建node server的体验只是聊到了renderer这一步,后面我会继续聊聊如何把bundle渲染成实际的HTML内容,并把它添加到template里面。最新的文章都会第一时间更新在我的公众号<闰土大叔>里面,欢迎关注。

图片描述

相关文章:

  • 用JS获取地址栏参数的方法
  • QA 应该更新的测试工具
  • 智慧社区APP引领2016生活服务新趋势
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • 苹果希望政府提供iPhone解锁技术愿望落空?
  • hive理论
  • 最大化混合云收益
  • Spring请求参数校验
  • 十年之后大数据的价值主张
  • NetCore偶尔有用篇:NetCore项目添加MIME
  • amazeui学习笔记--css(常用组件15)--CSS动画Animation
  • 诺基亚推出 第一个“百岁级”路由器
  • 解决idea中maven拉不下jar包问题
  • MySQL---笔记之视图的使用详解
  • 大数据联合实验室落地成都青羊
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 【EOS】Cleos基础
  • idea + plantuml 画流程图
  • js
  • PAT A1017 优先队列
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 聊聊sentinel的DegradeSlot
  • 深度学习入门:10门免费线上课程推荐
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • ###C语言程序设计-----C语言学习(3)#
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (全注解开发)学习Spring-MVC的第三天
  • (算法)求1到1亿间的质数或素数
  • (转)母版页和相对路径
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • *** 2003
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net web项目 调用webService
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET 依赖注入和配置系统
  • .NET/C# 使窗口永不获得焦点
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .NET6 开发一个检查某些状态持续多长时间的类
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @Pointcut 使用
  • [ vulhub漏洞复现篇 ] Celery <4.0 Redis未授权访问+Pickle反序列化利用
  • [ 蓝桥杯Web真题 ]-布局切换
  • [Android View] 可绘制形状 (Shape Xml)
  • [Android] Android ActivityManager
  • [android] 请求码和结果码的作用
  • [android] 天气app布局练习
  • [Android]创建TabBar
  • [AR Foundation] 人脸检测的流程
  • [BZOJ1089][SCOI2003]严格n元树(递推+高精度)
  • [C# 网络编程系列]专题六:UDP编程
  • [C#]C# winform部署yolov8目标检测的openvino模型