πŸš€ АвтоматичСская конвСртация React Π² Vue: избавляСмся ΠΎΡ‚ Ρ€ΡƒΡ‡Π½ΠΎΠ³ΠΎ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π°

#react#vue#frontend#compiler#typescript

TL;DR

Source-to-source компилятор для автоматичСской ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚Π°Ρ†ΠΈΠΈ React-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² (JSX/TSX) Π² Vue 3 SFC с <script setup>. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Ρ…ΡƒΠΊΠΈ, JSX-Ρ‚Ρ€Π°Π½ΡΡ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΈ основныС React-ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½Ρ‹. Π Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Ρ‡Π΅Ρ€Π΅Π· CLI ΠΈΠ»ΠΈ API, сокращая врСмя ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ экосистСмами.

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅: ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠ²ΠΎΠ³ΠΎ lock-in

Π’ соврСмСнном frontend-Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ смСна стСка часто ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ ΠΏΠΎΠ»Π½Ρ‹ΠΉ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΊΠΎΠ΄ΠΎΠ²ΠΎΠΉ Π±Π°Π·Ρ‹. Π’ΠΈΠΏΠΈΡ‡Π½Ρ‹Π΅ сцСнарии:

Π ΡƒΡ‡Π½ΠΎΠΉ пСрСнос ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²:

  1. Π’Ρ€ΡƒΠ΄ΠΎΠ΅ΠΌΠΊΠΈΠΉ процСсс с высоким риском ошибок
  2. Π’Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π³Π»ΡƒΠ±ΠΎΠΊΠΎΠ³ΠΎ знания ΠΎΠ±Π΅ΠΈΡ… экосистСм
  3. Π‘ΠΎΠ·Π΄Π°Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ с ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΎΠΉ когСрСнтности

Π‘ΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ (AI tools, regex-ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚Π΅Ρ€Ρ‹) часто Π΄Π°ΡŽΡ‚ Π½Π΅ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚. ΠœΡ‹ ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅ΠΌ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Ρ‡Π΅Ρ€Π΅Π· настоящий компилятор с ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΌ прСдставлСниСм (IR).

Как Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ трансформация

ΠšΠΎΠΌΠΏΠΈΠ»ΡΡ‚ΠΎΡ€Π½Ρ‹ΠΉ pipeline

// ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚Π°Ρ†ΠΈΠΈ Ρ‡Π΅Ρ€Π΅Π· API
import { convertCode } from "cross-framework"

const vueCode = convertCode({
  from: "react",
  to: "vue",
  sourceCode: reactSource,
  filename: "Component.tsx",
})

Π­Ρ‚Π°ΠΏΡ‹ прСобразования:

  1. Parse: Babel-based парсинг исходного ΠΊΠΎΠ΄Π° Π² AST
  2. Transform: созданиС framework-agnostic IR
  3. Emit: гСнСрация Vue SFC с Composition API

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΡ‹Π΅ конструкции

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹

// React input
export default function Button({ children }) {
  return <button className="btn">{children}</button>
}

// Vue output
<template>
  <button class="btn"><slot /></button>
</template>

<script setup>
defineProps(['children'])
</script>

Π₯ΡƒΠΊΠΈ ΠΈ Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ

ReactVue 3
useStateref
useRefref + template ref
useMemocomputed
useEffectwatch/watchEffect

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ трансформации:

// React
function Counter() {
  const [count, setCount] = useState(0)
  useEffect(() => console.log(count), [count])
  
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>
}

// Vue
<template>
  <button @click="count++">{{ count }}</button>
</template>

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)
watch(count, () => console.log(count.value))
</script>

ΠŸΡ€Π°ΠΊΡ‚ΠΈΡ‡Π΅ΡΠΊΠΎΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅

CLI Usage

npx cross-framework convert \
  --from react \
  --to vue \
  --out-dir ./vue-components \
  ./src/components/**/*.tsx

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ Π² сборку

Для постСпСнной ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ»Π°Π³ΠΈΠ½ для Vite/Rollup:

// vite.config.js
import { crossFramework } from 'cross-framework/vite'

export default {
  plugins: [
    crossFramework({
      from: 'react',
      to: 'vue'
    })
  ]
}

ΠžΠ³Ρ€Π°Π½ΠΈΡ‡Π΅Π½ΠΈΡ ΠΈ roadmap

Π’Π΅ΠΊΡƒΡ‰ΠΈΠ΅ constraints:

ΠŸΠ»Π°Π½Ρ‹ развития:

  1. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Class Components β†’ Options API
  2. Врансформация React Router β†’ Vue Router
  3. ΠšΠΎΠ½Π²Π΅Ρ€Ρ‚Π°Ρ†ΠΈΡ Redux β†’ Pinia/Vuex

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Source-to-source компиляция ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ pragmatic approach ΠΊ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ΅ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊΠΎΠ²ΠΎΠΉ ΠΌΠΈΠ³Ρ€Π°Ρ†ΠΈΠΈ. Π₯отя инструмСнт Π½Π΅ ΠΏΠΎΠΊΡ€Ρ‹Π²Π°Π΅Ρ‚ 100% use cases, ΠΎΠ½:

Для слоТных ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌ:

  1. ΠΠ°Ρ‡Π°Ρ‚ΡŒ с Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ²
  2. ΠŸΠΎΡΡ‚Π΅ΠΏΠ΅Π½Π½ΠΎ Ρ€Π°ΡΡˆΠΈΡ€ΡΡ‚ΡŒ coverage
  3. Π˜Π½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² CI для ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ консистСнтности

Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚ особСнно ΠΏΠΎΠ»Π΅Π·Π΅Π½ для:

# ΠŸΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π΅
npm install cross-framework
npx cross-framework convert ./your-component.tsx

Как next-step β€” ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅ΠΌ ΠΏΠΎΡΠΊΡΠΏΠ΅Ρ€ΠΈΠΌΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ с ΠΊΠΎΠ½Π²Π΅Ρ€Ρ‚Π°Ρ†ΠΈΠ΅ΠΉ Π΄ΠΈΠ·Π°ΠΉΠ½-систСм ΠΈ провСсти benchmark ΠΏΠΎ ΡΡ€Π°Π²Π½Π΅Π½ΠΈΡŽ с Ρ€ΡƒΡ‡Π½Ρ‹ΠΌ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ΠΎΠΌ.


Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: https://dev.to/parsajiravand/stop-rewriting-components-convert-react-to-vue-automatically-pfc