echart移动端优化

做移动端数据可视化产品,需要封装echarts图表做子组件,并兼容原先pc端api请求格式,还引入了地图数据,支持省份下钻。完成所有功能后,vendor大小2.49M,build速度59s,首屏加载速度和webpack打包速度都很慢。
webpack: 3.6 echarts:4.1


image.png

1241542345488_.pic_hd.jpg

优化1:echart按需加载
(echart整体画图数据包700KB,比highcharts和f2要大,技术选型上可以考虑一下其他方案。)
从全局引用,优化为按需引用。引用echarts压缩过的省份地图的js数据,json数据会大一些,还需要registerMap。

import echarts from 'echarts/lib/echarts'
import 'echarts/lib/chart/bar'
import 'echarts/lib/component/tooltip'

require('node_modules/echarts/map/js/china.js') // 引入中国地图数据
require('node_modules/echarts/map/js/province/anhui.js')
require('node_modules/echarts/map/js/province/aomen.js')
require('node_modules/echarts/map/js/province/beijing.js')
require('node_modules/echarts/map/js/province/chongqing.js')
require('node_modules/echarts/map/js/province/fujian.js')
...

优化2:路由懒加载,vue异步组件,vendor分包,首屏加载速度加快。
将路由页面拆分chunk打包,所有路由页面打包在cube中。
按需加载省市js数据,打包到province中。
封装echart子组件,打包到echarts中。

const Demo = () => import(/* webpackChunkName: 'cube' */ '@/components/pages/demo/demo')
const Notfound = () => import(/* webpackChunkName: 'cube' */ '@/components/pages/content/notfound')

let r = require.ensure([], function() {
        require('node_modules/echarts/map/js/province/anhui.js')
        require('node_modules/echarts/map/js/province/aomen.js')
        ...
      }, 'province')
      r.then(
        res => {
          this.drawChart()
        }
      )

import Vue from 'vue'
const Chart  = Vue.component('Chart', () => import(/* webpackChunkName: 'echarts' */'@/utils/echarts.vue'))
export default Chart;

分包结果:
npm run build --report

1181542267595_.pic_hd.jpg

1281542346134_.pic_hd.jpg

访问一般页面加载cube,有echarts图表加载echarts chunk,有省份地图数据下钻加载province chunk。nginx开启了gzip压缩,在webpack中也可以配置。
1271542346026_.pic_hd.jpg

优化3:webpack打包速度
分包后build速度41s,先用webpack-visualizer-plugin分析一下当前打包的状况。

const Visualizer = require('webpack-visualizer-plugin')
new Visualizer({
  filename: './statistics.html'
}),

1291542346966_.pic_hd.jpg

echarts 打包占了整个打包时长的71.3%,map地图的js数据占打包时长的28.5%。这些地图数据包括常规的vue、vue-loader等不会变化,想把他们分离出来,不用每次都打包。
开发环境:
热更新

生产环境:
配置CommonsChunkPlugin
加速文件搜索
配置 resolve.modules
设置 test & include & exclude
使用并行压缩插件 webpack-parallel-uglify-plugin
配置externals(cdn)(会增加首屏加载时长)
DllPlugin和DllReferencePlugin (会加载首屏加载时长)
使用HappyPack来加速构建

webpack.dll.conf.js:

const path = require('path');
const webpack = require('webpack');
module.exports = {
  entry: {
    vendor: [
      'axios',
      'vue-router',
      'vue'
    ]
  },
  output: {
    path: path.resolve(__dirname, '../static/js'),
    filename: '[name].dll.js',
    library: '[name]_library'
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.resolve('../static', '[name]-manifest.json'),
      name: '[name]_library'
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};
webpack.prod.conf.js:

new webpack.DllReferencePlugin({
    manifest: require('../static/vendor-manifest.json')
})
//这个主要是将生成的vendor.dll.js文件加上hash值插入到页面中。解决不同环境下的路径问题。
new AddAssetHtmlPlugin([{
  filepath: path.resolve(__dirname,'../dist/static/js/vendor.dll.js'),
  outputPath: utils.assetsPath('js'),
  publicPath: path.posix.join(config.build.assetsPublicPath, 'static/js'),
  includeSourcemap: false,
  hash: true,
}]),
package.json

"scripts": {
    "build:dll": "webpack --config build/webpack.dll.conf.js"
}

npm run build:dll
npm run build
webpack 3.x版本,add-asset-html-webpack-plugin需要2.1.3版本。
报错:TypeError: Cannot read property 'compilation' of undefined

1321542362539_.pic_hd.jpg

dll真是快的起飞啊,build时间从41s降低到19s。
image

image

生成的vendor.dll.js放在index.html会被首屏加载,但把太多的第三方依赖都打包进去,会影响首屏加载的速度。但是不放进去会影响webpack的打包速度。
省份数据不用打包到index页面的vendor里,异步加载。
vendor是vue等基础组件,vendor2是echarts。
1331542512219_.pic_hd.jpg

1341542512363_.pic_hd.jpg

减少webpack打包时间,省份数据还编译。
加了cache-loader做缓存,用了only-if-changed-webpack-plugin插件,发现全局不动不编译,有一点动都编译。还和 html-webpack-plugin 有冲突。
巨大的echarts让人头大。

一开始想让打包好的dll,可以不首屏加载,动态加载。
发现有一个scriptjs的插件。

let scriptjs = require('scriptjs')
      // scriptjs不能单独引用require
      let r = scriptjs(echart_prefix + 'dist/echarts.min.js', () => {
        scriptjs(echart_prefix + 'map/js/china.js') // 引入中国地图数据
        let map_province = ['anhui', 'aomen', 'beijing', 'chongqing', 'fujian', 'gansu', 'guangdong', 'guangxi', 'guizhou', 'hainan', 'hebei', 'heilongjiang', 'henan', 'hubei', 'jiangsu', 'jiangxi', 'jilin', 'liaoning', 'neimenggu', 'ningxia', 'qinghai', 'shandong', 'shanghai', 'shanxi1', 'sichuan', 'taiwan', 'tianjin', 'xianggang', 'xinjiang', 'xizang', 'yunnan', 'zhejiang']
        let map_province_data = []
        for (let x in map_province) {
          map_province_data.push(echart_prefix + 'map/js/province/' + map_province[x] + '.js')
        }
        scriptjs(map_province_data, () => {
          this.drawChart()
        })
      })

把echarts、地图数据拆到cdn里,scriptjs按需加载。


1361542621208_.pic_hd.jpg

1371542621283_.pic.jpg

1381542621435_.pic_hd.jpg

总结:
程序猿学好英语是件很重要的事情,github看的让人头大。
小师傅好厉害,哈哈哈。

相关链接:
https://www.npmjs.com/package/scriptjs
https://github.com/webpack/webpack/issues/3115

你可能感兴趣的:(echart移动端优化)