【笔记】Vue3项目实现SSR

前言

Vue3项目实现SSR

下载依赖

1
2
npm install express vue @vue/server-renderer
npm install -D webpack webpack-cli webpack-node-externals vue-loader babel-loader @babel/core @babel/preset-env

客户端

定义客户端

src/client/index.js
1
2
3
4
5
import { createSSRApp } from "vue";
import App from "../App.vue";

const app = createSSRApp(App);
app.mount("#app");

定义Webpack配置

config/client/webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const path = require("path");
const { VueLoaderPlugin } = require("vue-loader");

module.exports = {
target: "web",
mode: "development",
entry: "./src/client/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "../../build/client")
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
},
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
plugins: [new VueLoaderPlugin()]
}

通过Webpack打包客户端

1
webpack --config config/client/webpack.config.js

服务器

定义Vue3根组件

src/App.vue
1
<template></template>

定义服务器

  • 渲染Vue3根组件
  • 实现JS水合激活(Hydration)
src/server/app.js
1
2
3
4
5
6
import { createSSRApp } from "vue";
import App from "../App.vue";

export function createApp() {
return createSSRApp(App);
}
src/server/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const express = require("express");
const path = require("path");
const { renderToString } = require("@vue/server-renderer");
const { createApp } = require("./app.js");

const server = express();
server.use(express.static(path.resolve(__dirname, "../client")));
server.get("/", async function (request, response) {
const app = createApp();
const appHTML = await renderToString(app);
response.send(`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">${appHTML}</div>
<script src="/bundle.js"></script>
</body>
</html>
`);
});
server.listen(3000);

定义Webpack配置

config/server/webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const { VueLoaderPlugin } = require("vue-loader");

module.exports = {
target: "node",
mode: "development",
entry: "./src/server/index.js",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "../../build/server"),
libraryTarget: "commonjs2"
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"]
}
},
{
test: /\.vue$/,
loader: "vue-loader"
}
]
},
plugins: [new VueLoaderPlugin()],
externals: [
nodeExternals({
allowlist: ["vue", "@vue/server-renderer"]
})
]
}

通过Webpack打包服务器

1
webpack --config config/server/webpack.config.js

启动SSR服务器

  • 先通过Webpack依次打包客户端和服务器,再启动打包好的服务器程序
1
2
3
4
webpack --config config/client/webpack.config.js
webpack --config config/server/webpack.config.js

node build/server/bundle.js

完成