03 Minimum Client SFC
In this section, we'll look at how to mount Vue App in client side. Full Code is available at 3-client-sfc
First, create a entry.client.ts
ts
import { createSSRApp } from 'vue'
import App from './App.vue'
const initApp = async () => {
const app = createSSRApp(App)
app.mount('#__nuxt')
}
initApp().catch(console.error)Next, rewrite build function to build also entry.client.ts
We will use mergeConfig to merge defaultConfig and config specific to client and server as it is used in Nuxt.
ts
import { join } from 'node:path'
import { build as _build, mergeConfig, type InlineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export const build = async () => {
try {
const defaultConfig = {
plugins: [vue()],
build: {
rollupOptions: {
output: {
format: 'esm',
dir: join(import.meta.dirname, 'dist'),
},
preserveEntrySignatures: 'exports-only',
treeshake: false,
},
emptyOutDir: false,
},
} satisfies InlineConfig
const clientConfig = mergeConfig(defaultConfig, {
build: {
rollupOptions: {
input: join(import.meta.dirname, 'entry.client.ts'),
output: {
entryFileNames: 'entry.client.js',
},
},
},
} satisfies InlineConfig)
await _build(clientConfig)
const severConfig = mergeConfig(defaultConfig, {
build: {
rollupOptions: {
input: join(import.meta.dirname, 'entry.server.ts'),
output: {
entryFileNames: 'entry.server.js',
},
},
},
} satisfies InlineConfig)
await _build(severConfig)
console.log('Build completed successfully!')
}
catch (error) {
console.error('Build failed:', error)
process.exit(1)
}
}Add a id and script to html to mount the app in client side
ts
function htmlTemplate({ HEAD, APP }: HtmlTemplateParams): string {
return `
<!DOCTYPE html>
<html>
<head>
${HEAD}
</head>
<body>
<div id="__nuxt">${APP}</div>
<script type="module" src="/entry.client.js"></script>
</body>
</html>
`
}Serve client.entry.js script in specific route request
ts
export const renderMiddleware = defineEventHandler(async (event) => {
if (!renderer) await setupRenderer()
const { req, res } = event.node
if (req.url === '/entry.client.js') {
const code = readFileSync(
join(import.meta.dirname, 'dist/entry.client.js'),
'utf-8',
)
res.setHeader('Content-Type', 'application/javascript')
res.end(code)
}
const rendered = await renderer.renderToString({})
const data = renderHTML(rendered)
res.setHeader('Content-Type', 'text/html;charset=UTF-8')
res.end(data, 'utf-8')
})Run the server
If you run the server, you can see Count button works because we have mounted the app in client side.
