mirror of
https://github.com/tuono-labs/tuono
synced 2026-07-25 21:02:45 -07:00
feat: generate main file from tuono dev cmd
This commit is contained in:
+10
-5
@@ -1,6 +1,8 @@
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::process::Command;
|
||||
mod axum_source_builder;
|
||||
|
||||
mod source_builder;
|
||||
use source_builder::{bundle_axum_source, create_client_entry_files};
|
||||
mod watch;
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
@@ -24,11 +26,14 @@ pub fn cli() {
|
||||
let args = Args::parse();
|
||||
|
||||
match args.action.unwrap() {
|
||||
Actions::Dev => watch::watch().unwrap(),
|
||||
Actions::Dev => {
|
||||
bundle_axum_source();
|
||||
create_client_entry_files().unwrap();
|
||||
watch::watch().unwrap();
|
||||
}
|
||||
Actions::Build => {
|
||||
axum_source_builder::bundle_axum_source();
|
||||
|
||||
println!("Build JS source");
|
||||
bundle_axum_source();
|
||||
create_client_entry_files().unwrap();
|
||||
let mut vite_build = Command::new("./node_modules/.bin/tuono-build-prod");
|
||||
let _ = &vite_build.output().unwrap();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,30 @@
|
||||
use glob::glob;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
const ROOT_FOLDER: &'static str = "src/routes";
|
||||
const DEV_FOLDER: &'static str = ".tuono";
|
||||
const SERVER_ENTRY_DATA: &'static str = "// File automatically generated by tuono
|
||||
|
||||
import { routeTree } from './routeTree.gen'
|
||||
import { serverSideRendering } from 'tuono/ssr'
|
||||
|
||||
export const renderFn = serverSideRendering(routeTree)
|
||||
";
|
||||
|
||||
const CLIENT_ENTRY_DATA: &'static str = "// File automatically generated by tuono
|
||||
|
||||
import { hydrate } from 'tuono/hydration'
|
||||
|
||||
// Import the generated route tree
|
||||
import { routeTree } from './routeTree.gen'
|
||||
|
||||
hydrate(routeTree)
|
||||
";
|
||||
|
||||
enum Mode {
|
||||
Prod,
|
||||
@@ -159,3 +178,14 @@ pub fn bundle_axum_source() {
|
||||
|
||||
create_main_file(&base_path, &bundled_file);
|
||||
}
|
||||
|
||||
pub fn create_client_entry_files() -> io::Result<()> {
|
||||
let dev_folder = Path::new(DEV_FOLDER);
|
||||
let mut server_entry = fs::File::create(&dev_folder.join("server-main.tsx"))?;
|
||||
let mut client_entry = fs::File::create(&dev_folder.join("client-main.tsx"))?;
|
||||
|
||||
server_entry.write(SERVER_ENTRY_DATA.as_bytes())?;
|
||||
client_entry.write(CLIENT_ENTRY_DATA.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -6,7 +6,7 @@ use watchexec::Watchexec;
|
||||
use watchexec_signals::Signal;
|
||||
use watchexec_supervisor::job::start_job;
|
||||
|
||||
use crate::axum_source_builder::bundle_axum_source;
|
||||
use crate::source_builder::bundle_axum_source;
|
||||
|
||||
// What is the development pipeline?
|
||||
//
|
||||
@@ -22,7 +22,6 @@ use crate::axum_source_builder::bundle_axum_source;
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn watch() -> Result<()> {
|
||||
bundle_axum_source();
|
||||
let (watch_client, _) = start_job(Arc::new(Command {
|
||||
program: Program::Exec {
|
||||
prog: "node_modules/.bin/tuono-dev-watch".into(),
|
||||
|
||||
@@ -25,6 +25,26 @@
|
||||
"default": "./dist/cjs/build/index.js"
|
||||
}
|
||||
},
|
||||
"./ssr": {
|
||||
"import": {
|
||||
"types": "./dist/esm/ssr/index.d.ts",
|
||||
"default": "./dist/esm/ssr/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/cjs/ssr/index.d.ts",
|
||||
"default": "./dist/cjs/ssr/index.js"
|
||||
}
|
||||
},
|
||||
"./hydration": {
|
||||
"import": {
|
||||
"types": "./dist/esm/hydration/index.d.ts",
|
||||
"default": "./dist/esm/hydration/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/cjs/ssr/index.d.ts",
|
||||
"default": "./dist/cjs/ssr/index.js"
|
||||
}
|
||||
},
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
@@ -65,6 +85,7 @@
|
||||
"@types/babel__core": "^7.20.5",
|
||||
"@types/node": "^20.12.7",
|
||||
"@vitejs/plugin-react-swc": "^3.7.0",
|
||||
"fast-text-encoding": "^1.0.6",
|
||||
"prettier": "^3.2.4",
|
||||
"vite": "^5.2.11",
|
||||
"zustand": "4.4.7"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'vite/modulepreload-polyfill'
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import { RouterProvider, createRouter } from '../router'
|
||||
|
||||
export function hydrate(routeTree: any) {
|
||||
// Create a new router instance
|
||||
const router = createRouter({ routeTree })
|
||||
|
||||
// Render the app
|
||||
const rootElement = document.getElementById('__tuono')!
|
||||
|
||||
ReactDOM.hydrateRoot(
|
||||
rootElement,
|
||||
<React.StrictMode>
|
||||
<RouterProvider router={router} />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import 'fast-text-encoding' // Mandatory for React18
|
||||
import * as React from 'react'
|
||||
import { renderToString, renderToStaticMarkup } from 'react-dom/server'
|
||||
import { RouterProvider } from '../router'
|
||||
import { createRouter } from '../router'
|
||||
|
||||
export function serverSideRendering(routeTree: any) {
|
||||
return function render(payload: string | undefined): string {
|
||||
const props = payload ? JSON.parse(payload) : {}
|
||||
|
||||
const router = createRouter({ routeTree }) // Render the app
|
||||
|
||||
const app = renderToString(
|
||||
<RouterProvider router={router} serverProps={props} />,
|
||||
)
|
||||
|
||||
const developmentScript = `<script type="module">
|
||||
import RefreshRuntime from 'http://localhost:3001/@react-refresh'
|
||||
RefreshRuntime.injectIntoGlobalHook(window)
|
||||
window.$RefreshReg$ = () => {}
|
||||
window.$RefreshSig$ = () => (type) => type
|
||||
window.__vite_plugin_react_preamble_installed__ = true
|
||||
</script>
|
||||
<script type="module" src="http://localhost:3001/@vite/client"></script>
|
||||
<script type="module" src="http://localhost:3001/client-main.tsx"></script>`
|
||||
|
||||
return `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Playground</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="__tuono">${app}</div>
|
||||
${renderToStaticMarkup(
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `window.__TUONO_SSR_PROPS__=${payload}`,
|
||||
}}
|
||||
/>,
|
||||
)}
|
||||
${developmentScript}
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,12 @@ const config = defineConfig({
|
||||
export default mergeConfig(
|
||||
config,
|
||||
tanstackBuildConfig({
|
||||
entry: ['./src/index.ts', './src/build/index.ts'],
|
||||
entry: [
|
||||
'./src/index.ts',
|
||||
'./src/build/index.ts',
|
||||
'./src/ssr/index.tsx',
|
||||
'./src/hydration/index.tsx',
|
||||
],
|
||||
srcDir: './src',
|
||||
}),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user