add demo
This commit is contained in:
parent
7173d39a17
commit
ad3fe496ef
@ -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",
|
||||
|
@ -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', () => {
|
||||
|
35
src/main.tsx
35
src/main.tsx
@ -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({
|
||||
path: '',
|
||||
key: '',
|
||||
basename: '',
|
||||
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
7
src/routes/ai.ts
Normal 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
92
src/routes/home.ts
Normal 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
13
src/routes/list.ts
Normal 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);
|
||||
};
|
@ -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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user