优点
- 加速或减少HTTP请求损耗
- 延迟加载
- 减少请求内容的体积
- 优化用户等待体验
vuecli3
components/Skeleton.vue
<template>
<div class="skeleton-wrapper">
<section class="skeleton-block">
<!-- eslint-disable vue/max-len -->
骨架内容
</section>
</div>
</template>
<script>
export default {
name: 'Skeleton',
};
</script>
<style scoped>
.skeleton-block {
display: flex;
flex-direction: column;
padding: 16px;
background: #f7f7f7;
}
</style>
src/Skeleton.js
// - Skeleton.js
import Vue from 'vue';
import Skeleton from './components/Skeleton.vue';
export default new Vue({
components: {
Skeleton,
},
render: h => h(Skeleton),
});
最重要的 vue.config.js
const path = require('path');
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin');
module.exports = {
publicPath: './', //已经用publicPath代替baseUrl了,// 根域上下文目录
outputDir: 'dist', // 构建输出目录
assetsDir: 'assets', // 静态资源目录 (js, css, img, fonts)
lintOnSave: true, // 是否开启eslint保存检测,有效值:ture | false | 'error'
runtimeCompiler: true, // 运行时版本是否需要编译
transpileDependencies: [], // 默认babel-loader忽略mode_modules,这里可增加例外的依赖包名
productionSourceMap: false, // 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度
configureWebpack: (config) => {
config.plugins.push(new SkeletonWebpackPlugin({
webpackConfig: {
entry: {
app: path.join(__dirname, './src/skeleton.js'),
},
},
minimize: true,
quiet: true,
}))
},
css: { // 配置高于chainWebpack中关于css loader的配置
// modules: true, // 是否开启支持‘foo.module.css’样式
// extract: true, // 是否使用css分离插件 ExtractTextPlugin,采用独立样式文件载入,不采用<style>方式内联至html文件中
sourceMap: false, // 是否在构建样式地图,false将提高构建速度
loaderOptions: { // css预设器配置项
sass: {
data: '' //`@import "@/assets/scss/mixin.scss";`
}
}
},
parallel: require('os').cpus().length > 1, // 构建时开启多进程处理babel编译
pluginOptions: { // 第三方插件配置
},
pwa: { // 单页插件相关配置 https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
},
devServer: {
open: true,
host: '0.0.0.0',
port: 8080,
https: false,
hotOnly: false,
proxy: null,
// proxy: {
// '/api': {
// target: '<url>',
// ws: true,
// changOrigin: true
// }
// },
before: app => {}
}
}
白屏时的效果
vuecli2
在build文件夹下新建webpack.skeleton.conf.js文件
const path = require('path');
const merge = require('webpack-merge');
const baseWebpackConfig = require('./webpack.base.conf');
const nodeExternals = require('webpack-node-externals');
const utils = require('./utils');
const config = require('../config');
const isProduction = process.env.NODE_ENV === 'production';
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap;
function resolve (dir) {
return path.join(__dirname, dir);
}
let skeletonWebpackConfig = merge(baseWebpackConfig, {
target: 'node',
devtool: false,
entry: {
app: resolve('../src/entry-skeleton.js')
},
output: Object.assign({}, baseWebpackConfig.output, {
libraryTarget: 'commonjs2'
}),
externals: nodeExternals({
whitelist: /\.css$/
}),
plugins: []
});
// skeletonWebpackConfig.module.rules[1]这里不一定是0或1,要看webpack.base.conf.js下rules中vue-loader的下标是多少
skeletonWebpackConfig.module.rules[1].options.loaders = utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: true
});
module.exports = skeletonWebpackConfig;
注意enter文件入口路径,指向enter-skeleton.js所在目录
在webpack.dev.conf.js、webpack.prod.conf.js进行配置(两个文件设置内容一样)
// 导入插件
const SkeletonWebpackPlugin = require('vue-skeleton-webpack-plugin');
// 在plugins中设置入下
new SkeletonWebpackPlugin({
webpackConfig: require('./webpack.skeleton.conf'),
quiet: true,
minimize: true,
router: {
mode: 'hash' // 'history',
routes: [
// 可以为多个路由页面配置不同的骨架屏
{
path: '/', // 给指定的路由配置具体的骨架屏
skeletonId: 'skeleton1'// 设置指定路由使用的具体骨架屏的id
}
]
}
})
参数说明:
SkeletonWebpackPlugin
webpackConfig 必填,渲染 skeleton 的 webpack 配置对象
insertAfter 选填,渲染 DOM 结果插入位置,默认值为字符串 " '<div id=“app”
也可以传入 Function,方法签名为 insertAfter(entryKey: string): string,返回值为挂载点字符串
quiet 选填,在服务端渲染时是否需要输出信息到控制台
router 选填 SPA 下配置各个路由路径对应的 Skeleton
mode 选填 路由模式,两个有效值 history|hash
routes 选填 路由数组,其中每个路由对象包含两个属性:
path 路由路径 string|RegExp
skeletonId Skeleton DOM 的 id string
minimize 选填 SPA 下是否需要压缩注入 HTML 的 JS 代码