vue3项目之VUE-SSR 第一次改造方案(二)

VUE-SSR 第一次改造方案(二)

先实现客户端渲染
  • main.ts

实现导出一个 createApp 函数,再去 router、vuex 中实现类似的函数 createSSR...()

下面是全新的 mian.ts

import { createSSRApp } from 'vue'
import App from './App.vue'
import './style.css'

import { createSSRRouter } from './router'
import { createSSRStore, key } from './store'

import ElementPlus from 'element-plus'
import { ID_INJECTION_KEY } from 'element-plus'
import 'element-plus/dist/index.css'

import { createSSRI18n } from '@/language/i18n'

import '@/mock/mockServe'

export function createApp() {
    const app = createSSRApp(App)
    
    // 路由
    const router = createSSRRouter()
    app.use(router)
    
    // vuex
    const store = createSSRStore()
    app.use(store, key)
    
    // ElementPlus
    app.use(ElementPlus)
    app.provide(ID_INJECTION_KEY, {
        prefix: Math.floor(Math.random() * 10000),
        current: 0,
    })
    
    // 语言配置
    const i18n = createSSRI18n()
    app.use(i18n)

    return { app, router, store }
}

router 导出长这样

export function createSSRRouter() {

    return createRouter({
        history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
        routes,
    })

}
  • entry-client.ts

客户端入口文件,(之前一直是 main.ts为入口文件,现在入口文件需要区分)

这里主要用于客户端初始化

import { createApp } from "./main"
import { airbnbDB } from '@/db/index';
import stores from '@/db/index'


const { app, router, store } = createApp()

router.beforeEach(async function () {
    
    // 页面刷新时执行该回调函数
    
    // 一般用于初始化客户端的 vuex 数据
    ...
    
}) 


router.isReady().then(function() {
    app.mount('#app')
})
  • index.html

将首页的渲染方式改成 entry-client.ts 客户端渲染

并使用 <!--ssr-outlet--> 用作服务端渲染的 HTML 的占位符

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Airbnb</title>
</head>

<body>
    <div id="app"><!--ssr-outlet--></div>
    <script type="module" src="/src/entry-client.ts"></script>
</body>

</html>
5.2.3 再实现服务端渲染

这里用的 vite 服务端渲染模板!!

  • server.js

需要先下载 express 服务器框架,下面是模板

import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import express from 'express'
import { createServer as createViteServer } from 'vite'

const __dirname = path.dirname(fileURLToPath(import.meta.url))

async function createServer() {
    const app = express()

    // 以中间件模式创建 Vite 应用,这将禁用 Vite 自身的 HTML 服务逻辑
    // 并让上级服务器接管控制
    const vite = await createViteServer({
        server: { middlewareMode: true },
        appType: 'custom'
    })

    // 使用 vite 的 Connect 实例作为中间件
    // 如果你使用了自己的 express 路由(express.Router()),你应该使用 router.use
    app.use(vite.middlewares)

    app.use('*', async (req, res, next) => {
        const url = req.originalUrl

        try {
            // 1. 读取 index.html
            let template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8')

            // 2. 应用 Vite HTML 转换。这将会注入 Vite HMR 客户端,
            //    同时也会从 Vite 插件应用 HTML 转换。
            //    例如:@vitejs/plugin-react 中的 global preambles
            template = await vite.transformIndexHtml(url, template)

            // 3. 加载服务器入口。vite.ssrLoadModule 将自动转换
            //    你的 ESM 源码使之可以在 Node.js 中运行!无需打包
            //    并提供类似 HMR 的根据情况随时失效。
            const { render } = await vite.ssrLoadModule('/src/entry-server.ts')

            // 4. 渲染应用的 HTML。这假设 entry-server.js 导出的 `render`
            //    函数调用了适当的 SSR 框架 API。
            //    例如 ReactDOMServer.renderToString()
            const appHtml = await render(url)

            // 5. 注入渲染后的应用程序 HTML 到模板中。
            const html = template.replace(`<!--ssr-outlet-->`, appHtml)

            // 6. 返回渲染后的 HTML。
            res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
        } catch (e) {
            // 如果捕获到了一个错误,让 Vite 来修复该堆栈,这样它就可以映射回
            // 你的实际源码中。
            vite.ssrFixStacktrace(e)
            next(e)
        }
    })

    app.listen(5173, function() {
        console.log('服务端渲染进行中...');
    })
}

createServer()
  • entry-server.ts

服务端渲染入口!!!

import { createApp } from "./main"
import { renderToString } from 'vue/server-renderer'

export async function render(url: string) {
    const { app, router } = createApp()

    await router.push(url)
    await router.isReady()

    const appHtml = renderToString(app)
    return appHtml
}
5.2.4 最后选择启动服务

服务端渲染:node server.js

客户端渲染:npm run dev

只需要启动一次即可!vite 都会帮我们自动更新

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要将vue-cli2项目添加ssr打包,需要进行以下步骤: 1. 首先,安装相应的依赖包。在项目根目录下运行以下命令: ``` npm install vue-server-renderer --save npm install webpack-node-externals --save-dev ``` 这样可以安装vue-server-renderer和webpack-node-externals两个依赖包。 2. 创建一个新文件,用于处理服务器端渲染。在项目根目录下创建一个`build`文件夹,并在其中创建一个名为`webpack.server.config.js`的文件。在该文件中,添加以下内容: ```javascript const path = require('path') const webpack = require('webpack') const nodeExternals = require('webpack-node-externals') module.exports = { target: 'node', entry: './src/server.js', // 根据实际文件名修改 output: { filename: 'server.bundle.js', path: path.join(__dirname, '../dist'), libraryTarget: 'commonjs2' }, externals: [nodeExternals()], module: { rules: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ } ] } } ``` 3. 修改package.json文件,添加相应的脚本。在`scripts`字段中添加以下内容: ```json "scripts": { "build:server": "webpack --config build/webpack.server.config.js", "build": "npm run build:server && npm run build:client", "build:client": "vue-cli-service build" } ``` 这样可以添加三个命令:`build:server`用于构建服务器端渲染文件,`build:client`用于构建客户端文件,`build`用于同时构建服务器端和客户端文件。 4. 创建一个服务器端入口文件。在`src`文件夹下创建一个名为`server.js`的文件,并在其中添加以下内容: ```javascript const fs = require('fs') const path = require('path') const express = require('express') const { createBundleRenderer } = require('vue-server-renderer') const server = express() const template = fs.readFileSync(path.resolve(__dirname, '../dist/index.html'), 'utf-8') const serverBundle = require('./dist/server.bundle') const renderer = createBundleRenderer(serverBundle, { template, runInNewContext: false }) server.use(express.static(path.resolve(__dirname, '../dist'))) server.get('*', (req, res) => { const context = { url: req.url } renderer.renderToString(context, (err, html) => { if (err) { console.error(err) res.status(500).end('Server error') return } res.end(html) }) }) server.listen(3000, () => { console.log('Server started at http://localhost:3000') }) ``` 在这个文件中,首先引入所需的模块。然后,使用`createBundleRenderer`方法创建bundle渲染器,并传入相关参数。接着,设置静态文件目录,并处理所有请求,将渲染好的HTML返回给客户端。 5. 最后,运行`npm run build`命令进行打包。打包完成后,可以运行`node dist/server.bundle.js`启动服务器端。 至此,我们成功将vue-cli2项目添加了ssr打包。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cocoonne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值