序言
新公司是一个初创团队,研发团队的人较少,自然要把精力更多地投放到业务上。所以我们团队内部决定使用 serverless 的函数运算作为服务的部署方案。这样我们就可以减少购买云服务器和运维的成本,就可以更多的把精力留在业务上。至于技术栈,我会去使用 nuxt.js 与 nest.js 这一套 node 全栈方案。最后,本篇文章只介绍如何部署到云厂商上,这里我用的是阿里云为例。(主要是我的域名备案在这里,所以只好用这个了。)。至于数据库如:mongoDB部分,以后会补上,这个并不难,主要是在部署 nest.js 项目有坑(官方不支持直接部署,需要手动适配)。
1,需要的准备
1,你需要有一个备案的域名。(真的很重要!!!)
如果是部署一些网页还好,可以用临时域名,但是一旦部署服务端,就会被强制添加一个 header 名为 Content-Disposition: attachment ,如果你不用你自定义的域名,你的一切请求将会以一个文件的形式下载(体验很差)。
2,为每一个服务创建一个 access key 。
如图:进去 serverless 服务首页配置就好。
最后:需要在项目的根目录创建一个 .env 文件,里面配上一些身份验证信息。以便后期一键部署。如以下代码所示
3,下载 funcraft (项目部署工具)
首先我要说的是,阿里云官方提供的网页版上传真的不好用,我上传了好多次,都无法成功。(唯有官方的代码才能成功,牛掰!)
所以老实用 funcraft 上传吧
npm i @alicloud/fun -g
2,部署 nuxt.js 项目(很简单,官方适配了 nuxt 项目,所以很简单)
1,先 build 项目
2,再运行 fun deploy -y 一键部署项目。
3,部署 nest.js 项目(由于官方不支持 fun 一键部署,需要自行修改项目,暴露 handler 函数)
1,首先安装依赖 @webserverless/fc-express
npm i @webserverless/fc-express
原先项目的 main.ts 是这样的
import { NestFactory, Reflector } from "@nestjs/core";
import { AppModule } from "./app.module";
import { ResponseInterceptor } from "./intercepter/response.interceptor";
import { AllExceptionsFilter } from "./filter/exception.filter";
import { ValidationPipe, ClassSerializerInterceptor } from "@nestjs/common";
// swagger 相关
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { ValidationPipe as TypeValidation } from "./pipe/global.pipe";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix("api");
// 第一个先做类型验证,第二个给多余属性过滤掉(但是需要有验证的注解)
app.useGlobalPipes(new TypeValidation(), new ValidationPipe({whitelist: true}));
app.useGlobalInterceptors(new ResponseInterceptor(), new ClassSerializerInterceptor(app.get(Reflector)));
app.useGlobalFilters(new AllExceptionsFilter());
// swagger 相关配置
const docOptions = new DocumentBuilder()
.setTitle("Nest practise")
.setDescription("Nest.js 练习用 api")
.setVersion("1.0")
.addSecurity("token", { type: "apiKey", name: "token", in: "header" })
.build();
const document = SwaggerModule.createDocument(app, docOptions);
SwaggerModule.setup("api-docs", app, document);
await app.listen(3000);
}
bootstrap();
改装后的代码是这样的(在main.ts的目录下创建index.ts。工作量并不大)
import { NestFactory, Reflector } from "@nestjs/core";
import { ExpressAdapter } from "@nestjs/platform-express";
import { Server } from "@webserverless/fc-express";
import express from "express";
import { AppModule } from "./app.module";
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { ValidationPipe as TypeValidation } from "./pipe/global.pipe";
import { ResponseInterceptor } from "./intercepter/response.interceptor";
import { AllExceptionsFilter } from "./filter/exception.filter";
import { ValidationPipe, ClassSerializerInterceptor } from "@nestjs/common";
const Express = express();
let p = (async () => {
const adapter = new ExpressAdapter(Express);
const app = await NestFactory.create(AppModule, adapter);
app.setGlobalPrefix("api");
// 第一个先做类型验证,第二个给多余属性过滤掉(但是需要有验证的注解)
app.useGlobalPipes(new TypeValidation(), new ValidationPipe({whitelist: true}));
app.useGlobalInterceptors(new ResponseInterceptor(), new ClassSerializerInterceptor(app.get(Reflector)));
app.useGlobalFilters(new AllExceptionsFilter());
// swagger 相关配置
const docOptions = new DocumentBuilder()
.setTitle("Nest practise")
.setDescription("Nest.js 练习用 api")
.setVersion("1.0")
.addSecurity("token", { type: "apiKey", name: "token", in: "header" })
.build();
const document = SwaggerModule.createDocument(app, docOptions);
SwaggerModule.setup("api-docs", app, document);
app.enableCors();
await app.init();
})();
Express.use(function(req, res, next) {
p.then(() => next());
});
const server = new Server(Express);
module.exports.handler = function(req, res, context) {
server.httpProxy(req, res, context);
};
然后抄下 template.yml 的代码
ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Resources:
# nest-practise 是项目的名称,可以自己去修改。
nest-practise:
Type: 'Aliyun::Serverless::Service'
Properties:
Description: ''
NasConfig: Auto
nest-practise:
Type: 'Aliyun::Serverless::Function'
Properties:
Handler: dist/index.handler
Runtime: nodejs12
CodeUri: ./
Timeout: 60
EnvironmentVariables:
NODE_PATH: '/mnt/auto/node_modules:/usr/local/lib/node_modules'
Events:
httpTrigger:
Type: HTTP
Properties:
AuthType: ANONYMOUS
Methods:
- GET
- POST
- PUT
- DELETE
最后:运行 fun deploy 即可
配置自定义域名
看图配置即可
注意:路径匹配需要注意一下是否考虑子项目就行了。
云 MongoDB 的使用
TBD
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!