处理登陆页面首次登陆白屏的问题,有知道的怎么处理的么?

vue项目可以单独让登录页面做SSR服务器渲染么 ,具体要怎么操作么?

没有思路

阅读 809
3 个回答

准备项目结构与拆分路由

定义登录页面组件 在项目中创建并配置登录页面组件,例如将其放在 src/views/Login.vue 文件中。
路由配置 在路由配置文件中,为登录页面设置一个带有特殊meta属性的路由,表示该路由需要进行服务器端渲染(SSR):

   // router.js 或相关路由配置文件
   import Login from '@/views/Login.vue';
   import { createRouter, createWebHashHistory } from 'vue-router';

   const router = createRouter({
     history: createWebHashHistory(),
     
     routes: [
       // 其他非SSR路由...
       { path: '/', component: () => import('@/views/Home.vue') },

       // 登录页SSR路由
       { path: '/login', component: Login, meta: { ssr: true } },
     ],
   });
   

编写服务端渲染入口
创建一个服务端渲染入口文件(如 server-entry.js),实现SSR逻辑:

// 导入相关模块
import Login from '@/views/Login.vue';
import { createApp } from './app';
import { createServerRenderer } from '@vue/server-renderer';
import { router } from '../router'; // 引入路由配置

// 判断是否为SSR路由的方法
function isSSRRoute(routeMeta) {
  return routeMeta && routeMeta.ssr;
}

// 创建服务器渲染器
export default createServerRenderer(async context => {
  // 创建应用实例和路由实例
  const { app, router: _router } = createApp();

  // 根据请求路径决定是否进行SSR渲染
  const matchedComponent = router.getMatchedComponents({ path: context.url })[0];
  if (isSSRRoute(matchedComponent.meta)) {
    // 设置当前路由并等待数据加载完成
    _router.push(context.url);
    await _router.isReady();
  }

  // 执行服务器端渲染并将结果转换为HTML字符串
  return renderToString(app);
});

数据预取与服务端环境配置

数据预取 如果登录页面在渲染时需要从服务器获取数据,可以在组件中使用 asyncData 或 fetch 钩子方法,确保在服务器端渲染前获取所需数据。

在登录页面组件中使用asyncData钩子: 在Login.vue组件的<script>标签内添加asyncData方法,该方法会在服务器端渲染时被调用,并在组件实例化前同步数据。

<script>
export default {
  data() {
    return {
      // 初始化数据
    };
  },
  async asyncData({ store, params, query }) {
    // 使用Vuex Store、路由参数或查询参数来获取数据(如果有)
    // 根据实际情况替换以下示例API请求
    const response = await this.$axios.get('/api/login-preload-data');

    // 返回一个对象,其属性将合并到组件的data对象中
    return {
      initialFormData: response.data, // 假设这是登录页面需要的初始数据
    };
  },
  methods: {
    // 登录逻辑等其他方法
  },
};
</script>

在非Nuxt.js项目中处理SSR时的数据预取: 如果不是在Nuxt.js环境下,需要在自定义的服务器端渲染逻辑中手动触发asyncData的执行。在调用renderToString方法前,先执行asyncData并等待其返回结果。

// server-entry.js
import { createApp } from './app';
import { createServerRenderer } from '@vue/server-renderer';
import { router } from '../router';
import Login from '@/views/Login.vue';

// 创建一个通用的处理函数,用于执行asyncData
async function executeAsyncData(component, context) {
  if (component.options.asyncData) {
    const asyncDataResult = await component.options.asyncData(context);
    return Object.assign({}, context, asyncDataResult);
  }
  return context;
}

export default createServerRenderer(async context => {
  const { app, router: _router } = createApp();

  // 获取匹配的组件
  const matchedComponent = router.getMatchedComponents({ path: context.url })[0];

  // 如果是登录页面并且需要SSR
  if (matchedComponent === Login && matchedComponent.options.meta.ssr) {
    // 执行asyncData
    context = await executeAsyncData(matchedComponent, context);
  }

  _router.push(context.url);
  await _router.isReady();

  return renderToString(app);
});

服务端环境

安装依赖 安装 @vue/server-renderer 包,用于在服务器端渲染Vue应用。
配置Webpack 调整Webpack配置,分别构建用于客户端和服务器端的bundle文件。

npm install --save @vue/server-renderer

用yarn:

yarn add @vue/server-renderer

Webpack配置调整
分别构建客户端和服务器端bundle
webpack.client.config.js:

const { VueLoaderPlugin } = require('vue-loader');
const path = require('path');

module.exports = {
  target: 'web',
  entry: './src/client-entry.js',
  output: {
    filename: 'client-bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm-bundler.js', // or vue.runtime.esm-bundler.js for runtime-only build
    },
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader',
      },
      // other loaders for CSS, images, etc.
    ],
  },
  plugins: [
    new VueLoaderPlugin(),
  ],
};

webpack.server.config.js:

const { VueSSRServerPlugin } = require('vue-server-renderer');
const path = require('path');

module.exports = {
  target: 'node',
  entry: './src/server-entry.js',
  output: {
    libraryTarget: 'commonjs2',
    filename: 'server-bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.runtime.common.prod.js', // use the production version of Vue with server rendering capabilities
    },
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        use: 'vue-loader',
      },
      // other loaders for CSS (usually extract-text-webpack-plugin for SSR), images, etc.
    ],
  },
  externals: nodeExternals(), // 忽略node_modules目录,只打包应用程序依赖
  plugins: [
    new VueSSRServerPlugin({
      filename: 'vue-ssr-server-bundle.json', // 输出Vue SSR编译后的JSON文件
    }),
  ],
};

// Node.js外部模块解析器,通常需要安装对应的包:npm install --save-dev nodeExternals
function nodeExternals() {
  return ({ context, request }, callback) => {
    if (request.match(/\.(css|scss|sass|jpg|png|gif)$/i)) {
      return callback(null, 'empty-module');
    }
    if (/^vue/.test(request)) {
      return callback();
    }
    callback();
  };
}

上面只是示例,可以参考,然后还需要在项目中创建相应的client-entry.js和server-entry.js文件,分别作为客户端和服务器端的入口点。在服务器端入口文件中,通常会包含服务端渲染的相关逻辑,包括引入Vue组件、创建应用、处理请求并调用@vue/server-renderer进行渲染。

构建Node.js服务器

创建Node.js服务器 使用Express或其他框架创建一个HTTP服务器,监听客户端请求。

  // server.js
  import express from 'express';
  import serverRenderer from './server-entry.js';

  const app = express();

  // 处理请求并返回SSR渲染的HTML
  app.use(async (req, res) => {
    const html = await serverRenderer(req, res);
    res.send(html);
  });

  // 启动服务器
  app.listen(3000, () => {
    console.log('Server is listening on port 3000');
  });

整合客户端逻辑

客户端接管 确保在HTML模板中注入客户端脚本,当脚本加载并执行时,Vue应用将识别并接管已经存在于DOM中的服务器端渲染内容,从而实现无缝切换至客户端渲染模式。

综上所述,差不多就ok了。。。。。。通过对登录页面进行特别标记、编写服务端渲染逻辑、预取数据、配置服务端环境并启动服务器,以及在客户端进行正确的接管,Vue项目中的登录页面就可以成功实现服务器端渲染。这样不仅提高了SEO效果,还能让用户更快地看到登录页面的初始内容。

加一个loading, v-loading,等dom元素加载完再取消loading

可以在 index.html 中增加loading效果。比如说借鉴 ant-design-vue 中的 public/index.html 文件。

图片.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题