Vue:结合SSR实现骨架屏

836 阅读1分钟

1、创建目录和文件

src新建skeleton目录,并在里面创建skeleton.vueskeleton.entry.js文件。
skeleton.vue 是骨架屏的代码:

<template>
  <div class="skeleton page">
    <span>骨架屏</span>
  </div>
</template>

skeleton.entry.js 是编译骨架屏代码的入口文件:

import Vue from 'vue'
import Skeleton from './skeleton'

export default new Vue({
  // 根实例简单渲染应用程序组件
  render: h => h(Skeleton)
})

2、创建webpack配置文件

根目录build目录中新建一个webpack.skeleton.conf.js的配置文件,配合vue-server-rendererskeleton.vue文件的内容构建为单个的json文件。

const path = require('path')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = {
  entry: './src/skeleton/skeleton.entry.js',
  output: {
    path: path.resolve(__dirname, '../dist'),
    publicPath: '/dist/',
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }, {
        test: /\.css$/,
        use: ['vue-style-loader', 'css-loader']
      }
    ]
  },
  plugins: [
    new VueSSRServerPlugin({
      filename: 'skeleton.json'
    })
  ]
}

3、获取skeleton.json文件

package.json配置npm命令

"skeleton": "webpack --progress --config build/webpack.skeleton.conf.js"

运行 npm run skeleton 命令,在dist中生成skeleton.json文件

4、将skeleton.json插入到模板文件index.html中

在根目录下创建skeleton.js

const fs = require('fs')
const {resolve} = require('path')
const {createBundleRenderer} = require('vue-server-renderer')

function createRenderer(bundle, options) {
  return createBundleRenderer(bundle, Object.assign(options, {}))
}

const handleError = err => {
  console.error(err.stack)
}

const bundle = require('./dist/skeleton.json')
const templatePath = resolve('./index.html')
const template = fs.readFileSync(templatePath, 'utf-8')
const renderer = createRenderer(bundle, {template})

const context = {
  title: '',
  meta: `
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <link rel="stylesheet" href="<%= BASE_URL %>css/reset.css">
  `
}

renderer.renderToString(context, (err, html) => {
  if (err) {
    return handleError(err)
  }
  fs.writeFileSync(resolve(__dirname, './index.html'), html, 'utf-8')
})

默认的index.html中包含<%= BASE_URL %>的插值语法,在vue-server-renderer中使用模板而不传值时会报错,所以需要去掉模板中的传值,使用传参的方式再将两个插值返回到模板中

5、模板index.html加上插槽注解

index.htmldiv#app中要加<!--vue-ssr-outlet-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title></title>
  </head>
  <body>
    <div id="app">
      <!--vue-ssr-outlet-->
    </div>
  </body>
</html>

6、执行skeleton.js

node skeleton.js

执行成功后,模板index.html中的div#app中的内容就会变成骨架屏代码