owned this note
owned this note
Published
Linked with GitHub
- 本筆演講內容在此連結
https://hackmd.io/dk91-0LyTqe0MaqA8TeoKg
- Miro 報到的連結
https://miro.com/app/board/uXjVM2ue-oE=/?share_link_id=483117069515
- 另設有共同編輯區,大家可點此進去編輯打字
https://hackmd.io/@milochen0418/Hy9Byz3Fn
- 以前分享過Pynecone (Reflex) 的[雜記](https://hackmd.io/@milochen0418/pynecone-post-python-taiwan)
-------
本篇架構
-------
[TOC]
# Reflex 的開發
可以使用 VSCode+conda, VSCode+poetry 等方式來開發,或是初次使用的話可以考慮 [Pynecone (Reflex) Colab-IDE](https://github.com/milochen0418/pynecone-colab-ide)
[Pynecone](https://pynecone.app/) 改名至 [Reflex](https://reflex.dev/)
## What is pynecone(Reflex)
Pinecone -> Pynecone 松果
-> Reflex
pure pyhon 寫 全端網站 (後端、前端)
- ReactJS
PyQt
flask + jQuery MySQL , PostgreSQL
ReactJS
.NET framework
前端 React
2023 Q1 top 1 最熱的開源新創項目 YC seed
https://github.com/pynecone-io/pynecone
## Reflex 架構簡介
很簡化的來說,就是透過開發團隊的努力,將FastAPI + React 的集成,最終包出一個簡易好用的WebApp框架給你用, 希望讓人們可以用純python 來發展WebApp
### 後端的部份
簡單來說就是 FastAPI ,但是實戰app開發中,它框架已經作了簡化,因此你不用處理到中間複雜的溝通過程。
### 前端的部份
前端使用 ReactJS (或是說NextJS)
在作畫面調整的部份部份,支持 [TailwindCSS](https://tailwindcss.com/), [ChakraUI](https://chakra-ui.com/),而且另一個特好用的優點,你可以自己使用其它React元件 來擴充。Reflex願景是希望可以盡可能將React的優點拿來使用。
目前,Netflix、Uber、星巴克或 Twitch 使用了NextJS
NextJS是基於React的框架,差別在於 ReactJS 是在 browser 上直接作了渲染,而 Next.js將渲染方面的工作移到了服務器上,因此客戶端不需要處理這些信息。這提高了性能和SEO,因為服務器預先渲染頁面,然後將最終的HTML發送給客戶端,從而使JS最小化,也就是說加載的代碼更少。不僅用戶可以期待一個更快的網站,而且爬蟲也可以更容易地看到你的網站,並對其進行相應的索引。
Pynecone的渲染到底是 NextJS的哪種呢?
NextJS它支持三種渲染方式包括
客戶端渲染 BSR (Broswer Side Render), 靜態頁面生成 SSG (Static Site Generation), 服務端渲染 SSR (Server Side Render)
而 [pynecone 使用 SSG](https://news.ycombinator.com/item?id=35137402) 靠 [bun-runtime](https://bun.sh/) 來作,因為渲染效能比 NodeJS 快約三倍以上。
[其餘渲染知識請見此](https://zhuanlan.zhihu.com/p/341229054)
# 實戰開發
## 申請 key 的部份
### ngrok auth token
### openai key
## 開始開發
讓我們來寫寫看一個 DALL-E
### 建立初始專案
```bash=
mkdir mydalle
cd mydalle
reflex init
reflex run
```
### 新增requirments.txt (Optional)
```txt=
reflex==0.2.0
openai
```
### 簡化成 HelloWorld
```python=
"""Welcome to Reflex! This file outlines the steps to create a basic app."""
import reflex as rx
import openai
import os
class State(rx.State):
"""The app state."""
pass
def index() -> rx.Component:
return rx.center(
rx.heading("Hello World"),
)
# Add state and page to the app.
app = rx.App(state=State)
app.add_page(index, title="MyDALL-E")
app.compile()
```
### Layout
```python=
import reflex as rx
import openai
import os
openai.api_key = os.environ.get("OPENAI_KEY","YOUR_OPENAI_KEY")
class State(rx.State):
"""The app state."""
image_url = ""
image_processing = False
image_made = False
def get_dalle_result(self, form_data: dict[str, str]):
pass
pass
def index() -> rx.Component:
return rx.center(
rx.vstack(
rx.heading("DALL-E", font_size="1.5em"),
rx.form(
rx.input(id="prompt_text", placeholder="Enter a prompt.."),
rx.button(
"Generate Image",
type_="submit",
width="100%",
),
on_submit=State.get_dalle_result,
),
rx.divider(),
rx.cond(
State.image_processing,
rx.circular_progress(is_indeterminate=True),
rx.cond(
State.image_made,
rx.image(
src=State.image_url,
height="25em",
width="25em",
),
),
),
bg="white",
padding="2em",
shadow="lg",
border_radius="lg",
),
width="100%",
height="100vh",
background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)",
)
# Add state and page to the app.
app = rx.App(state=State)
app.add_page(index, title="MyDALL-E App")
app.compile()
```
### 完成
```python=
import reflex as rx
import openai
import os
openai.api_key = os.environ.get("OPENAI_KEY","YOUR_OPENAI_KEY")
class State(rx.State):
"""The app state."""
image_url = ""
image_processing = False
image_made = False
def get_dalle_result(self, form_data: dict[str, str]):
prompt_text:str = form_data['prompt_text']
self.image_processing = True
yield
try:
response = openai.Image.create(prompt=prompt_text, n=1, size="1024x1024")
self.image_url = response["data"][0]["url"]
self.image_processing = False
self.image_made = True
yield
except:
self.image_processing = False
yield rx.window_alert("Error to call openAI API")
pass
def index() -> rx.Component:
return rx.center(
rx.vstack(
rx.heading("DALL-E", font_size="1.5em"),
rx.form(
rx.input(id="prompt_text", placeholder="Enter a prompt.."),
rx.button(
"Generate Image",
type_="submit",
width="100%",
),
on_submit=State.get_dalle_result,
),
rx.divider(),
## rx.cond( Treu/False, True:作啥layout, False:作啥layout )
rx.cond(
State.image_processing,
rx.circular_progress(is_indeterminate=True),
rx.cond(
State.image_made,
rx.image(
src=State.image_url,
height="25em",
width="25em",
),
),
),
bg="white",
padding="2em",
shadow="lg",
border_radius="lg",
),
width="100%",
height="100vh",
background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)",
)
# Add state and page to the app.
app = rx.App(state=State)
app.add_page(index, title="MyDALL-E App")
app.compile()
```
# 聽眾
碰過 Django, flask, FastAPI, 想評估 reflex