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

关于前后端整合和打包成exe文件的个人的总结和思考

前言

感觉有很多东西,不知道写什么,随便写点吧。

正文

前后端合并

就不说怎么开发的,就说点个人感觉重要的东西。

前端用React+Vite+axios随便写一个demo,用于CRUD。

后端用Django REST Framework。

设置前端打包

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
  plugins: [react()],
  base:'./',
  build:{
    outDir:'template',
    assetsDir:'static',
  },
  server:{
    proxy:{
      '/api':{
        target:'http://localhost:8000',
        changeOrigin:true,
        rewrite:path=>path.replace(/^\/api/,'')
      }
    }
  }
})

如果不用一些代理工具nginx等,打包后代理没有用了。

要么在axios中去掉

baseUrl='/api'

或者在Django的路由前加上/api,一样,都行

后续操作

1、打包后将tempate目录复制到Django的根目录下

2、将vite.svg图标放到static目录下

3、修改settings.py文件的关键部分

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR/'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
STATICFILES_DIRS=[
    BASE_DIR/'templates/static'
]

如果选择static文件夹拿到根目录,也行,修改一下STATICFILES_DIRS。

4、修改index.html,显示图标

{% load static %}
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="{% static 'vite.svg'%}" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React</title>
    <script type="module" crossorigin src="../static/index-CetNvwB0.js"></script>
    <link rel="stylesheet" crossorigin href="../static/index-B7i0P6ID.css">
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

5、修改项目的urls.py文件

from django.contrib import admin
from django.urls import path,include,re_path
from django.views.generic import TemplateView


urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/book/', include('book.urls')), # 加上api前缀
    re_path(r'^.*$', TemplateView.as_view(template_name='index.html')), # 这里是为了解决前端路由问题
]

启动项目。

刷新页面,没有问题。

如果写成下面这种。

path('',TemplateView.as_view(template_name='index.html')),

刷新就会报错。因为前端路由和后端路由并不是完全相同的。

比如前端路由/show,而后端只有book,book/:id等的路由,没有/show,路由不一致。

因此,代码如下

re_path(r'^.*$', TemplateView.as_view(template_name='index.html'))

前后端合并完成,其实这个时候,可以部署到服务器。笔者选择打包成exe文件

打包exe文件

笔者的Django项目是Rye建立的,安装Pyinstaller

其中pyproject.toml的脚本内容如下

[tool.rye.scripts]

dev = "python manage.py runserver"
build="pyinstaller -F manage.py"
build_add_data='pyinstaller -F --add-data="./templates;templates" --add-data="./static;static" manage.py'

dev :运行项目

build_add_data:增加其他模板文件和静态文件打包成一个exe文件

笔者依照脚本移动templates目录下的static到根目录,为了更好的打包。也可以不移动,修改一下脚本的路径即可。

笔者参考了其他大佬的打包过程,可能版本发生变换,打包简单多了,只需要增加静态文件和模板。

Pyinstaller打包Django项目(耗时两天 踩坑无数 记录一下)_runtimeerror: script runserver does not exist.-CSDN博客https://blog.csdn.net/qq_40292262/article/details/117026558pyinstaller打包Django项目+避坑指南-CSDN博客https://blog.csdn.net/weixin_37934258/article/details/130216656进入到manage.py目录下。

运行脚本

rye run build_add_data

虽然过程中有警告

但无所谓,运行成功。

完美。

后端打包,前端使用nw

在前篇文章中

在github action工作流使用nw和nw-builder打包-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146126489?spm=1001.2014.3001.5502我使用了nw,nw可以吧html页面打包成exe

笔者有个想法

不把前后端合并,后端没有模板和静态文件,就提供API,把后端打包成manage.exe

然后nw运行html文件时,同时打开manage.exe。

可惜,没完全实现,笔者实力不行

前端打包和跨域问题

笔者可能刚刚知道nw,不是很了解,笔者发现需要html文件本身能够运行,才能使用nw。

因此,修改路由为Hash

即createHashRouter,

如果不改,运行是这样的

修改后

没有显示内容,因为代理失效了

修改axios的baseUrl内容

import axios from 'axios';

// 后端服务地址
const API_BASE_URL = 'http://127.0.0.1:8000/api';
const requests = axios.create({
    baseURL: API_BASE_URL, // 动态设置 baseURL
    timeout: 5000,
    headers: {
        'Content-Type': 'application/json'
    }
});

export default requests;

再次前端打包,运行

需要跨域,而笔者没有使用代理工具。因此,笔者使用django-cors-headers

修改setting.py的配置

INSTALLED_APPS = [
    ...
    'corsheaders', # 增加corsheaders
]
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware', # 配置中间件
      ...

]
CORS_ALLOW_ALL_ORIGINS = True # 允许所有的源访问

运行index.html

后端打包

不需要模板和静态文件

rye run build

打包没有问题,不必细说。

后端、前端、nw合并

1、将没有模板和静态文件的manage.exe复制在前端pubilc目录下

2、在前端pubilc目录下新建package.json,内容如下

{
  "name": "book",
  "version": "1.0.0",
  "main": "index.html",
  "window": {
    "icon": "vite.svg"
  },
    "scripts": {
        "dev": "concurrently \"node ./main.js\" \"nwbuild --mode=run --glob=false ./\"",
        "nw:build": "nwbuild --mode=build --glob=false --output=../build ."
    },
  "dependencies": {
    "nw": "^0.96.0",
    "nw-builder":"^4.13.9"
  },
  "devDependencies": {
    "concurrently": "^6.2.1"
  }
}

3、新建main.js文件,这里面deepseek写的,我希望使用js代码运行manage.exe

其中内容如下。

const { exec } = require('child_process');
const path = require('path');

// 获取 manage.exe 的路径
const manageExePath = path.join(__dirname, 'manage.exe');

// 打印路径以调试
console.log('manageExePath:', manageExePath);

// 在 Windows 上使用 start 命令启动 manage.exe
if (process.platform === 'win32') {
    exec(`start "" "${manageExePath}" runserver --noreload`, (error, stdout, stderr) => {
        if (error) {
            console.error(`启动 manage.exe 失败: ${error.message}`);
            return;
        }
        console.log(`stdout: ${stdout}`);
        console.error(`stderr: ${stderr}`);
    });
} else {
    // 非 Windows 系统使用 spawn
    const manageProcess = spawn(manageExePath, ['ruanserver', '--noreload'], {
        detached: true,
        stdio: 'ignore'
    });

    manageProcess.unref();

    manageProcess.on('close', (code) => {
        console.log(`manage.exe 退出,代码 ${code}`);
    });

    manageProcess.on('error', (error) => {
        console.error(`启动 manage.exe 失败: ${error.message}`);
    });
}

安装依赖后,运行dev脚本,同时运行manage.exe和nw

结果如下

完美

可惜

可惜,笔者并不知道如何打包后双击的同时运行manage.exe,这可能需要nw的知识,以后再来。

相关文章:

  • 数据集构建与训练前准备
  • VIC模型有哪些优势?适用哪些范围?基于QGIS的VIC模型建模;未来气候变化模型预测;基于R语言VIC参数率定和优化
  • 【Academy】Web 缓存欺骗 ------ Web cache deception
  • 如何实现wordpress搜索自字义字段内容
  • 分享最佳ChatGPT替代11个方案(2025)
  • 计算机组成原理(第六章 总线)
  • 关于在electron(Nodejs)中使用 Napi 的简单记录
  • 内容中台的核心架构是什么?
  • 【在校课堂笔记】Python 第 3 节课 总结
  • FlinkSQL源码笔记
  • ~(取反)在算法竞赛中的常见用法和注意事项
  • 线程管理操作
  • 【CSS3】金丹篇
  • 3.3.5 VO-O语法- 高级语法
  • 大语言模型中Token的输出过程
  • vue+dhtmlx-gantt 实现甘特图-快速入门【甘特图】
  • Python 编程题 第八节:字符串变形、压缩字符串、三个数的最大乘积、判定字符是否唯一、IP地址转换
  • KL散度详解与应用
  • FTP 与 TFTP 的详细异同点
  • 信号与系统笔记——第二章 连续系统的时域分析(三)
  • 马上评|纠偏“左行右立”,并排站不必有道德压力
  • 猫是影子,又是平行时空的使者
  • 11次战斗起飞应对外军挑衅,逼退外军直升机细节曝光
  • 王毅将主持召开第三次中国—太平洋岛国外长会
  • 绵阳一村民在外务工家中老宅被拆,镇政府回应:系施工方误拆
  • 印度空军为“阵风”战机换装国产导弹,以增强作战能力推动国防自主