静态页面

一、express 启动后端

仓库open in new window

index.js

let express = require('express')

let server = express()

server.get('/', (req, res) => {
  res.send(`Hello World 123`)
})
server.listen(3000, () => {
  console.log('your server start on http://localhost:3000')
})

使用 webpack 打包

webpack.config.js

let path = require('path')
let nodeExternals = require('webpack-node-externals')
module.exports = {
  target: 'node',
  mode: 'development',
  entry: './src/server/index.js',
  output: {
    filename: 'server_bundle.js',
    path: path.resolve(__dirname, '../build/server')
  },
  externals: [nodeExternals()] // node环境
}

二、vue 的 SSR

仓库open in new window

一个 vue 组件

App.vue

<template>
  <div class="app" style="border: 1px solid beige">
    <h2>Vue app</h2>
    <div>{{ count }}</div>
    <button @click="addCount">+1</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
const addCount = () => {
  count.value += 1
}
</script>
<style scoped></style>

app.js

import { createSSRApp } from 'vue'

import App from './App.vue'

// q: 为什么写成函数返回app?
// a: 通过函数返回,可以保证每个请求都返回一个新的app实例,避免跨请求的污染
export default function createApp() {
  let app = createSSRApp(App)
  return app
}

跨请求状态污染

在 SPA 中,整个生命周期只有一个 App 对象实例

在 SSR 环境下,App 模块通常只在服务启动时初始化一次,同一个模块会在对个请求之间被复用,所以会存在状态泄露,这种情况被称为 跨请求状态污染

为了避免 在每个请求中为整个应用创建一个全新的实例

修改后端服务 index.js

let express = require('express')

let server = express()

import createApp from '../app'
import { renderToString } from '@vue/server-renderer'

server.get('/', async (req, res) => {
  let app = createApp()
  let htmlStr = await renderToString(app)

  res.send(
    `
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      ${htmlStr}
    </div>
  </body>
  </html>
  `
  )
})
server.listen(3000, () => {
  console.log('your server start on http://localhost:3000')
})

修改 webpack 配置

webpack.config.js

let path = require('path')
let nodeExternals = require('webpack-node-externals')
let { VueLoaderPlugin } = require('vue-loader/dist/index')
module.exports = {
  target: 'node',
  mode: 'development',
  entry: './src/server/index.js',
  output: {
    filename: 'server_bundle.js',
    path: path.resolve(__dirname, '../build/server')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [new VueLoaderPlugin()],
  resolve: {
    extensions: ['.js', '.json', '.vue']
  },
  externals: [nodeExternals()] // node环境
}











 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 





启动打包后的文件,这个文件只是静态的,没有交互

贡献者: seekHoo