FhVite

Vite plugin for FastHTML - automatic bundling, minifcation and script injection of static assets

Imports

File configuration

File init


source

setup_files


def setup_files(
    root_dir, entry_file, use_monster:bool=True
):

Setup Vite files in project, with FastHTML configuration

setup_files(root_dir='vite', entry_file='index.js')
Created: vite/vite.config.js
Created: vite/package.json
Created: vite/src/style.css
Created: vite/src/index.js

added 113 packages, and audited 114 packages in 7s

18 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
for path in _monster_temp.keys():
    print('#'+path, (Path('vite')/path).read_text()[:100], sep='\n')
    print('---')
#vite.config.js
import franken from "franken-ui/plugin-vite";
import tailwindcss from "@tailwindcss/vite";
import { 
---
#package.json
{
  "name": "fastvite",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {

---
#src/style.css
@import "tailwindcss";
@import "franken-ui/css/franken-ui.css";
@source "../../";

@theme {
  --colo
---
#src/index.js
import "vite/modulepreload-polyfill";
import "./style.css";
---

Create script injections

subprocess.run('pybun run build', cwd='vite', shell=True, check=True)

> fastvite@0.0.0 build
> vite build

vite v7.0.4 building for production...
transforming...
✓ 3 modules transformed.
rendering chunks...
computing gzip size...
../dist/.vite/manifest.json          0.19 kB │ gzip:  0.14 kB
../dist/assets/index-DwAzhI66.css  215.53 kB │ gzip: 25.35 kB
../dist/assets/index-DSGW5Iaw.js     0.71 kB │ gzip:  0.40 kB
✓ built in 101ms
CompletedProcess(args='npm run build', returncode=0)
print(*(o for o in _mk_scripts(dirname="vite", entry_file='index.js')))
<link rel="stylesheet" href="/vite/assets/index-DwAzhI66.css"> <script type="module" src="/vite/assets/index-DSGW5Iaw.js"></script>

App configuration


source

add_vite


def add_vite(
    app:FastHTML, entry_file:str='index.js', dirname:str='frontend', use_monster:bool=True, directory:str='.'
):

Configure app to use vite

from fasthtml.common import *
app = FastHTML()
app
<fasthtml.core.FastHTML>
app = FastHTML(surreal=False)
rt = app.route
#app.hdrs
add_vite(app, dirname='vite')

> fastvite@0.0.0 build
> vite build

vite v7.0.4 building for production...
transforming...
✓ 3 modules transformed.
rendering chunks...
computing gzip size...
../dist/.vite/manifest.json          0.19 kB │ gzip:  0.14 kB
../dist/assets/index-DwAzhI66.css  215.53 kB │ gzip: 25.35 kB
../dist/assets/index-DSGW5Iaw.js     0.71 kB │ gzip:  0.40 kB
✓ built in 91ms
app.hdrs
[meta((),{'charset': 'utf-8'}),
 meta((),{'name': 'viewport', 'content': 'width=device-width, initial-scale=1, viewport-fit=cover'}),
 link((),{'rel': 'stylesheet', 'href': '/static/assets/index-DwAzhI66.css'}),
 script(('',),{'type': 'module', 'src': '/static/assets/index-DSGW5Iaw.js'}),
 link((),{'rel': 'preconnect', 'href': 'https://cdn.jsdelivr.net'}),
 script(('\n    const htmlElement = document.documentElement;\n\n    const __FRANKEN__ = JSON.parse(\n    localStorage.getItem("__FRANKEN__") || "{}",\n    );\n\n    if (\n    __FRANKEN__.mode === "dark" ||\n    (!__FRANKEN__.mode &&\n        window.matchMedia("(prefers-color-scheme: dark)").matches)\n    ) {\n    htmlElement.classList.add("dark");\n    } else {\n    htmlElement.classList.remove("dark");\n    }\n\n    htmlElement.classList.add(__FRANKEN__.theme || "uk-theme-zinc");\n    htmlElement.classList.add(__FRANKEN__.radii || "uk-radii-md");\n    htmlElement.classList.add(__FRANKEN__.shadows || "uk-shadows-md");\n    htmlElement.classList.add(__FRANKEN__.font || "uk-font-sm");',),{}),
 script(('',),{'src': 'https://cdn.jsdelivr.net/npm/franken-ui@2.1.0-next.14/dist/js/core.iife.js', 'type': 'module'}),
 script(('',),{'src': 'https://cdn.jsdelivr.net/npm/franken-ui@2.1.0-next.14/dist/js/icon.iife.js', 'type': 'module'}),
 script((),{'src': 'https://cdn.jsdelivr.net/npm/htmx.org@2.0.4/dist/htmx.min.js'}),
 script((),{'src': 'https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js'}),
 script(("\n    function sendmsg() {\n        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');\n    }\n    window.onload = function() {\n        sendmsg();\n        document.body.addEventListener('htmx:afterSettle',    sendmsg);\n        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);\n    };",),{})]

Testing in a running app

server = JupyUvi(app)
Show = partial(HTMX, app=app)
@rt
def index():
    return Titled('FhVite Test App', 
                  H1('This is a test!'), 
                  Div(Button('Click Me!', cls="uk-btn-primary uk-btn-xs"))
                 )
Show('/')
server.stop()
!rm -rf vite