This commit is contained in:
2025-04-01 13:51:33 +08:00
parent ad346ee25b
commit 3ac31e4d09
8 changed files with 254 additions and 15 deletions

63
src/files/demo.ts Normal file
View File

@@ -0,0 +1,63 @@
/** @type {import('@webcontainer/api').FileSystemTree} */
import { WebContainer } from '@webcontainer/api';
// Call only once
const webcontainerInstance = await WebContainer.boot();
export const files = {
'package.json': {
file: {
contents: `
{
"name": "vite-starter",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^4.0.4"
}
}`,
},
},
'index.html': {
file: {
contents: `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>`,
},
},
};
await webcontainerInstance.mount(files);
async function startDevServer() {
const installProcess = await webcontainerInstance.spawn('npm', ['install']);
const installExitCode = await installProcess.exit;
if (installExitCode !== 0) {
throw new Error('Unable to run npm install');
}
// `npm run dev`
await webcontainerInstance.spawn('npm', ['run', 'dev']);
// webcontainerInstance.on('server-ready', (port, url) => (iframeEl.src = url));
}
startDevServer();

54
src/files/files.ts Normal file
View File

@@ -0,0 +1,54 @@
export const files = {
'package.json': {
file: {
contents: `
{
"name": "vite-starter",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^4.0.4",
"tailwindcss": "^3.3.5"
}
}`,
},
},
'a.js': {
file: {
contents: `
console.log('Hello, world!');
`,
},
},
'style.css': {
file: {
contents: `
@import 'tailwindcss';
`,
},
},
'index.html': {
file: {
contents: `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app">这是一个app的内容</div>
<script type="module" src="a.js"></script>
</body>
</html>`,
},
},
};

74
src/files/main.ts Normal file
View File

@@ -0,0 +1,74 @@
import { WebContainer } from '@webcontainer/api';
import { files } from './files';
/** @type {import('@webcontainer/api').WebContainer} */
let webcontainerInstance;
/** @type {HTMLIFrameElement | null} */
const iframeEl = document.querySelector('iframe');
/** @type {HTMLTextAreaElement | null} */
const textareaEl = document.querySelector('textarea');
window.addEventListener('load', async () => {
// textareaEl.value = files['index.js'].file.contents;
// textareaEl.addEventListener('input', (e) => {
// writeIndexJS(e.currentTarget.value);
// });
const hasLoaded = document.querySelector('.container') !== null;
if (hasLoaded) {
return;
}
console.log('@hasLoaded', document.querySelector('.container'), hasLoaded);
document.querySelector('#root')!.innerHTML = `
<div class="container">
<div class="editor">
<textarea>I am a textarea</textarea>
</div>
<div class="preview">
<iframe src=""></iframe>
</div>
</div>
`;
console.log('@root', document.querySelector('#root'));
console.log('@window.addEventListener', document.querySelector('#root'));
// Call only once
webcontainerInstance = await WebContainer.boot();
await webcontainerInstance.mount(files);
const exitCode = await installDependencies();
if (exitCode !== 0) {
throw new Error('Installation failed');
}
console.log('Installation successful');
startDevServer();
});
async function installDependencies() {
// Install dependencies
const installProcess = await webcontainerInstance.spawn('npm', ['install']);
installProcess.output.pipeTo(
new WritableStream({
write(data) {
console.log(data);
},
}),
);
// Wait for install command to exit
return installProcess.exit;
}
async function startDevServer() {
// Run `npm run start` to start the Express app
await webcontainerInstance.spawn('npm', ['run', 'start']);
// Wait for `server-ready` event
webcontainerInstance.on('server-ready', (port, url) => {
console.log('@server-ready', port, url);
const iframe = document.querySelector('iframe');
if (iframe) {
iframe.src = url;
}
});
}