Замена EsBuild StartService
Я новичок в esBuild и ReactJS, и, следуя руководству, я решил создать собственное приложение CLI Transpiling. Я дошел до того, что ввожу текст в текстовое поле, но на консоли в клиенте появилось следующее сообщение об ошибке. Версия хоста «0.8.27» не соответствует двоичной версии «0.9.0». Я знаю, что использую старую версию, я попытался сначала найти способ решить проблему, просмотрев документацию, поскольку они полностью выбросили метод startService() в новой версии. Но я не смог найти никакого возможного решения моей проблемы, есть ли кто-нибудь, кто может помочь мне решить эту проблему. Вот мой код, который должен запустить транспилинг:
const startService = async () => {
ref.current = await esbuild.startService({
worker: true,
wasmURL: '/esbuild.wasm'
})
}
useEffect(() => {
startService()
}, [])
const onClick = async () => {
if (!ref.current) {
return;
}
const result = await ref.current.build({
entryPoints: ['index.js'],
bundle: true,
write: false,
plugins: [unpkgPathPlugin()]
})
console.log(result );
setCode(result)
}
5 ответов
Документация по запуску esbuild в браузере находится здесь: https://esbuild.github.io/api/#running-in-the-browser . В версии 0.9.0
esbuild.startService()
стал
esbuild.initialize()
а также
service.build()
стал
esbuild.build()
(т.е. явный объект службы исчез). Итак, обновленный код может выглядеть примерно так:
const startService = async () => {
await esbuild.initialize({
worker: true,
wasmURL: '/esbuild.wasm'
})
ref.current = true
}
useEffect(() => {
startService()
}, [])
const onClick = async () => {
if (!ref.current) {
return;
}
const result = await esbuild.build({
entryPoints: ['index.js'],
bundle: true,
write: false,
plugins: [unpkgPathPlugin()]
})
console.log(result);
setCode(result)
}
Обратите внимание, что при работе в браузере асинхронный API недоступен. Кроме того, я не хотел бросать «уже инициализировано» каждый раз, когда я перезагружаюсь во время редактирования. Вот как я это настроил:
import { useState, useEffect } from 'react';
import './App.css';
import * as esbuild from 'esbuild-wasm';
function App() {
const [input, setInput] = useState('');
const [code, setCode] = useState('');
useEffect(() => {
// This ugly code is to avoid calling initialize() more than once
try {
esbuild.build({});
} catch (error) {
if (error instanceof Error && error.message.includes('initialize')) {
esbuild.initialize({
worker: false,
wasmURL: '/esbuild.wasm',
});
} else {
throw error;
}
}
}, []);
const onClick = () => {
esbuild
.transform(input, {
loader: 'jsx',
target: 'es2015',
})
.then((result) => {
setCode(result.code);
});
};
return (
<div className="App">
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}></textarea>
<div>
<button onClick={onClick}>Submit</button>
</div>
<pre>{code}</pre>
</div>
);
}
export default App;
Ребят, у меня есть решение получше, можно горячую перезагрузку и без ошибок.
const startService = async () => {
if (!window.isEsbuildRunning) {
await esbuild.initialize({
worker: true,
wasmURL: '/esbuild.wasm'
})
}
window.isEsbuildRunning = true;
ref.current = true
}
useEffect(() => {
startService()
}, [])
const onClick = async () => {
if (!ref.current) {
return;
}
const result = await esbuild.build({
entryPoints: ['index.js'],
bundle: true,
write: false,
plugins: [unpkgPathPlugin()]
})
console.log(result);
setCode(result)
}
Придумал лучший способ:
import * as esbuild from "esbuild-wasm";
const startService = (() => {
let esBuildRef: any;
return async() => {
if (esBuildRef) {
return esBuildRef
} else {
await esbuild.initialize({
worker: true,
wasmURL: "./esbuild.wasm"
});
esBuildRef = esbuild;
return esBuildRef;
}
}
})()
export default startService;
используйте его как
import { useState, useEffect } from 'react';
import startService from './plugins/esbuild';
export default function Home() {
const [input, setInput] = useState('');
const [code, setCode] = useState('');
const submitHandler = async() => {
const esBuildRef = await startService();
console.log(esBuildRef);
const result = await esBuildRef.transform(input, {
loader: 'jsx',
target: 'es2015'
})
setCode(result.code);
}
return (
<main>
<textarea value = {input} onChange={(e) => setInput(e.target.value)}>
</textarea>
<div onClick={submitHandler}>
Submit
</div>
<pre>
{code}
</pre>
</main>
)
}
Шаблон синглтон
Я догадываюсь, откуда взялся этот вопрос. Предыдущий ответ верен, но если в
setCode(result)
затем прокомментируйте это некоторое время.