mirror of
https://github.com/setube/ogame-vue-ts.git
synced 2026-05-12 07:55:11 +08:00
feat(server): 优化静态资源服务与构建配置
- 添加 docs 目录到 .gitignore 忽略列表 - 修复统计脚本 URL 协议为 HTTPS - 更新构建时间戳并新增 Windows 可执行文件构建脚本 - 重构服务端静态资源处理逻辑,支持 Bun 自动嵌入 - 改进 SPA 路由 fallback 机制 - 优化局域网 IP 获取函数变量声明 - 完善 Content-Type 响应头设置 - 移除冗余代码注释,提升可读性
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -12,6 +12,7 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
|
docs
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.claude/*
|
.claude/*
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
<!-- 统计勿删 -->
|
<!-- 统计勿删 -->
|
||||||
<script charset="UTF-8" id="LA_COLLECT" src="//sdk.51.la/js-sdk-pro.min.js"></script>
|
<script charset="UTF-8" id="LA_COLLECT" src="https://sdk.51.la/js-sdk-pro.min.js"></script>
|
||||||
<script>LA.init({ id: "L298GYqn6JhAO0VU", ck: "L298GYqn6JhAO0VU", autoTrack: true, hashMode: true })</script>
|
<script>LA.init({ id: "L298GYqn6JhAO0VU", ck: "L298GYqn6JhAO0VU", autoTrack: true, hashMode: true })</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@
|
|||||||
"author": "setube",
|
"author": "setube",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"buildDate": "2025/12/13 11:11:17",
|
"buildDate": "2025/12/13 14:49:22",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port 25121",
|
"dev": "vite --port 25121",
|
||||||
"build": "vue-tsc -b && vite build && node update-build-date.js",
|
"build": "vue-tsc -b && vite build && node update-build-date.js",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"build-pkg:windows": "bun build ./server.js --compile --minify --outfile ogame.exe"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@tailwindcss/vite": "^4.1.17",
|
"@tailwindcss/vite": "^4.1.17",
|
||||||
|
|||||||
51
server.js
51
server.js
@@ -3,21 +3,23 @@ const path = require('path');
|
|||||||
const { exec } = require('child_process');
|
const { exec } = require('child_process');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
|
||||||
|
|
||||||
|
// Bun 会自动嵌入整个 docs 目录下所有文件(包括 assets/ 里的 js、css、图片等)
|
||||||
|
import "./docs/index.html";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
// 1. 跨平台自动打开浏览器函数
|
|
||||||
function openUrl(url) {
|
function openUrl(url) {
|
||||||
const start = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start ""' : 'xdg-open';
|
const start = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start ""' : 'xdg-open';
|
||||||
exec(`${start} "${url}"`);
|
exec(`${start} "${url}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 获取局域网 IP
|
|
||||||
function getLocalIp() {
|
function getLocalIp() {
|
||||||
const interfaces = os.networkInterfaces();
|
const interfaces = os.networkInterfaces();
|
||||||
for (let devName in interfaces) {
|
for (let devName in interfaces) {
|
||||||
let iface = interfaces[devName];
|
const iface = interfaces[devName];
|
||||||
for (let i = 0; i < iface.length; i++) {
|
for (let i = 0; i < iface.length; i++) {
|
||||||
let alias = iface[i];
|
const alias = iface[i];
|
||||||
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
|
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
|
||||||
return alias.address;
|
return alias.address;
|
||||||
}
|
}
|
||||||
@@ -26,28 +28,39 @@ function getLocalIp() {
|
|||||||
return 'localhost';
|
return 'localhost';
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 核心:静态资源拦截器(实现单文件嵌入的关键)
|
// 静态资源服务(现在能正常工作了!)
|
||||||
app.get('/:path*', async (req, res) => {
|
app.use(async (req, res, next) => {
|
||||||
// 处理请求路径,默认为 index.html
|
let requestedPath = req.path;
|
||||||
let reqPath = req.path === '/' ? '/index.html' : req.path;
|
|
||||||
|
|
||||||
// 这里的路径必须在构建时能找到对应的 docs 目录
|
// 根路径处理
|
||||||
// Bun 编译时会自动将 Bun.file 引用的静态资源打包进去
|
if (requestedPath === '/' || requestedPath === '') {
|
||||||
const filePath = path.join(__dirname, "docs", reqPath);
|
requestedPath = '/index.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = "./docs" + requestedPath;
|
||||||
const file = Bun.file(filePath);
|
const file = Bun.file(filePath);
|
||||||
|
const exists = await file.exists();
|
||||||
|
|
||||||
if (await file.exists()) {
|
if (exists) {
|
||||||
res.type(file.type);
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
res.send(Buffer.from(await file.arrayBuffer()));
|
const buffer = Buffer.from(arrayBuffer);
|
||||||
|
|
||||||
|
// 设置正确的 Content-Type
|
||||||
|
const type = file.type || 'application/octet-stream';
|
||||||
|
res.setHeader('Content-Type', type);
|
||||||
|
|
||||||
|
res.send(buffer);
|
||||||
} else {
|
} else {
|
||||||
// Vue History 模式支持:找不到的文件指向 index.html
|
// SPA fallback
|
||||||
const indexFile = Bun.file(path.join(__dirname, "docs", "index.html"));
|
const indexFile = Bun.file("./docs/index.html");
|
||||||
res.type('text/html');
|
const arrayBuffer = await indexFile.arrayBuffer();
|
||||||
res.send(Buffer.from(await indexFile.arrayBuffer()));
|
const buffer = Buffer.from(arrayBuffer);
|
||||||
|
|
||||||
|
res.setHeader('Content-Type', 'text/html');
|
||||||
|
res.send(buffer);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 4. 启动服务器(随机端口)
|
|
||||||
const server = app.listen(0, '0.0.0.0', () => {
|
const server = app.listen(0, '0.0.0.0', () => {
|
||||||
const { port } = server.address();
|
const { port } = server.address();
|
||||||
const url = `http://localhost:${port}`;
|
const url = `http://localhost:${port}`;
|
||||||
|
|||||||
Reference in New Issue
Block a user