ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Vue application with React component
    Frameworks, Platforms and Libraries/Vue.js 2023. 10. 8. 16:09

    현재 회사에서 운영 중인 세 개의 application 중 두 개의 application의 경우 React, 남은 하나의 application는 Vue.js 기반이었습니다. 운영 중인 Vue.js 기반의 application을 React로 포팅할려는 니즈가 있었지만 한 번에 빅뱅 하기엔 시간이 부족하여 점진적으로 React로 포팅하고 신규 기능 페이지의 경우는 미리 React로 구성하기로 했습니다. 그렇다 보니 기존 Vue.js 기반의 application에 React component를 띄워야 했고 이때 사용한 방식을 포스팅하고자 합니다.

     

    react → vue 변환 모듈

    ※ Vue는 Class Component 형태로 작성되었습니다.

    ReactDOMClient의 createRoot()를 통해 렌더링 되는 DOM의 위치를 Vue.js 기반의 application으로 향하게 합니다.

    // glue.tsx
    import React from 'react';
    import { createRoot } from 'react-dom/client';
    
    // import { Provider } from 'react-redux';
    // import { store } from './store';
    
    import './styles/index.scss';
    
    export function mount(
      targetNode: HTMLElement,
      component: React.FunctionComponent,
    ) {
      const reactElement = React.createElement(component);
      const root = createRoot(targetNode!);
      root.render(reactElement);
    
      // 필요에 따라 store도 임시로 연결할 수 있습니다.
      // root.render(<Provider store={store}>{reactElement}</Provider>);
    
      return root;
    }
    // Bridge.ts
    // react => vue
    import { Component, Vue } from 'vue-property-decorator';
    import { Root } from 'react-dom/client';
    
    import { mount } from './glue';
    
    @Component({
      name: 'Bridge',
    })
    export default class extends Vue {
      reactRoot: Root | null = null;
    
      setComponent(component: React.FunctionComponent) {
        this.reactRoot = mount(this.$el as HTMLElement, component);
      }
    
      beforeDestroy() {
        this.reactRoot?.unmount();
      }
    }

     

    적용

    // Component.tsx
    function Component() {
      return <div>Vue application with React component</div>;
    }
    
    export default Component;
    // ComponentBridge.vue
    <template>
      <div></div>
    </template>
    
    <script lang="ts">
    import { Component } from 'vue-property-decorator';
    
    import Component from './Component';
    import Bridge from './Bridge';
    
    @Component({
      name: 'ComponentBridge',
    })
    export default class extends Bridge {
      mounted() {
        this.setComponent(Component);
      }
    }
    </script>

    router를 통해 ComponentBridge 페이지를 보면 정상적으로 출력이 됩니다.

     

    후기

    Vue.js 기반의 application을 당장 React로 빅뱅 할 시간이 부족하여 신규 기능 페이지만이라도 미리 React로 구성하기 위해 사용한 방식이었습니다. 하나의 application에서 두 개의 프론트엔드 프레임워크가 공존하는 건 좋지 않지만 이러한 방식을 통해 점진적으로 포팅할 수 있었습니다. 그래도 역시나 빠른 시일 내에 완전히 포팅을 완료해야겠습니다.

     

    'Frameworks, Platforms and Libraries > Vue.js' 카테고리의 다른 글

    Vue Class Component with Decorator  (0) 2023.09.16
Designed by Tistory.