我是如何把个人网站首屏加载时间从18秒优化到5秒的

起因是这样的,自己做了一个网站,开发的时候好好的,部署到服务器上去后,打开的时候白屏了好长时间才展示内容, 这可不能忍,必须找出原因优化掉!

服务器配置

CPU:1核,内存:2GiB,带宽:1Mbps

这上来就找到原因了啊,这配置这么低,肯定慢啊,怎么办?

换!!!

然而贫穷像是一万多条无形的枷锁束缚住了我,让我换服务器的双手动弹不得。

此路不通,只能另寻他法解决了。

优化前首屏加载测试

测试结果分析

  1. 从截图可以看到,首屏加载耗时19.15秒,主要是chunk-vendors.2daba5b2.js这个文件加载耗时最长,为17.6秒,大小为1.9M,其他文件均在4秒内加载完毕。通常页面加载的一个文件大小超过300k,已经算比较大了。第二个比较耗时的文件是chunk-vendors.62bee483.css,这个应该是样式文件。其他的文件加载耗时都不超过1秒,所以后面优化先从那两个文件下手。
  2. 重新编译项目,看下项目生成的文件

可以看到前面提到的两个文件比较大,后面列出了每个文件使用gz压缩后的大小,但是浏览器实际并没有加载压缩后的文件,而是原始文件。再打开打包文件夹,发现实际生成的js文件夹中除了js文件,还有js.map文件,js.map文件通常用于开发环境调试用,方便我们查找错误,在生成环境是不需要用到的,而且都比较大,这也是一个优化的点。

分析项目依赖情况

运行vue ui,编译查看chunk-vendors中的结构发现,主要是element-ui依赖比较大,其次是vue和mavon-editor

整个项目的情况如下

那么如何优化呢

开启nginx压缩配置

修改nginx配置,启用gzip压缩

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

测试页面加载时间缩短到5.2秒,chunk-vendors.js传输大小为556k,加载时间为4秒,其他文件加载时间基本不超过200毫秒

生产配置不生成js.map

修改项目根目录中vue.config.js配置文件,设置productionSourceMap: false

module.exports = {
    runtimeCompiler: true,
    productionSourceMap: false
}

打包测试文件夹大小由9.1M减小到2.26M

配置gzip压缩插件

执行npm i compression-webpack-plugin@5.0.1 -D安装插件,在vue.config.js中修改打包配置

const CompressionPlugin = require("compression-webpack-plugin");
const productionGzipExt = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;
module.exports = {
    runtimeCompiler: true,productionSourceMap: false,configureWebpack: () => {
        if (process.env.NODE_ENV === "production") {
            return {
                plugins: [
                    new CompressionPlugin({
                        filename: "[path].gz[query]",
                        algorithm: "gzip",
                        test: productionGzipExt,
                        threshold: 1024, // 大于1024字节的资源才处理
                        minRatio: 0.8, // 压缩率要高于80%
                        deleteOriginalAssets: false, // 删除原始资源,如果不支持gzip压缩的浏览器无法正常加载则关闭此项
                    }),
                ],
            };
        }
    },
};

插件需要指定版本,最新版本的会报错这个和nginx压缩配置感觉重复了,实际测试和nginx压缩配置的速度差不多,如果两个压缩都有,速度并没有提升

修改elementui组件按需引入

  1. 执行npm install babel-plugin-component -D安装 babel-plugin-component2. 修改.babelrc内容如下:
{
    "presets": [["@babel/preset-env", { "modules": false}]],
    "plugins": [
        [
            "component",
            {
                "libraryName": "element-ui",
                "styleLibraryName": "theme-chalk"
            }
        ]
    ]
}
  1. 在main.js中引入需要用到的组件,示例如下:
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import "element-ui/lib/theme-chalk/index.css";
import mavonEditor from "mavon-editor";
import "mavon-editor/dist/css/index.css";
import axios from "axios";
import {
    Avatar,
    Button,
    Container,
    DatePicker,
    Dialog,
    Dropdown,
    DropdownItem,
    DropdownMenu,
    Footer,
    Form,
    FormItem,
    Header,
    Image,
    Input,
    Main,
    Message,
    MessageBox,
    Notification,
    Option,
    Select,
    Table,
    TableColumn,
    TabPane,
    Tabs,
    Timeline,
    TimelineItem,
} from "element-ui";
​
Vue.use(Button);
Vue.use(Dialog);
Vue.use(Dropdown);
Vue.use(DropdownMenu);
Vue.use(DropdownItem);
Vue.use(Input);
Vue.use(Select);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(DatePicker);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Tabs);
Vue.use(TabPane);
Vue.use(Header);
Vue.use(Main);
Vue.use(Footer);
Vue.use(Timeline);
Vue.use(TimelineItem);
Vue.use(Image);
Vue.use(Avatar);
Vue.use(Container);
Vue.use(Option);
Vue.use(mavonEditor);
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$axios = axios;
Vue.config.productionTip = false;
​
axios.interceptors.request.use(
    (config) => {
        config.url = "/api/" + config.url;
        config.headers.token = sessionStorage.getItem("identityId");
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);
​
axios.interceptors.response.use(
    (response) => {
        if (response.data && response.data.exceptionCode) {
            const exceptionType = response.data.exceptionType;
            Notification({ title: response.data.exceptionMessage, type: exceptionType.toLowerCase() });
            return Promise.reject(response.data);
        }
        return response;
    },
    (error) => {
        return Promise.reject(error);
    }
);new Vue({
    router,
    store,
    render: (h) => h(App),
}).$mount("#app");

修改按需引入后elementui依赖大小约为1.3M

修改组件局部引入为异步组件

在一个组件中引入其他组件时使用异步的方式引入,如

export default {
    components: {
        register: () => import('./views/Register.vue'),
        login: () => import('./views/Login.vue')
    }
};

完成后此时chunk-vendors.js这个文件已经从优化前的1.9M缩小到890k

页面加载约3秒可以显示出来,其他资源在页面显示后继续后台加载,全部加载完总耗时约5秒,请求数68次

组件按组分块

使用命名chunk语法webpackChunkName: "块名"将某个路由下的组件打包在同一个异步块中,如

import Vue from "vue";
import VueRouter from "vue-router";
​
Vue.use(VueRouter);const routes = [
    {
        path: "/",
        redirect: 'home'
    },
    {
        path: '/home',
        component: () => import(/* webpackChunkName: "home-page" */ '../views/Home.vue')
    },
    {
        path: '/documents',
        component: () => import(/* webpackChunkName: "home-page" */ '../views/documents/DocumentList.vue')
    },
    {
        path: '/documentcontent',
        component: () => import(/* webpackChunkName: "home-page" */ '../views/documents/DocumentContent.vue')
    },
    {
        path: '/write',
        component: () => import(/* webpackChunkName: "home-page" */ '../views/WriteMarkdown.vue')
    },
    {
        path: '/about',
        component: () => import(/* webpackChunkName: "home-page" */ '../views/About.vue')
    },
    {
        path: '/management',
        component: () => import(/* webpackChunkName: "management" */ '../views/management/Management.vue'),
        children: [
            { path: '', component: () => import(/* webpackChunkName: "management" */ '../views/management/ManagementOptions.vue') },
            { path: 'developplan', component: () => import(/* webpackChunkName: "management" */ '../views/management/DevelopmentPlan.vue') },
            { path: 'tags', component: () => import(/* webpackChunkName: "management" */ '../views/management/TagsManage.vue') },
            { path: 'documents', component: () => import(/* webpackChunkName: "management" */ '../views/management/DocumentsManage.vue') }
        ]
    },
    {
        path: '/games',
        component: () => import(/* webpackChunkName: "games" */ '../views/games/Games.vue'),
        children: [
            { path: '', component: () => import(/* webpackChunkName: "games" */ '../views/games/GameList.vue') },
            { path: 'minesweeper', component: () => import(/* webpackChunkName: "games" */ '../views/games/minesweeper/MineSweeper.vue') }
        ]
    },
    {
        path: '/tools',
        component: () => import(/* webpackChunkName: "tools" */ '../views/tools/ToolsView.vue'),
        children: [
            { path: '', component: () => import(/* webpackChunkName: "tools" */ '../views/tools/ToolsList.vue') },
            { path: 'imageconverter', component: () => import(/* webpackChunkName: "tools" */ '../views/tools/ImageConverter.vue') }
        ]
    }
];const router = new VueRouter({
    mode: "history",
    base: process.env.BASE_URL,
    routes,
});export default router;

打包编译后文件比之前要减少了一部分,并且合并后的文件资源也不大,完全可以接受

页面加载耗时基本没变,但是请求数减少到51次

总结

  1. nginx压缩对性能的提升最大,通过压缩文件缩短资源加载时间
  2. gzip压缩插件会将文件压缩成gz格式,暂时不知道怎么用
  3. elementui按需引入会减小依赖资源的大小,chunk-vendors.js文件体积会减小
  4. 使用异步组件可以在后台加载渲染不到的资源,优先加载渲染需要的资源,缩短页面响应时间,但同时会增加打包后的文件数量,导致页面请求数量增加。
  5. 组件按路由分组,打包的时候会将相同组名的资源打包到一个文件中,可以减小请求数
  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值