This commit is contained in:
xion 2024-12-10 01:49:36 +08:00
parent 7173d39a17
commit ad3fe496ef
7 changed files with 153 additions and 22 deletions

View File

@ -1,6 +1,6 @@
{
"name": "browser-apps",
"version": "0.0.1",
"version": "0.0.2",
"description": "",
"main": "index.js",
"scripts": {
@ -29,6 +29,7 @@
},
"devDependencies": {
"@build/tailwind": "1.0.2-alpha-2",
"@kevisual/types": "^0.0.3",
"@types/lodash-es": "^4.17.12",
"@types/react": "^19.0.1",
"@types/umami": "^2.10.0",

View File

@ -1,6 +1,5 @@
import { QueryRouterServer } from '@kevisual/router/browser';
import { useContextKey } from '@kevisual/store/config';
import { useConfigKey } from '@kevisual/store/config';
import { EventEmitter } from 'eventemitter3';
export const app = useContextKey('app', () => {

View File

@ -8,33 +8,36 @@ import './page/index.css';
import './main.css';
import { Page } from '@kevisual/store/page';
import { AiChat } from './page/AiChat';
import { useContextKey } from '@kevisual/store/config';
const main = () => {
start();
};
main();
const page = new Page({
const page = useContextKey('page', () => {
return new Page({
path: '',
key: '',
basename: '',
});
});
page.addPage('/', 'home');
page.addPage('/ai', 'ai');
page.addPage('/list', 'list');
page.subscribe('home', (page) => {
const div = document.createElement('div');
div.className = 'text-4xl text-center p-4 bg-blue-200';
div.innerHTML = 'Browser Apps';
document.body.appendChild(div);
page.subscribe('home', async (page) => {
const module = await import('./routes/home.ts');
module?.route(page);
});
page.subscribe('ai', (page) => {
const aiChat = AiChat();
console.log(aiChat);
document.body.appendChild(aiChat);
page.subscribe('ai', async (page) => {
const module = await import('./routes/ai.ts');
module?.route();
});
page.subscribe('list', async (page) => {
const module = await import('./routes/list.ts');
module?.route();
});

7
src/routes/ai.ts Normal file
View File

@ -0,0 +1,7 @@
import { AiChat } from '../page/AiChat';
export const route = () => {
const aiChat = AiChat();
console.log(aiChat);
document.body.appendChild(aiChat);
};

92
src/routes/home.ts Normal file
View File

@ -0,0 +1,92 @@
import { QueryRouterServer } from '@kevisual/router/browser';
import { useContextKey } from '@kevisual/store/config';
type InitFn = () => any;
type InitModule = {
init?: boolean;
loaded?: boolean;
fn?: InitFn;
key?: string;
};
class UseInit {
modules = new Map<string, InitModule>();
callbacks = new Map<string, InitFn>();
constructor() {}
async run(fn: InitFn, key: string, force = false) {
if (this.modules.has(key)) {
const module = this.modules.get(key)!;
if (module.init) {
if (force) {
await module.fn?.();
}
return;
}
await module.fn?.();
module.init = true;
} else {
this.modules.set(key, {
init: true,
fn,
key,
});
await fn();
}
}
}
const module = useContextKey<UseInit>('module', () => {
return new UseInit();
});
const app = useContextKey<QueryRouterServer>('app');
const loadApps = async () => {
app
.route({
path: 'dev',
key: 'preview-container',
})
.define(async (ctx) => {
const data = ctx.query?.data || {};
const code = data.code || '';
if (!code) {
ctx.throw?.(400, 'code is required');
}
const url = URL.createObjectURL(new Blob([code], { type: 'application/javascript' }));
console.log('dev route');
const module = await import(url);
URL.revokeObjectURL(url);
if (module?.render) {
module.render();
}
})
.addTo(app);
};
export const route = async (page?: any) => {
console.log('home route page', page);
console.log('home route app', app);
const div = document.createElement('div');
div.className = 'text-4xl text-center p-4 bg-blue-200';
div.innerHTML = 'Browser Apps';
div.onclick = () => {
location.href = '/list';
};
document.body.appendChild(div);
module.run(() => {
loadApps();
}, 'home');
const res = await app.call({
path: 'dev',
key: 'preview-container',
payload: {
data: {
code: `
export const render = () => {
const div = document.createElement('div');
div.className = 'text-4xl text-center p-4 bg-blue-200';
div.innerHTML = 'Browser Apps Preview';
document.body.appendChild(div);
}`,
},
},
});
console.log('res', res);
};

13
src/routes/list.ts Normal file
View File

@ -0,0 +1,13 @@
import { useContextKey } from '@kevisual/store/config';
import { Page } from '@kevisual/store/page';
export const route = () => {
console.log('list route');
const div = document.createElement('div');
div.className = 'text-4xl text-center p-4 bg-blue-200';
div.innerHTML = 'Browser Apps List';
div.onclick = () => {
location.href = '/';
};
document.body.appendChild(div);
};

View File

@ -4,10 +4,12 @@ import path from 'path';
import tailwindcss from 'tailwindcss';
import autoprefixer from 'autoprefixer';
import nesting from 'tailwindcss/nesting';
import pkgs from './package.json' with { type: 'json' };
const version = pkgs.version || '0.0.1';
const isDev = process.env.NODE_ENV === 'development';
console.log('isDev', isDev);
export default defineConfig({
root: '.',
// plugins: [react()],
css: {
postcss: {
// @ts-ignore
@ -26,15 +28,29 @@ export default defineConfig({
// '@kevisual/router/browser': 'https://kevisual.xiongxiao.me/system/lib/router-browser.js', // 将本地路径替换为远程 URL
},
},
base: './',
build: {
minify: false,
outDir: './dist',
rollupOptions: {
external: ['react', 'react-dom'],
external: ['react'],
output: {
chunkFileNames: (chunkInfo) => {
if(isDev) {
return '[name].js';
}
if (chunkInfo.facadeModuleId && chunkInfo.facadeModuleId.includes('/routes/')) {
// 对以 routes/ 开头的代码分块使用不带 hash 的命名
return `routes/[name]-${version}.js`;
}
// 其他代码分块继续使用 hash
return '[name].[hash].js';
},
},
},
},
optimizeDeps: {
exclude: ['react', 'react-dom'], // 排除 react 和 react-dom 以避免打包
exclude: ['react'], // 排除 react 和 react-dom 以避免打包
},
esbuild: {
jsxFactory: 'h',