网站首页 > 技术文章 正文
需求
Git 全量打包和增量打包参考:全量打包和增量打包前端项目
打包后会在项目根目录下生成 zip 压缩包。
上线需要将此压缩包文件上传到服务器。
这里通过代码实现自动上传功能
思路
- 在服务器端实现文件上传的功能。这里使用 koa 实现
- 文件上传需要 post 方式提交,请求内容格式为 Content-Type: multipart/form-data
- 可以使用 koa-multer 实现文件上传。这里使用 koa-body 实现
- 客户端发送 http 请求使用 curl。可以到curl for windows下载安装包安装
- 命令格式:curl -F "type=myproject/web" -F "user=sch" -F "action=upload" -F file=@"./project_202011061049.zip" http://192.168.1.10:3000/upload
- 服务器端根据 user 和 action 参数判断是否是有效请求。有效请求的话,文件放到服务器的 type 参数目录下
- 需要先递归判断目录是否存在,如果不存在则新建
- path 里面有个 parse() 方法,可以获取父级目录
// 在 Linux 中
path.parse('/目录1/目录2/文件.txt');
// 返回:
// {
// root: '/',
// dir: '/目录1/目录2',
// base: '文件.txt',
// ext: '.txt',
// name: '文件'
// }
// 在 Windows 中
path.parse('C:\\目录1\\目录2\\文件.txt');
// 返回:
// {
// root: 'C:\\',
// dir: 'C:\\目录1\\目录2',
// base: '文件.txt',
// ext: '.txt',
// name: '文件'
// }
实现
服务器端实现
初始化项目
- 新建项目目录 server
- 打开 cmd,切换到项目目录下,输入 npm init -y 生成 package.json 文件
- 在项目目录下新建 public 目录,用来存放静态文件
- 在项目目录下新建 src 目录,用来存放源代码
- 在 src 目录下新建 server.js 文件,作为服务器启动文件
使用ES6、7语法
安装 babel,使用 import、 export、 async await 等语法
- 安装:npm install @babel/core @babel/cli @babel/preset-env @babel/register @babel/node @babel/plugin-transform-runtime
- 在根目录下新建 .babelrc 文件
{
"presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-runtime"]
]
}
- 在 src 目录下新建 index.js
require('@babel/register')
require('./server')
自动重启
开发过程中,修改代码之后,需要重启才能看到最新的效果
这里使用 nodemon 来自动重启
- 安装:npm i nodemon --save-dev
代码实现
- 安装 koa 相关插件:npm i koa koa-router koa-body koa-static koa2-cors
- 修改 src/server.js 文件
import path from 'path'
import Koa from 'koa'
import cors from 'koa2-cors'
import koaStatic from 'koa-static'
import koaBody from 'koa-body'
import Router from 'koa-router'
import apiRouter from './router'
const app = new Koa()
const router = new Router()
// cors - 这个例子其实用不到
app.use(cors({
origin: function(ctx) {
return '*'
},
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
maxAge: 5,
credentials: true,
allowMethods: ['GET', 'POST', 'DELETE'],
allowHeaders: ['Content-Type', 'Authorization', 'Accept'],
}))
// 静态文件
app.use(koaStatic(path.join(__dirname, '../public')))
// post请求数据接收。
// 配置 formidable.uploadDir 后文件会自动上传到配置的目录
// 不配置formidable.uploadDir 文件会自动上传到系统的 tmp 目录
app.use(koaBody({
multipart: true, // 支持文件上传
// formidable: {
// uploadDir: path.join(__dirname, 'public/'),
// keepExtensions: true, // 保存图片的扩展名
// }
}))
router.use('', apiRouter.routes())
app.use(router.routes()).use(router.allowedMethods())
app.listen(3000, () => {
console.log('server is started at part: 3000')
})
- 在 src 目录下新建 router.js 文件
import Router from 'koa-router'
const router = new Router()
router.post('/upload', async (ctx) => {
const { type, user, action } = ctx.request.body
const file = ctx.request.files && ctx.request.files.file
console.log(type, user, action)
console.log(file)
ctx.body = {
code: 0
}
})
export default router
- 我们需要先根据传过来的参数 type 判断对应目录是否存在,如果不存在新建目录
import fs from 'fs'
import path from 'path'
/**
* 同步递归创建路径
*
* @param {string} dir 处理的路径
* @param {function} cb 回调函数
*/
const $mkdir = function(dir, cb) {
const pathinfo = path.parse(dir)
if (!fs.existsSync(pathinfo.dir)) {
$mkdir(pathinfo.dir, function() {
fs.mkdirSync(pathinfo.dir)
})
}
cb && cb()
}
$mkdir(path.join(__dirname, 'demo/test/123/'))
- 这里我们需要异步方案。在 src 目录下新建 utils 目录
- 在 src/utils 目录下新建 mkdir.js 文件
import fs from 'fs'
import path from 'path'
// 异步自动创建路径
class Mkdir {
// 开始处理一个路径
async start(dir) {
// 获取路径
const pathStat = await this.getStat(dir)
if (pathStat) {
// 路径存在:是目录返回true,不是目录返回false
return pathStat.isDirectory()
}
// 路径不存在,需要判断上一级路径是否存在。只有上一层路径存在,才能执行新建目录操作
const pathinfo = path.parse(dir)
// 递归处理上一级路径
const status = await this.start(pathinfo.dir)
// 上一级路径处理失败,返回失败
if (!status) {
return false
}
// 上一级路径有了,才能再创建当前级目录
const mkdirStatus = await this.mkdir(dir)
// 返回当前级目录创建成功与否
return mkdirStatus
}
// 获取路径Stat
getStat(loadpath) {
return new Promise((resolve, reject) => {
fs.stat(loadpath, (err, stats) => {
if (err) {
resolve(false)
} else {
resolve(stats)
}
})
})
}
// 创建目录
mkdir(dir) {
return new Promise((resolve, reject) => {
fs.mkdir(dir, (err) => {
if (err) {
console.log(err)
resolve(false)
} else {
resolve(true)
}
})
})
}
}
const mkdir = new Mkdir()
export default (dir) => mkdir.start(dir)
- 修改 src/router.js 文件
import path from 'path'
import fs from 'fs'
import Router from 'koa-router'
import mkdir from './utils/mkdir'
const router = new Router()
router.post('/upload', async (ctx) => {
const { type, user, action } = ctx.request.body
const file = ctx.request.files && ctx.request.files.file
if (user != 'sch' || action != 'upload') {
ctx.throw(401, 'parameter error')
}
// 创建可读流
const reader = fs.createReadStream(file.path)
// const dirPath = path.join(__dirname, '../public/', type)
// 用上面的写法也可以
// 这里换一种写法:process.cwd() - 表示命令运行时所在的目录
const dirPath = path.join(process.cwd(), 'public/', type)
const mkdirStatus = await mkdir(dirPath)
if (!mkdirStatus) {
ctx.throw(404, 'make directory error')
}
const uploadPath = dirPath + `/${file.name}`
//创建可写流
const upStream = fs.createWriteStream(uploadPath)
// 可读流通过管道写入可写流
reader.pipe(upStream)
ctx.body = {
code: 0,
msg: 'success',
data: {
url: `http://${ctx.headers.host}/${type}/${file.name}`
}
}
})
export default router
添加命令
开发环境:执行 npm run server 命令。使用 nodemon 自动重启,入口文件为 src/index.js 文件
线上环境:先执行 npm run build 命令打包,将 ES6/7 等语法转换成 ES5,然后再执行 npm run start 启动项目。不需要使用 nodemon 自动重启,入口文件为 dist/server.js
- 修改 package.json 文件,添加 scripts
{
// ...
"scripts": {
"server": "nodemon ./src/index.js",
"build": "babel src --out-dir dist",
"start": "node ./dist/server.js",
// ...
},
// ...
}
- 代码放在服务器上面启动。可以使用 Nginx 配置一个代理,比如代理到 8080 端口等。
客户端实现
- 到curl for windows下载安装包安装
- 打开 cmd,输入 curl --version 测试是否安装成功
- 修改 post-push-full.bat 和 post-push.bat 文件,在打包完成后添加打包命令
:: ...
IF "%current_branch%"=="master" (
:: ...
:: http://192.168.1.10:3000/upload 是服务器端提供的上传地址
:: 如果使用代理的话可能就变成了 http://192.168.1.10:8080/upload
curl -F "type=myproject/web" -F "user=sch" -F "action=upload" -F file=@"%output%" http://192.168.1.10:3000/upload
pause
)
猜你喜欢
- 2025-05-25 前端怎么打包成小程序和APP圈子系统开发平台圈子系统源码
- 2024-09-24 五种可视化方案分析webpack打包性能瓶颈
- 2024-09-24 我在实际前端项目中遇到的坑(Electron)
- 2024-09-24 vue-cli 大型项目打包优化
- 2024-09-24 vscode运行打包后的npm前端dist文件
- 2024-09-24 关于vue-cli 3配置打包优化要点
- 2024-09-24 一起来学习打包工具 rollup.js 入门,也许你会需要
- 2024-09-24 运行时 Bun 又添王炸,支持 Bun宏!
- 2024-09-24 探寻webpack打包vue项目特别慢问题
- 2024-09-24 将前端框架vue打包后部署到node服务中,本文采用egg框架演示
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)