关于javascript:包真我的第一次webpack优化首屏渲染从9s到1s

40次阅读

共计 5452 个字符,预计需要花费 14 分钟才能阅读完成。

大家好,我是猫小白,本文基于 vue2,全文浏览大概须要 3 分钟。
谈到 webpack 优化大部分人可能都看腻了,无非就那几招嘛,我之前也是看过许多相似的文章,但都没有本人真正上手过,上面是我用公司的我的项目实在操练下来的,首屏加载速度晋升很大(刷刷的),心愿能帮到你。

废话不多说,先看看比照成绩!

类型 优化前 优化后
js 文件大小 24MB 3MB
主页首屏显示 9s 1s

这几乎太夸大了,晋升了 8 倍?能够设想以前是多慢,要等半天啊。蛮王 这个真男人都开大 2 次了~

能够看到,优化前后首屏加载速度有质的晋升,之前始终想优化咱们我的项目的首屏加载工夫,有缓存还好,没有缓存屏幕白屏都要期待 7、8s。特地是有的客户第一次关上这个零碎,那 7、8 秒犹如过了一个世纪,十分难堪。那么我做了那些惯例操作呢?

1. 生产环境敞开productionSourceMapcss sourceMap

家喻户晓,SourceMap就是当页面呈现某些谬误,可能定位到具体的某一行代码,SourceMap就是帮你建设这个映射关系的,不便代码调试。在生产环境中咱们齐全没必要开启这个性能(谁在生产环境调试代码?不会是你吧

如下配置:

const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境
module.exports = {
    productionSourceMap: !isProduction, // 敞开生产环境下的 SourceMap 映射文件
    css: {
        sourceMap: !isProduction, // css sourceMap 配置
        loaderOptions: {... 其它代码}
    },
     ... 其它代码
}

此时再npm run build 打包,就会发现速度快了很多,体积霎时只有几兆了!

2. 剖析大文件,找出内鬼

装置 npm install webpack-bundle-analyzer -D 插件,打包后会生产一个本地服务,分明的展现打包文件的蕴含关系和大小。

vue.config.js 配置:


const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
    ... 其它
    configureWebpack: [
        plugins: [new BundleAnalyzerPlugin() // 剖析打包大小应用默认配置
        ]
    },
  ... 其它
}

自动弹出一个服务,清晰的展现打包后 js 的文件大小:

通过图中能够发现:

  1. element-ui 和 ant-design 占了近 1 / 4 的大小:1.53MB
  2. exceljs 也是个大货色有:1.3MB
  3. echarts.js 文件也靠近1MB
  4. moment.js 也有700KB

打包后 js 文件一共就 5MB,这五个哥们就占了 4M 左右。不剖析好还,一剖析吓得够呛~

不要虚!找到刺了,一个一个来拔掉就好了。置信我拔掉的过程是很爽的。

一个一个解决,拔刺

1. 把必须要用的第三方 js 通过 cdn 的形式援用

剖析发现,elementui、echarts是必须应用的,打包又耗时且页面加载也较慢得很。能够通过 cdn 间接引入,不便且速度快。

1.element-ui是咱们我的项目用的次要框架,所以这个必定是少不了,然而我的项目外面 ant-design 为什么会存在呢,原来是发现有个页面应用了 antd 的进度条组件,因为 elementui 的进度条不太好看。然而没想到这样把整个 antd 都导进来了。

计划:

  1. 舍弃 antd 组件,本人去找一个相似的 vue 插件或者罗唆本人实现一个。(这个办法短时间无奈实现,且不想去动以前代码,暂不思考)
  2. 应用 antd 局部加载。只加载想要的进度条组件,能够缩小文件体积(这个办法简略粗犷,就是就义一些文件大小)。

咱们应用计划2,依据 antd 官网的文档配置局部组件的引入。

装置 npm install babel-plugin-import -D

1 main.js导入须要的组件 Step

import {Steps} from 'ant-design-vue';
Vue.component(Steps.name, Steps);
Vue.component(Steps.Step.name, Steps.Step);

2 babel.config.js 加上配置:

module.exports = {
  presets: ['@vue/cli-plugin-babel/preset'],
  // 以下是按需加载的配置 ++++
  plugins: [
    [
      "import",
      {
        libraryName: "ant-design-vue",
        libraryDirectory: "es",
        style: true
      }
    ]
  ]
}

此时再剖析,antd曾经小了很多。

2. 应用 cdn 加载第三方 js。

咱们我的项目外面第三方 js 很多,有些打包下来会很大,而且加载速度较慢。咱们把这些 js 分离出来,通过 cdn 的形式在 html 中的 script 标签中间接应用,一方面缩小打包体积,一方面进步了加载速度。

这里举荐一个收费的 cdn: BootCDN。也能够应用本人购买的付费cdn 服务,咱们到网站搜寻本人我的项目须要的js。例如:vue

留神,肯定要抉择本人我的项目对应的版本,否则会呈现各种奇怪的问题

我的我的项目应用的是 "vue": "^2.6.12", (package.json)

第一步:配置 vue.config.js,让webpack 不打包这些 js,而是通过 script 标签退出。

const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境
// 正式环境不打包公共 js
let externals = {}
// 贮存 cdn 的文件
let cdn = {
    css: ['https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/theme-chalk/index.min.css' // element-ui css 样式表],
    js: []}
// 正式环境才须要
if (isProduction) {
    externals = { // 排除打包的 js
        vue: 'Vue',
        'element-ui': 'ELEMENT',
        echarts: 'echarts',
    }
    cdn.js = [
        'https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js', // vuejs
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.6.0/index.js', // element-ui js
        'https://cdn.bootcdn.net/ajax/libs/element-ui/2.6.0/locale/zh-CN.min.js',
        'https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js',
    ]
}
module.exports = {
//... 其它配置
configureWebpack: {
        // 罕用的公共 js 排除掉,不打包 而是在 index 增加 cdn,externals, 
        //... 其它配置
    },
chainWebpack: config => {
        //... 其它配置  
        // 注入 cdn 变量 (打包时会执行)
        config.plugin('html').tap(args => {args[0].cdn = cdn // 配置 cdn 给插件
            return args
        })
    }
//... 其它配置     
}

第二步:html 模板中退出定义好的 cdn 变量应用的代码

<!DOCTYPE html>
<html lang="">

<head>
<meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>web</title>
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- 引入款式 -->
    <% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
       <link rel="stylesheet" href="<%=css%>" >
    <% } %>

    <!-- 引入 JS -->
    <% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
       <script src="<%=js%>"></script>
    <% } %>
</head>
<body style="font-size:14px">
    <div id="app"></div>
</body>
</html>

能够发现 cdn.js 中,我把 vue、echarts、element-ui 这三个大头退出了。在 externals 对象中左侧是 npm 包的名称,右侧是在代码中裸露的全局变量。留神 element-ui 对应的是 ELEMENT

没有 ant-design-vue 是因为咱们下面应用了局部加载的形式,如果应用 cdn 这种形式是加载全副的代码,有点节约。

没有应用 exclejs,是因为exceljs 在我的业务代码中不是间接援用的,而是一个叫 table2excel 间接依赖的。所以就算我通过下面的办法排除掉它,在打包的时候还是会通过 table2excel 的依赖找到它并打包。

那这种不可避免的状况,该如何优化,让加载速度不受影响呢?

答案是通过 懒加载 的形式:

1.script 标签中正文掉 import Table2Excel from "table2excel.js";

2. 下载的办法中:download(){// 应用 import().then()形式
    import("table2excel.js").then((Table2Excel) => {new Table2Excel.default("#table").export('filename') // 多了一层 default 
    })
}

这样在进入零碎时,不会加载Table2Excelexceljs,当须要时才会去加载,第一次会慢一点,前面就不须要加载了,会变快。

3 moment.js 的优化

咱们发现 monentjs 在我的项目中有应用来对工夫格式化,然而应用频率并不高,齐全能够本人实现一个 format 办法,或者应用只有 6kbday.js.

但这里咱们暂不替换,把 moment 变得瘦小一些即可,删除掉除中文以外的语言包

第一步:vue.config.js

... 其它配置
 chainWebpack: config => {config.plugin('ignore')
        // 疏忽 /moment/locale 下的所有文件
     .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
 }
... 其它配置

第二步:main.js

import moment from 'moment'
// 手动引入所须要的语言包
import 'moment/locale/zh-cn';
// 指定应用的语言
moment.locale('zh-cn');

这次咱们看看 moment 打包后多大:

只有 174kb 了。不过,有一说一还是 day.js 香~

做完下面这些动作咱们的 js 文件总大小:3.04MB,其中蕴含 1.3MB的懒加载 js,剩下的 1.7MB 左右的 js 基本上不会对页面造成很大的卡顿。

还有提高空间?

1. 通过 compression-webpack-plugin 插件把代码压缩为 gzip。然而!须要服务器反对

webpackvue.config.js配置如下:

// 打包压缩动态文件插件
const CompressionPlugin = require("compression-webpack-plugin")

//... 其它配置
module.exports = {
    //... 其它配置
    chainWebpack: config => {
        // 生产环境开启 js\css 压缩
        if (isProduction) {config.plugin('compressionPlugin').use(new CompressionPlugin({test: /\.(js)$/, // 匹配文件名
                threshold: 10240, // 对超过 10k 的数据压缩
                minRatio: 0.8,
                deleteOriginalAssets: true // 删除源文件
            }))
        }
    }
    //... 其它配置
}

打包大小由 3MB860KB,感觉腾飞了~

服务器端配置这里就不具体阐明了能够谷百:nginx 开启动态压缩 找到答案。

最初贴上优化前后的无缓存下的首屏加载工夫比照(chrome 浏览器),相对包真:

优化前我的项目网站首屏加载数据:9.17s

优化后我的项目网站首屏加载数据:1.24s

这些都是在工作之余,本人抽时间去查阅各位大佬的帖子,尽管都是些耍栏了的技术,然而真的要在本人我的项目中施行还是须要一些工夫和精力,大多数都是为了实现性能疾速迭代而疏忽掉了做程序本来的目标,就是要让用户有一个良好的应用体验。

肯请各位大佬, 不要忘了给我 点赞 评论 珍藏

往期精彩:

1. 什么是迭代器(iterator)?Generator 和它有什么关联

2. 微信小程序 UI 组件、图表、自定义 bar 这些坑都帮你踩了

正文完
 0