Vue 3 SSR with SFC but without high level solutions

491 views Asked by At

I have pretty small vue 3 app. It's just a login form with very old fashioned lifecycle: it submits the login and password in a synchronous manner. May be i shouldn't use any frontend framework at all, but rather make do with jquery and some server side template engine as in the past. That's the thoughts that keep disturbing me, but i still see benefits in using vue. The idea of SSR in vue 3 is pretty clear, but how to convert my App.vue component (in SFC format) into a single js object like in the example?

I found a lot of very complex high level solutions like nuxt and vite-plugin-ssr, but I think they are too complex for such a small task.

About the app component itself. It has styles in separate scss files which are used as CSS modules, it has some styles in the component itself and it uses a part from bootstrap. Also it has no routing and other stuff related to large applications.

index.js:

import { createApp } from 'vue'
import App from './App.vue'
import '@styles/bootstrap/index.scss'
import '@styles/index.scss'

createApp(App).mount('#app')

App.vue:

<script setup>
  // App.vue
  import { ref, watchEffect } from 'vue'
  import modal from '@styles/modules/modal.module.scss'
  import spacing from '@styles/modules/spacing.module.scss'
  import card from '@styles/modules/card.module.scss'

  // Some code
  // ...
  </script>

  <template>
    <!-- Some HTML -->
  </template>

  <style lang="scss">
    // Some style
  </style>
2

There are 2 answers

0
Tolbxela On

For a very simple Vue.js app you don't need a lot.

You could put it all on one HTML page rendered in backend. See the playground.

For Sass you will need a preprocessor.

<html>
<head>
    <!-- Global CSS Styles -->
    <link rel="stylesheet" href="styles/style.css" />
    <!-- Current Page CSS-->
    <style>
        #app { line-height: 1.75; }
        [v-cloak] { display: none; }
    </style>
</head>
<body>
    <!-- Vue App Template -->
    <div id="app" v-cloak>
        Counter: {{counter}}
        <button @click="plusOne">+1</button>
    </div>
    <!-- Vue.js -->
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
    <!-- Vue App Scripts -->
    <script>
        const { createApp, ref } = Vue
        const App = {
            setup(props, context) {
                //  <-- hier everything from <script setup> except imports
                //
                const counter = ref(0)
                const plusOne = () => counter.value++;
                return { counter, plusOne }
            }
        }
        createApp(App).mount('#app')
    </script>
</body>
</html>

0
Serge On

The short answer for the question "How to SSR the app that is not as simple as a single javascript object" is to build it and import all the functions you need on the backend from the entry point of the bundle. I export render and createApp (that calls createSSRApp inside) in entry-server.js and import them on the backend from my dist folder. This is about working without viteDevServer. With viteDevServer things get more complicated (i didn't manage to get vite's express middleware to work with fastify by now). Detailed step-by-step instructions that helped me a lot can be found here.