Flet Web 应用发布指南静态网站与动态网站选型与完整实战【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/fletFlet 允许你将纯 Python 编写的应用发布为静态网站Python 在浏览器中以 Pyodide 运行或动态网站Python 运行在服务器端浏览器通过 WebSockets 实时通信。本文以 Flet 官方发布文档为核心系统对比两种模式在加载速度、性能、兼容性与托管成本上的差异并给出flet publish、flet build web与flet run --web三条完整的上线路径以及 base URL、路由策略、Web 渲染器等关键配置项的解析与示例帮助你根据应用场景做出正确选型并快速部署。两种发布模式总览静态网站 vs 动态网站Flet 发布 Web 应用有两条完全不同的技术路线静态网站Static website——内容以静态文件的形式交付Python 代码通过 PyodideCPython 的 WebAssembly 移植版在浏览器中运行服务器上不执行任何 Python 代码。动态网站Dynamic website——内容按用户请求实时生成Python 代码持续运行在服务器上浏览器仅作为客户端。以下表格来自 Publish Flet web app完整对比了两种模式的关键差异静态网站动态网站加载时间⬇️ 较慢——Python 运行时Pyodide连同应用 Python 代码及其所有依赖都必须加载进浏览器Pyodide 初始化本身也需要时间。✅ 较快——应用驻留在服务器上运行。Python 兼容性⬇️ 并非所有能在原生 Python 下运行的程序都能在 Pyodide 下运行✅ 可以使用任意 Python 包。响应性✅ 用户事件点击、文本框修改、拖拽与页面更新之间零延迟。⬇️ 存在非零延迟——用户事件通过 WebSockets 发送到服务器UI 更新再传回浏览器。性能⬇️ 较慢——受 WASM 影响Pyodide 目前比原生 Python 慢 3~5 倍✅ 较快——代码由原生 Python 在服务器上运行。代码保护⬇️ 较低——应用代码被加载进浏览器用户可以直接查看。✅ 较高——应用运行在服务器上。托管✅ 便宜/免费——服务器不运行任何代码因此应用可以托管在任何地方GitHub Pages、Cloudflare Pages、Replit、Vercel、共享主机或你自己的 VPS。⬇️ 付费——应用需要 Python 代码在服务器上运行并通过 WebSockets 与浏览器通信。Python 版本⬇️ 绑定到特定 Pyodide 版本——只能从受支持的集合中挑选3.12 / 3.13 / 3.14。见选择 Python 版本。✅ 任意能运行服务器的 Python 版本。从源码结构看这两条路径分别对应仓库中 static-website 与 dynamic-website 两个独立的发布子文档下文分别展开。静态网站两种发布命令的取舍发布静态网站有两条路径flet publish与flet build web。两者产出的都是在浏览器中通过 Pyodide 运行的静态站点主要区别在于 Python 依赖的安装时机与方式flet publishflet build web需要 Flutter否是依赖安装运行时、在浏览器中micropip构建时、在本地机器上pip构建时间更快——无需 Flutter 编译无需本地 pip 安装较慢——需要 Flutter 构建 本地依赖安装初始加载时间较慢——页面加载时从 PyPI 拉取 wheel较快——依赖已随构建产物打包纯 Python wheel✅✅Pyodide 构建的二进制 wheel✅来自 Pyodide CDN✅从 Pyodide 注册表自动检测源码发行包sdist❌micropip无法在浏览器中构建 sdist✅ 纯 Python sdist通过source_packages启用Pyodide 与 Python 版本绑定Pyodide 是 CPython 到 WebAssemblyWASM的移植存在一些已知限制。你为flet build web/flet publish选择的 Python 版本会固定一个具体的 Pyodide 版本完整的版本矩阵与解析规则见选择 Python 版本简要对应关系如下PythonPyodide3.14314.0.63.130.29.43.120.27.7匹配的 Pyodide 运行时会下载到构建输出中并在首次使用时缓存到~/.flet/pyodide/version/。原先内置在构建模板中的旧版0.27.5已移除改为这种按构建版本化下载的方式。原生 Python 包的约束原生 Python 包相对于仅用 Python 编写的纯 Python包是部分用 C、Rust 或其他语言编写并产生原生代码的包典型如numpy、cryptography、lxml、pydantic-core。Pyodide 自带一份内置包列表。要使用 PyPI 上的包它必须是纯 Python 的或者提供了为 Emscripten 构建的 wheel。单线程与异步约束静态网站运行在浏览器单一线程中。你可以同时使用同步和异步 handler但长时间运行的 CPU 密集任务或阻塞调用会冻结 UI。官方建议优先使用异步 I/O或者把重负载工作移到服务器通过 Web API 调用。运行时安装包MicropipPyodide 使用 micropip 安装包。你也可以在 Flet 应用中直接使用 Micropip API 按需安装依赖import sys if sys.platform emscripten: import micropip await micropip.install(regex)Sdist-only 依赖常见的失败模式flet publish一个常见失败场景是传递依赖只提供源码发行包.tar.gz没有 wheel例如docopt。micropip无法构建 sdist加载时会报错ValueError: Cant find a pure Python 3 wheel for package遇到这种情况官方建议切换到flet build web并把该包加入source_packages。注意source_packages只对纯 Pythonsdist 生效带 C/Rust 扩展的 sdist如numpy、cryptography无法为 Pyodide 构建——请改用 Pyodide 的内置包。使用flet publish发布flet publish不依赖 Flutter。它打包你的应用并在浏览器运行时通过 micropip 安装依赖。发布命令flet publish path-to-app.py网站发布到--distpath指定的目录默认./dist。本地测试可以用flet serve命令试跑发布好的应用flet serve dist然后在浏览器中打开http://localhost:8000检查发布效果。Assets 资源如果 assets 目录存在默认./assets其内容会被复制到发布站点的根目录。用--assets可以指向其他目录。注意 assets 不会被打包进app.tar.gz。使用flet build web构建flet build web使用 Flutter。本地测试flet serve会直接服务默认输出目录./build/webflet serve动态网站基于 FastAPI 的实时应用动态网站模式下Flet 把你的应用作为 FastAPIASGI应用运行。默认使用 Uvicorn但任何兼容 ASGI 的服务器都可以替代。混合使用同步与异步 handlerFlet Web 应用可以混用同步与异步 handler。官方示例import flet as ft import time import asyncio def main(page: ft.Page): def handler(e): time.sleep(3) page.add(ft.Text(Handler clicked)) async def handler_async(e): await asyncio.sleep(3) page.add(ft.Text(Async handler clicked)) page.add( ft.Button(Call handler, on_clickhandler), ft.Button(Call async handler, on_clickhandler_async) ) ft.run(main)示例中点击第一个按钮由阻塞式 handler 处理点击第二个按钮则调用异步 handler。前者运行在threading.Thread中后者作为asyncio.Task运行。关键考量在 Web 应用中线程是有限资源。通常使用线程池随着用户数增长它会成为瓶颈。如果你的应用以 I/O 为主数据库、Web API且能使用异步就绪的库请优先使用异步 handler。关于并发与并行的区别可参考 FastAPI 官方关于 async/await 的文章。本地运行使用--web-w选项以 Web 应用方式启动flet run --web app.py会打开新的浏览器窗口/标签页应用使用随机 TCP 端口。要固定端口使用--port-pflet run --web --port 8000 app.py生产环境运行你可以直接用python运行程序python app.py默认由 Uvicorn Web 服务器承载 Web 应用。如果 Flet 检测到无头 Linux 环境如 Docker 容器或 EC2 VM使用端口8000运行应用不打开浏览器窗口。如果 Flet 无法自动检测无头环境可通过环境变量强制FLET_FORCE_WEB_SERVERtrue使用任意 ASGI 服务器Flet 应用可以托管在任意兼容 ASGI 的服务器上如 Uvicorn默认、Hypercorn 或 Daphne。只需让 Flet 导出 ASGI 应用import flet as ft def main(page: ft.Page): page.add(ft.Text(Hello ASGI!)) app ft.run(main, export_asgi_appTrue)Hypercorn受 Gunicorn 启发的另一款 ASGI 服务器hypercorn main:app --bind 0.0.0.0:8000DaphneHTTP、HTTP2 与 WebSocket 协议服务器为 Django Channels 开发daphne -b 0.0.0.0 -p 8000 main:appGunicorn流行的 WSGI 服务器可通过 Uvicorn 提供的 worker 进程类运行 ASGI FastAPI 应用gunicorn --bind 0.0.0.0:8000 -k uvicorn.workers.UvicornWorker counter:app动态网站的资源服务与自定义浏览器打开 Flet 应用时其index.html、Flutter 引擎、favicon、图片等 Web 资源由 Web 服务器提供这些资源随fletPython 包打包。但有时你需要修改某些文件来自定义外观或行为例如Favicon。应用加载动画。含 PWA 详情的manifest.json。你可以在flet.run()中指定assets_dir来设置应用可访问的资源位置。assets_dir应相对于main.py所在目录或使用绝对路径默认值为assets。例如项目结构/assets /images/my-image.png main.py应用中访问图片import flet as ft def main(page: ft.Page): page.add(ft.Image(srcf/images/my-image.png)) ft.run(main, assets_dirassets)自定义 Web 应用图标Iconsassets 目录中的一切都会覆盖到构建站点上因此可以通过放置同名同路径文件来替换任何生成的图标文件用途是否被平台遮罩favicon.png浏览器标签页否icons/Icon-192.png、icons/Icon-512.png已安装应用、启动画面、任务切换器否icons/Icon-maskable-192.png、icons/Icon-maskable-512.pngAndroid 安装是裁切为圆形icons/apple-touch-icon-192.pngiOS添加到主屏幕是圆角你放入的文件按原样生效因此两种被遮罩的图标需要你自己处理好。可遮罩图标maskable icon应保持不透明且 artwork 位于占宽度 80% 的圆内——超出部分会被裁掉透明图标在部分 Android 启动器上会显示黑色角落。若想一次性更换所有图标可替换icon.png或仅 Web 用icon_web.pngFlet 会重新生成整套图标并适配各自的遮罩。加载画面Loading screen动态网站会先显示静态 Flet Logo直到 Flutter 绘制出第一帧。要替换它把你的图片放到应用 assets 目录的icons/loading-animation.png。文件名保留以兼容旧版该图片不再使用呼吸或缩放动画。随后的 Flutter 启动画面通过[tool.flet.boot_screen]单独配置且此覆盖仅对动态网站生效flet build web使用配置的启动画面。PWA渐进式 Web 应用PWA 将类应用网站变成类网站应用。支持 PWA 的浏览器包括全平台Chrome、全平台Edge、Android 上的Firefox、iOS/iPadOS 上的Safari。Manifest可以在 assets 目录根部的manifest.json中修改 PWA 的名称、描述、颜色等信息。常用字段name——Web 应用的显示名称。short_name——空间不足时显示的短名称。description——应用功能说明。theme_color——应用默认主题色。background_color——样式表加载前页面显示的占位背景色。自定义图标放在assets/icons目录icon-192.png、icon-512.png——Windows 任务栏显示的应用图标。icon-maskable-192.png、icon-maskable-512.png——Android 显示的应用图标。apple-touch-icon-192.png——iOS 显示的应用图标。Web 构建配置项详解以下配置适用于flet build web与flet publish除非特别注明。每个配置项都遵循 CLI 参数 pyproject.toml 环境变量 默认值的解析优先级。Base URL基础路径当应用托管在子目录时使用 base URL。Flet 会将其规范化为/value/未设置时使用/。解析优先级--base-url[tool.flet.web].base_url/# CLI flet build web --base-url /myapp/# pyproject.toml [tool.flet.web] base_url /myapp/Route URL strategy路由策略控制路由在 URL 中的表示方式path——干净路径需要支持 SPA 的托管服务。hash——使用 URL hash可在不支持 SPA 的静态主机上工作。解析优先级--route-url-strategy[tool.flet.web].route_url_strategyFLET_WEB_ROUTE_URL_STRATEGYpathflet build web --route-url-strategy hash[tool.flet.web] route_url_strategy hashFLET_WEB_ROUTE_URL_STRATEGYhashWeb rendererWeb 渲染器选择 Flutter Web 渲染器canvaskit默认——CanvasKit 渲染器应用编译为 JavaScript。skwasm——Skia WebAssembly 渲染器应用编译为 WebAssembly。auto——让 Flutter 根据浏览器自动选择。注意默认是canvaskit而非auto。使用auto时Chromium 系浏览器会选skwasm此时 JavaScript 与 Dart 之间传递的每个字节缓冲都要付出昂贵的 WebAssembly 边界转换开销。Flet Web 应用在每次 UI 更新时都要与 Python 运行时交换字节因此对它们而言canvaskit明显更快。解析优先级--web-renderer[tool.flet.web].rendererFLET_WEB_RENDERERcanvaskitflet build web --web-renderer skwasm[tool.flet.web] renderer skwasmFLET_WEB_RENDERERskwasmCDN assetsCDN 资源默认情况下Pyodide、CanvasKit 和字体从 CDN 加载以保持输出体积小。离线或隔离air-gapped部署时应禁用 CDN 加载。禁用 CDN 的解析优先级--no-cdn[tool.flet.web].cdn falseFLET_WEB_NO_CDN默认启用 CDNflet build web --no-cdn[tool.flet.web] cdn falseFLET_WEB_NO_CDNtruePWA colorsPWA 颜色配置manifest.json和浏览器 UI 中使用的 PWA 颜色。解析优先级每个设置独立--pwa-background-color/--pwa-theme-color[tool.flet.web].pwa_background_color/[tool.flet.web].pwa_theme_color#FFFFFF/#FF005Fflet build web --pwa-background-color #000000 --pwa-theme-color #FF0000[tool.flet.web] pwa_background_color #000000 pwa_theme_color #FF0000WASM outputWASM 输出默认情况下flet build web启用 Flutter 的 WASM 输出仅flet build web可用。禁用 WASM 输出的解析优先级--no-wasm[tool.flet.web].wasm false默认启用 WASMflet build web --no-wasm[tool.flet.web] wasm false托管与部署实践静态网站托管GitHub Pages静态网站无需服务器运行代码因此可以免费托管在 GitHub Pages 上。官方提供了基于 GitHub Actions 的完整 CI/CD 工作流见 Hosting Flet website on GitHub Pages。核心构建命令为uv run flet build web --yes --verbose --base-url ${GITHUB_REPOSITORY#*/} --route-url-strategy hash其中--base-url使项目页部署在/repo/下若仓库是username.github.io则用--base-url /--route-url-strategy hash让路由在没有服务器端重写的静态托管上正常工作。部署前需在 GitHubSettings → Pages中将部署源设为GitHub Actions。静态网站托管Cloudflare PagesCloudflare Pages 指南 提供了两种部署方式连接 Git 提供方此方式仅适用于flet publish。在仓库中添加runtime.txt指定 Python 版本构建命令由 Flet 执行后生成dist目录即输出目录。直接上传此方式同时适用于flet build web和flet publish。上传项目资产文件夹或 zip或先用flet publish生成dist文件夹再上传。若打开站点看到 Cloudflare 错误通常只是设置尚未完成等待一分钟后刷新即可。动态网站托管关注 WebSocket 与延迟动态网站托管指南 强调Flet 应用使用 WebSockets 进行 UI 的实时局部更新并把事件发回你的程序。选择托管服务商时需注意其对 WebSockets 的支持——有些服务不允许 WebSocket 或将其归入更贵的套餐有些代理会周期性超时断开 WebSocket 连接Flet 实现了重连逻辑但频繁断线对用户体验仍然不佳。另一个重要因素是延迟。用户每次 UI 操作都会向 Flet 应用发送消息应用再把更新后的 UI 传回。选择有多数据中心的托管商让应用尽量靠近多数用户运行。相关环境变量环境变量参考 中与 Web 托管直接相关的变量包括FLET_FORCE_WEB_SERVER——设为true强制以 Web 应用方式运行在无头 Linux 主机上自动设置。FLET_SERVER_PORT——应用运行的 TCP 端口。若程序运行在 Linux 服务器上或设置了FLET_FORCE_WEB_SERVER默认8000否则随机端口。FLET_SERVER_IP——监听 IP默认0.0.0.0。FLET_WEB_APP_PATH——域名后的 URL 路径如/apps/myapp默认/。FLET_WEB_NO_CDN——设为true避免从 CDN 加载 CanvasKit、Pyodide 与字体。FLET_WEB_RENDERER——Web 渲染模式canvaskit默认、skwasm或auto。FLET_WEB_ROUTE_URL_STRATEGY——URL 策略path默认或hash。FLET_WEB_USE_COLOR_EMOJI——设为True/true/1加载彩色 emoji 网页字体。FLET_WEBSOCKET_HANDLER_ENDPOINT——WebSocket handler 路径默认/ws。FLET_UPLOAD_HANDLER_ENDPOINT——上传 handler 路径默认/upload。FLET_OAUTH_CALLBACK_HANDLER_ENDPOINT——OAuth 回调路径默认/oauth_callback。FLET_MAX_UPLOAD_SIZE——上传文件的最大字节数默认无限制。FLET_SESSION_TIMEOUT——会话生命周期秒默认3600。高级 FastAPI 场景Flet FastAPI 应用的内置端点flet.fastapi.app()创建一个处理 Flet 会话的 FastAPI 应用并在应用根目录挂载以下端点/wsWS——Flet 应用的 WebSocket handler。建立新 WebSocket 连接并创建新应用会话时调用main()。/uploadPUT——文件上传 handler。/oauth_callbackGET——OAuth 流程回调 handler。/GET——Flet 应用静态文件带 SPA catch-all handler。同一域名下托管多个 Flet 应用import flet as ft import flet.fastapi as flet_fastapi async def root_main(page: ft.Page): page.add(ft.Text(This is root app!)) async def sub_main(page: ft.Page): page.add(ft.Text(This is sub app!)) app flet_fastapi.FastAPI() app.mount(/sub-app, flet_fastapi.app(sub_main)) app.mount(/, flet_fastapi.app(root_main))子应用必须映射在根 Flet 应用之前因为根应用会配置 SPA 的 catch-allindex.html。用uvicorn运行后访问http://127.0.0.1:8000与http://127.0.0.1:8000/sub-app/可看到两个应用。注意/sub-app/结尾的斜杠——缺少它请求会被路由到根应用。将 Flet 加入现有 FastAPI 应用from contextlib import asynccontextmanager import flet as ft import flet.fastapi as flet_fastapi from fastapi import FastAPI asynccontextmanager async def lifespan(app: FastAPI): await flet_fastapi.app_manager.start() yield await flet_fastapi.app_manager.shutdown() app FastAPI(lifespanlifespan) async def main(page: ft.Page): page.add(ft.Text(Hello, Flet!)) app.mount(/flet-app, flet_fastapi.app(main))将 Flet 应用加入现有 FastAPI 应用时需要在启动时调用flet_fastapi.app_manager.start()、关闭时调用app_manager.shutdown()可用 lifespan 或应用事件实现。start()启动清理过期会话与 OAuth 流程状态的后台任务shutdown()移除 Flet 应用创建的临时文件。单独配置 Flet 端点静态文件提供 index.html、manifest.json、Flutter JS 应用等静态资源与用户资源from flet.fastapi import FastAPI, FletStaticFiles app FastAPI() # mount to the root of web app app.mount(path/, appFletStaticFiles())WebSocket handler处理浏览器中 Flet 客户端的连接WebSocket 通道用于将事件从浏览器发送到后端并接收页面更新import asyncio import flet as ft from flet.fastapi import FletApp, app_manager async def main(page: ft.Page): page.add(ft.Text(Hello, Flet!)) app.websocket(/app1/ws) async def flet_app(websocket: WebSocket): await FletApp( loopasyncio.get_running_loop(), executorapp_manager.executor, mainmain, before_mainNone, ).handle(websocket)上传 handler处理由FilePicker控件发起的文件上传此端点可选若应用不使用 FilePicker 则无需配置from flet.fastapi import FletUpload app.put(/upload) async def flet_uploads(request: Request): await FletUpload(/Users/feodor/Downloads/123).handle(request)OAuth 回调 handler处理 OAuth 流程回调若应用不使用认证则无需配置from flet.fastapi import FletOAuth app.get(/oauth_callback) async def flet_oauth(request: Request): return await FletOAuth().handle(request)选型建议与总结结合官方发布文档的对比表可以总结出清晰的选型思路追求零成本托管、代码不敏感、交互实时——选静态网站flet publish或flet build web。它适合中小型应用、演示项目和个人工具可免费部署在 GitHub Pages、Cloudflare Pages 等任意静态托管平台代价是加载较慢、受 Pyodide 的性能与兼容性约束、代码可被查看。使用任意 Python 包、需要性能与代码保护、用户规模大——选动态网站flet run --web/flet build产物 Uvicorn 等 ASGI 服务器。服务器端原生 Python 运行兼容任意依赖但需要付费托管且要关注服务商对 WebSockets 的支持与网络延迟。依赖以纯 Python wheel 为主、无 Flutter 环境——flet publish最省事依赖含 sdist-only 或需要最快首屏加载——用flet build web并把纯 Python sdist 加入source_packages。无论选择哪条路径flet serve都是本地验证发布结果最便捷的手段而 base URL、路由策略、渲染器等配置项CLI 参数 /pyproject.toml/ 环境变量三级优先级则可以精确控制应用在不同托管环境下的行为。【免费下载链接】fletBuild realtime web, mobile and desktop apps in Python only. No frontend experience required.项目地址: https://gitcode.com/gh_mirrors/fl/flet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
