美文网首页
108.webpack+vue服务端渲染

108.webpack+vue服务端渲染

作者: wo不是黄蓉 | 来源:发表于2022-05-25 11:26 被阅读0次

为什么使用ssr?

  • 单页应用对SEO不友好,页面信息是从打包后再渲染过去的。服务端渲染使用服务端渲染页面,将结果返回到浏览器。

  • 内网速度比外网渲染更快

来自Vue官方的一张图:

image.png

实现过程:

  • 实现两个entry,因为服务端没有渲染的概念,因此client entry实现客户端挂载功能,server entry实现获取到应用信息。

  • 使用webpack分别打包client entryclient.bundle.jsserver entryserver.bundle.js

  • 服务端获取打包好的bundle信息,服务端budnle负责渲染vue模板将获取的模板插入到模板文件,客户端Bundle负责将js信息插入到模板文件进行事件调用。

目录结构

image-20220526100933382.png
需要安装的依赖:
webpack webpack-cli webpack-merge
vue @vue/server-render vue-loader
babel-core babel-loader@7
html-webpack-plugin
express

实现过程:

1.安装vuevue ssrvue版本要和vue-server-renderer版本一致,否则会提示版本不一致报错。

npm install vue
npm install @vue/server-renderer

2.实现渲文件和通用代码

App.vue

<template>
  <div id="app"><div class="demo" @click="handleClick">一段内容</div></div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log(111);
    },
  },
};
</script>

app.js

//vue3引入vue的方式
import { createApp } from 'vue';
import App from './App.vue';

export function createSsrApp() {
  const app = createApp(App);
  return { app };
}

3.实现模板文件和编写 client-entry.jsserver-entry.js

<!DOCTYPE html>
<html lang="en">
  <head></head>
  <body>
    <div id="app"></div>
  </body>
</html>

client-entry.js

//客户端实现方式使用$mount进行挂载,获取到vue信息,直接对齐进行挂载
import { createSsrApp } from './app';
const { app } = createSsrApp();
app.mount('#app');

server-entry.js

import { createSsrApp } from './app';//将创建的app信息暴露给服务端
export default () => {  const { app } = createSsrApp();  return app;};

4.编写package.json打包命令

 "scripts": {
    "client": "webpack --config ./build/webpack.client.js",
    "server": "webpack --config ./build/webpack.server.js",
    "build": "npm run client && npm run server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

5.编写webpack.config.js,区分客户端和服务端,合并配置信息需要使用webpack-merge

npm install webpack-merge --save-dev

webpack.base.js

const path = require('path');
//使用vueloader需要引入vueloaderplugin
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
  mode: 'production',
  //不配置entry信息,entry信息在不同的配置文件中来加载
  //解析js和vue文件,安装vue-loader
  resolve: {
    extensions: ['.js', '.vue'],
  },
  //解析vue文件,配置loader
  module: {
    rules: [
      // 使用Vueloader编译vue文件
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      // 它会应用到普通的 `.js` 文件
      // 以及 `.vue` 文件中的 `<script>` 块
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
    ],
  },
  plugins: [new VueLoaderPlugin()],
};

webpack.client.js

const path = require('path');
const { merge } = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const baseConfig = require('./webpack.base');

module.exports = merge(baseConfig, {
  entry: path.resolve(__dirname, '../src/entry-client.js'),
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'client.bundle.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
    //指定打包后的html文件
      filename: 'index.ssr.html',
      //指定模板文件
      template: path.resolve(__dirname, '../dist/index.ssr.html'),
      excludeChunks: ['server'],
      minify: {
        removeComments: false,
      },
    }),
  ],
});

webpack.server.js

const path = require('path');
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.base');
//使用merge合并配置信息
module.exports = merge(baseConfig, {
    //指定entry为entry.server.js
  entry: path.resolve(__dirname, '../src/entry-server.js'),
  output: {
      //打包到项目的dist目录下面
    path: path.resolve(__dirname, '../dist'),
      //指定打包后Bundle的名字
    filename: 'server.bundle.js',
      //需要打包为commonjs规范的代码,服务端在使用,不支持使用es module的规范
    libraryTarget: 'commonjs2',
  },
  plugins: [],
});

6.打包文件,打包

npm run server
//生成server.bundle.js

npm run client
//生成index.ssr.html和cliet.bundle.js文件

7.使用express编写服务器createServer.js

npm install express
//引入ssr
const { renderToString, render } = require('@vue/server-renderer');
//创建server
const server = require('express')();
const fs = require('fs');
const path = require('path');
const express = require('express');
// Cannot use import statement outside a module
//node服务端不能使用import语法

//获取模板文件
const indexTemplate = fs.readFileSync(
  path.resolve(__dirname, './dist/index.ssr.html'),
  'utf-8'
);
//使用sever.bundle.js创建vue app,配置webpack.server.js时如果不指定目标为commonjs会提示报错不支持module语法
const createApp = require('./dist/server.bundle').default;
//使用express.static将dist目录下的文件设置为静态资源,否则打包到index.ssr.html中的文件虽然可以看到已经引入了client.bundle.js,但是并不能够访问。引入成功之后,访问http://localhost:8080/client.bundle.js可以看到打包后的js信息
server.use(express.static(path.join(__dirname, './dist')));

server.get('*', async (req, res) => {
  const app = createApp();
  //renderToString将获取到的应用信息返回为字符串,使用将<div id="app">替换为新打包的内容信息
  const appContent = await renderToString(app);
  const html = indexTemplate
    .toString()
    .replace('<div id="app">', `<div id="app">${appContent}`);
//设置返回的文件格式
  res.setHeader('Content-Type', 'text/html');
  res.send(html);
});
//启动服务
server.listen(8080);

验证:打开http://localhost:8080 点击一段内容文件,可以发现打印了111

image-20220526105822056.png
没有将client.bundle.js资源静态化会出现的报错信息:
image-20220526110114189.png
参考1:视频
参考2:vue官方
源码资源->github

相关文章

  • 108.webpack+vue服务端渲染

    为什么使用ssr?[https://v3.cn.vuejs.org/guide/ssr/introduction....

  • 服务端渲染SSR之UmiJS预渲染

    UmiJS 服务端渲染 本文主要介绍 UmiJS 的预渲染功能。 一、什么是服务端渲染? 服务端渲染(Server...

  • SSR服务端同构渲染

    页面渲染历史 服务端框架模板渲染 -> 客户端渲染 -> 服务端同构渲染(Server Side Render) ...

  • 服务端渲染(SSR)

    导读 本文主要是从三个方面学习服务端渲染,内容整理自多个博客。 服务端渲染是什么?什么是服务端渲染?(服务端渲染的...

  • 服务端渲染与客户端渲染

    服务端渲染与客户端渲染 服务端渲染说白了,就是在服务端使用模板引擎末班引擎最早诞生于服务端,后来才到了前端 服务端...

  • Vue SSR 服务端渲染

    服务端渲染的基本模型 所谓服务端渲染, 其实一直都有, java, python, php 都有渲染模板来做服务端...

  • 服务端渲染介绍

    什么是渲染 渲染指的是把数据+模板拼接到一起 传统服务端渲染 早期Web页面都是通过服务端渲染,服务端将数据和页面...

  • SSR服务端渲染-简析

    什么是服务端渲染 (SSR)? 服务端渲染简单来讲就是,服务端渲染好html字符串直接返回给前端浏览器展示,可以先...

  • vue服务端渲染缓存应用详解

    服务端渲染简介 服务端渲染不是一个新的技术;在 Web 最初的时候,页面就是通过服务端渲染来返回的,用 PHP 来...

  • 服务端渲染

    一、服务端渲染需要考虑的问题 1、react 如何支持服务端渲染 import {renderToString, ...

网友评论

      本文标题:108.webpack+vue服务端渲染

      本文链接:https://www.haomeiwen.com/subject/aqruprtx.html