2、我们还需要在新建一个 webpack.skeleton.conf.js
文件,以专门用来进行骨架屏的构建(这个文件放在哪里无所谓,可以放在根目录下,也可以放在 build
目录中)。这是一个 webpack 的配置文件,配合使用 vue-server-renderer
将我们的 skeleton.vue
文件内容构建为单个的 json 格式的文件(这是 Vue SSR 渲染的策略)
// webpack.skeleton.conf.js
‘use strict’
const path = require(‘path’)
const nodeExternals = require(‘webpack-node-externals’)
const VueSSRServerPlugin = require(‘vue-server-renderer/server-plugin’)
module.exports = {
target: ‘node’,
devtool: ‘#source-map’,
entry: ‘./src/skeleton/skeleton.entry.js’,
output: {
path: path.resolve(__dirname, ‘…/dist’),
publicPath: ‘/dist/’,
filename: ‘[name].js’,
libraryTarget: ‘commonjs2’
},
module: {
noParse: /es6-promise.js$/, // avoid webpack shimming process
rules: [
{
test: /.vue$/,
loader: ‘vue-loader’,
options: {
compilerOptions: {
preserveWhitespace: false
}
}
},
{
test: /.css$/,
use: [‘vue-style-loader’, ‘css-loader’]
}
]
},
performance: {
hints: false
},
externals: nodeExternals({
// do not externalize CSS files in case we need to import it from a dep
whitelist: /.css$/
}),
plugins: [
// 这是将服务器的整个输出构建为单个 JSON 文件的插件。
// 默认文件名为 vue-ssr-server-bundle.json
new VueSSRServerPlugin({
filename: ‘skeleton.json’
})
]
}
3、写完 skeleton.vue
的内容以后,使用 webpack-cli
运行这个 webpack.skeleton.conf.js
配置文件。
// package.json
“skeleton”: “webpack --progress --config build/webpack.skeleton.conf.js”
然后运行:
npm i webpack-cli@3.3.10 -D
npm run skeleton
就会在 dist
文件夹中生成一个skeleton.json
文件。
4、将 skeleton.json
内容插入到模版文件 index.html
中。(在根目录下创建一个 skeleton.js
文件)
// 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, {
// recommended for performance
// runInNewContext: false
}))
}
const handleError = err => {
console.error(error during render : ${req.url})
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
})
// console.log(renderer)
/**
- 说明:
- 默认的index.html中包含<%= BASE_URL %>的插值语法
- 我们不在生成骨架屏这一步改变模板中的这个插值
- 因为这个插值会在项目构建时完成
- 但是如果模板中有这个插值语法,而我们在vue-server-renderder中使用这个模板,而不传值的话,是会报错的
- 所以,我们去掉模板中的插值,而使用这个传参的方式,再将这两个插值原模原样返回到模板中
- 文档: https://cli.vuejs.org/zh/guide/html-and-static-assets.html#%E6%8F%92%E5%80%BC
*/
const context = {
title: ‘’, // default title
meta: `
`
}
renderer.renderToString(context, (err, html) => {
if(err) {
return handleError(err)
}
fs.writeFileSync(resolve(__dirname, ‘./index.html’), html, ‘utf-8’)
})
5、模版 index.html 加上插槽注解
这里需要注意的是:index.html 中的 div#app 中要加一个注解插槽,<!--vue-ssr-outlet-->
这个是必须的,Vue SSR 文档中有说这个。这个注解是必须的,请注意!
vue-for-test
参考连接:https://ssr.vuejs.org/zh/guide/#%E4%BD%BF%E7%94%A8%E4%B8%80%E4%B8%AA%E9%A1%B5%E9%9D%A2%E6%A8%A1%E6%9D%BF
6、执行
node skeleton.js
执行成功后,模版 index.html
中的 div#app
中的内容就会变成我们的骨架屏代码;
7、看一下效果