mirror of
https://github.com/palxiao/poster-design.git
synced 2025-07-15 16:02:19 +08:00
fix: node dependent installation
This commit is contained in:
parent
36b737e590
commit
7bd376b660
@ -1,4 +1,3 @@
|
||||
|
||||
## Node截图服务
|
||||
|
||||
目录结构比较简单,主要就实现了三个接口,其中 `api/screenshots` 即是项目中所使用到的图片生成接口,在真实生产项目中可以把该服务单独部署,于内网调用,这样利于做一些鉴权之类的处理。
|
||||
@ -7,7 +6,17 @@
|
||||
|
||||
### 安装依赖
|
||||
|
||||
`npm install` 或 `yarn`
|
||||
`npm install`
|
||||
|
||||
安装依赖时可能会出现这个报错提示:
|
||||
|
||||
```
|
||||
ERROR: Failed to set up Chromium xxx! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.
|
||||
```
|
||||
|
||||
不用慌,这是因为 puppeteer 会自动下载 Chromium,国内会受到网络波动的影响。
|
||||
|
||||
如果跳过的话需要手动安装,比较麻烦所以并不推荐。解决方法是多尝试几次,或者更换国内的镜像源即可。
|
||||
|
||||
### 启动项目并热更新
|
||||
|
||||
@ -17,36 +26,24 @@
|
||||
|
||||
`npm run build`
|
||||
|
||||
#### 打包说明
|
||||
#### 打包部署步骤
|
||||
|
||||
直接打包可能会出现未知错误,本项目在 **webpack.config.js** 中过滤掉了依赖(打包出来的文件会非常小因为只包含项目代码),建议将 `package.json` 放到服务器上主动安装依赖来使用,具体的做法类似以下步骤:
|
||||
> 服务器环境需求:Node.js 16.18.1(版本不同则可能出现错误)、PM2(进程守护)
|
||||
|
||||
1. 将项目中的 `package-build.json` 上传到服务器中,重命名为 `package.json`
|
||||
2. 目录下执行 `yarn` 安装依赖
|
||||
3. 执行 `npm run build`
|
||||
4. 将打包的 `dist/server.js` 放在 `node_modules` 同级目录中
|
||||
5. 使用 `pm2 start server.js` 启动并守护服务
|
||||
1. 本地执行 `npm run build` 打包
|
||||
2. 打包后项目根目录 `dist/` 文件夹上传服务器,并执行 `npm install` 安装依赖
|
||||
3. 运行 `pm2 start dist/server.js` 启动并守护服务
|
||||
|
||||
### 服务器配置
|
||||
### 配置说明
|
||||
|
||||
在 Linux 环境下推荐主动安装浏览器,再给项目中的配置文件 `src/config.ts` 设置好路径:
|
||||
配置文件 `src/config.ts` 配置项说明:
|
||||
|
||||
```js
|
||||
exports.executablePath = '/opt/google/chrome-unstable/chrome'
|
||||
port // 端口号
|
||||
website // 编辑器项目的地址
|
||||
filePath // 生成图片保存的目录
|
||||
```
|
||||
|
||||
> `/opt/google` 为默认路径,一般不会变动
|
||||
|
||||
一些可能用到的 linux 命令参考(Debian GNU/Linux 9):
|
||||
|
||||
```shell
|
||||
google-chrome --version # 查看浏览器版本号
|
||||
apt-get update
|
||||
apt-get install -y google-chrome-stable // 安装最新稳定版谷歌浏览器
|
||||
```
|
||||
|
||||
> 其它系统自行搜索如何安装Chrome,推荐使用Docker部署,本项目部署[参考说明](https://xp.palxp.cn/#/articles/1689319644311?id=docker%e5%ae%b9%e5%99%a8)。
|
||||
|
||||
### 生成 API 文档
|
||||
|
||||
`build:apidoc`
|
@ -1,30 +0,0 @@
|
||||
var gulp = require('gulp');
|
||||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
var path = require('path');
|
||||
|
||||
gulp.task('clean', function() {
|
||||
return spawn('rm', ['-rf', path.join(__dirname, 'dist')])
|
||||
});
|
||||
|
||||
gulp.task('build-ts', function(){
|
||||
return exec('webpack --watch',(error,stdout,stderr)=>{
|
||||
console.log(`build ts====>stdout: ${stdout}`);
|
||||
console.log(`build ts====>stderr: ${stderr}`);
|
||||
if (error !== null) {
|
||||
console.log(`exec error: ${error}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
//自动重启服务器
|
||||
gulp.task('restart',function(){
|
||||
return exec('supervisor -w dist ./dist/main.js',(error,stdout,stderr)=>{
|
||||
console.log(`restart=====>stdout: ${stdout}`);
|
||||
console.log(`restart=====>stderr: ${stderr}`);
|
||||
if (error !== null) {
|
||||
console.log(`exec error: ${error}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('default',gulp.series('clean',gulp.parallel('build-ts','restart')));
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"name": "screenshot-node",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "./src/main",
|
||||
"scripts": {},
|
||||
"author": "ShawnPhang",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^0.24.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1",
|
||||
"fontmin": "^1.0.1",
|
||||
"form-data": "^4.0.0",
|
||||
"moment": "^2.18.1",
|
||||
"multiparty": "^4.2.3",
|
||||
"mysql": "^2.13.0",
|
||||
"qiniu": "^7.4.0",
|
||||
"puppeteer": "^10.4.0",
|
||||
"images": "3.2.3"
|
||||
},
|
||||
"devDependencies": {}
|
||||
}
|
15583
screenshot/package-lock.json
generated
15583
screenshot/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,15 +4,12 @@
|
||||
"description": "",
|
||||
"main": "./src/main",
|
||||
"scripts": {
|
||||
"dev": "ts-node-dev src/main",
|
||||
"test": "cd ./static && hs --cors",
|
||||
"dev": "cross-env NODE_ENV=development ts-node-dev src/main",
|
||||
"build": "cross-env NODE_ENV=production webpack",
|
||||
"serve": "ts-node src/main",
|
||||
"serve-test": "gulp",
|
||||
"start": "webpack --watch",
|
||||
"serverstart": "pm2 start ./dist/server.js --watch",
|
||||
"tscstart": "tsc -w",
|
||||
"serverstart2": "supervisor -w www ./www/main.js",
|
||||
"build:apidoc": "apidoc -i src/ -o _apidoc/",
|
||||
"publish": "rm -rf ./static && rm -rf ./_apidoc && sh script/publish.sh",
|
||||
"publish-fast": "git add . && git commit -m 'build: auto publish' && npm run publish"
|
||||
@ -22,27 +19,18 @@
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1",
|
||||
"gif-encoder-2": "^1.0.5",
|
||||
"images": "^3.2.4",
|
||||
"png-js": "^1.0.0",
|
||||
"puppeteer": "^10.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.6.9",
|
||||
"@types/node": "^16.18.87",
|
||||
"cross-env": "^7.0.3",
|
||||
"express-graphql": "^0.9.0",
|
||||
"graphql": "^14.5.4",
|
||||
"gulp": "^4.0.2",
|
||||
"http-server": "^14.0.0",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"supervisor": "^0.12.0",
|
||||
"ts-loader": "^6.0.4",
|
||||
"ts-node": "^8.3.0",
|
||||
"ts-node-dev": "^1.0.0-pre.40",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"typescript": "^3.5.3",
|
||||
"webpack": "^4.39.1",
|
||||
"webpack-bundle-analyzer": "^4.5.0",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack": "^5.90.3",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
},
|
||||
"apidoc": {
|
||||
|
@ -3,21 +3,36 @@
|
||||
* @Date: 2022-02-01 13:41:59
|
||||
* @Description: 配置文件
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-09-15 10:40:41
|
||||
* @LastEditTime: 2023-12-06 19:17:27
|
||||
*/
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
exports.servicePort = 7001
|
||||
// 服务器常用修改项
|
||||
const serviceComfig = {
|
||||
port: 7001, // 端口号
|
||||
website: 'https://design.palxp.cn', // 编辑器项目的地址
|
||||
filePath: '/cache/' // 生成图片保存的目录
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置服务器端的chrome浏览器位置
|
||||
* 端口号
|
||||
*/
|
||||
exports.executablePath = '/opt/google/chrome-unstable/chrome',
|
||||
exports.servicePort = serviceComfig.port
|
||||
|
||||
/**
|
||||
* 前端绘制页地址
|
||||
*/
|
||||
exports.drawLink = isDev ? 'http://localhost:3000/draw' : 'https://design.palxp.cn/draw'
|
||||
exports.drawLink = isDev ? 'http://localhost:3000/draw' : serviceComfig.website + '/draw'
|
||||
|
||||
/**
|
||||
* 图片缓存目录位置,根据实际情况调整
|
||||
*/
|
||||
exports.filePath = isDev ? process.cwd() + `/static/` : serviceComfig.filePath
|
||||
|
||||
/**
|
||||
* 配置服务器端的chrome浏览器位置
|
||||
*/
|
||||
exports.executablePath = isDev ? null : '/opt/google/chrome-unstable/chrome'
|
||||
|
||||
/**
|
||||
* 截图并发数上限
|
||||
@ -33,9 +48,3 @@ exports.upperLimit = 20
|
||||
* 多久释放浏览器驻留内存,单位:秒(多标签页版生效)
|
||||
*/
|
||||
exports.releaseTime = 300
|
||||
|
||||
/**
|
||||
* 图片缓存目录位置,根据实际情况调整
|
||||
*/
|
||||
exports.filePath = isDev ? process.cwd() + `/static/` : '/cache/'
|
||||
// exports.filePath = process.cwd() + `/static/`
|
@ -49,4 +49,4 @@ app.use(bodyParser.json())
|
||||
|
||||
app.use(router)
|
||||
|
||||
app.listen(port, () => console.log(`devServer start on port:${port}`))
|
||||
app.listen(port, () => console.log(`Screenshot Server start on port:${port}`))
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @Date: 2020-07-22 20:13:14
|
||||
* @Description:
|
||||
* @LastEditors: ShawnPhang <https://m.palxp.cn>
|
||||
* @LastEditTime: 2023-10-16 10:03:51
|
||||
* @LastEditTime: 2023-12-07 12:23:57
|
||||
*/
|
||||
const { saveScreenshot } = require('../utils/download-single.ts')
|
||||
const uuid = require('../utils/uuid.ts')
|
||||
@ -68,7 +68,6 @@ module.exports = {
|
||||
return
|
||||
}
|
||||
const targetUrl = url + id + `${tempType?'&tempType='+tempType:''}`
|
||||
// console.log(targetUrl, path, thumbPath);
|
||||
queueRun(saveScreenshot, targetUrl, { width, height, path, thumbPath, size, quality })
|
||||
.then(() => {
|
||||
res.setHeader('Content-Type', 'image/jpg')
|
||||
|
@ -22,17 +22,22 @@ const saveScreenshot = async (url: string, { path, width, height, thumbPath, siz
|
||||
// 格式化浏览器宽高
|
||||
width = Number(width).toFixed(0)
|
||||
height = Number(height).toFixed(0)
|
||||
|
||||
const puppeteerArgs = {
|
||||
old: ['–no-first-run', '--no-sandbox', '--disable-setuid-sandbox', `--window-size=${width},${height}`, '–single-process', '–disable-gpu', '–no-zygote', '–disable-dev-shm-usage'],
|
||||
new: [ '–no-first-run', '--no-sandbox', '--disable-setuid-sandbox', `--window-size=${width},${height}` ]
|
||||
}
|
||||
// 启动浏览器
|
||||
try {
|
||||
browser = await puppeteer.launch({
|
||||
headless: true, // !isDev,
|
||||
executablePath: isDev ? null : executablePath,
|
||||
executablePath,
|
||||
ignoreHTTPSErrors: true, // 忽略https安全提示
|
||||
args: ['–no-first-run', '–single-process', '–disable-gpu', '–no-zygote', '–disable-dev-shm-usage', '--no-sandbox', '--disable-setuid-sandbox', `--window-size=${width},${height}`], // 优化配置
|
||||
args: puppeteerArgs.old, // 如puppeteer版本v20+报错请尝试使用新参数
|
||||
defaultViewport: null,
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('Puppeteer启动错误!', '窗口大小:', width, height);
|
||||
console.log('Puppeteer Error: ', error, '窗口大小:', width, height);
|
||||
}
|
||||
if (!browser) {
|
||||
reject()
|
||||
|
@ -10,6 +10,7 @@
|
||||
const path = require('path')
|
||||
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
const nodeExternals = require('webpack-node-externals');
|
||||
const buildPlugin = require('./webpack.plugin.js');
|
||||
|
||||
module.exports = {
|
||||
mode: process.env.NODE_ENV,
|
||||
@ -39,4 +40,5 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
// plugins: [new BundleAnalyzerPlugin()],
|
||||
plugins: [ new buildPlugin() ]
|
||||
}
|
||||
|
24
screenshot/webpack.plugin.js
Normal file
24
screenshot/webpack.plugin.js
Normal file
@ -0,0 +1,24 @@
|
||||
const pkg = require("./package.json");
|
||||
const fs = require('fs');
|
||||
|
||||
class MyPlugin {
|
||||
apply(compiler) {
|
||||
compiler.hooks.emit.tap("BuildPackageJson", (compilation) => {
|
||||
console.log("构建 package.json ....");
|
||||
const myBuildPackageJson = `{
|
||||
name: ${pkg.name+'-builder'},
|
||||
version: ${pkg.version},
|
||||
dependencies: ${JSON.stringify(pkg.dependencies, null, 2)}
|
||||
}`;
|
||||
fs.writeFile('./dist/package.json', myBuildPackageJson, 'utf8', (err) => {
|
||||
if (err) {
|
||||
console.error('保存 package.json 文件时发生错误:', err);
|
||||
} else {
|
||||
console.log('package.json 文件构建完成!');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MyPlugin;
|
4984
screenshot/yarn.lock
4984
screenshot/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user