H5 Hybrid性能优化方案

在混合开发中,我们经常需要H5开发一些活动页面或内嵌的H5页面。当页面比较重,或网络较差时,经常出现加载缓慢,对客户体验不好。那么如果改善这个问题呢?

先看一下webview加载流程,webview加载通常可以分为以下几个过程:

Webview加载流程

大致可以分为以下几个阶段:

1、Webview初始化

2、下载和解析Html/js/css

3、和app交互(不一定有)

4、JS请求数据

5、更新数据,页面完成渲染

其中耗时比较多的阶段为1,2

 

那么我们的解决方案就是分而治之,寻找每个阶段的优化点,每个阶段都把消耗时间降低,总的消耗时间也就降低了不是吗?


各阶段优化方案

Webview初始化

1、webview预初始化

当App首次打开时,默认是不初始化浏览器内核的;只有当创建WebView实例的时候,才会创建WebView的基础框架。所以App中打开WebView的第一步并不是建立连接,而是启动浏览器内核。

因此,我们可以在进入webview之前,比如app初始化之后,进行webview预加载。等进入webview之后就不用再初始化了,从而缩短页面首次打开时间。

这一步主要由手机端同学完成。可以新建一个预加载类。进行webview的创建、存储于缓存池中、需要再从池中获取。例如:

private WebView createWebView() {
        WebView webView = new WebView(new MutableContextWrapper(BaseApplication.application));       
        webView.setWebViewClient(new WebViewClient());
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webView.loadDataWithBaseURL(H5首页地址, "", "text/html", "utf-8",null);
        return webView;
}

public WebView getWebView(Context context) {   
        WebView webView = null;
        if (mCachedWebViewStack == null || mCachedWebViewStack.isEmpty()) {
            webView  = createWebView();           
        } else {
            webView = mCachedWebViewStack.pop();
        }
        MutableContextWrapper contextWrapper = (MutableContextWrapper) webView.getContext();
        contextWrapper.setBaseContext(context);
        return webView;
}

2、开启缓存、硬件加速

主要用于页面有较多图形绘制场景。

使用方式:在AndroidManifest中<activity>元素中使用android:hardwareAccelerated属性,启用或禁止Activity硬件加速。

 

下载和解析Html/js/css

1、不生成map文件(H5端)

config文件夹,index.js中,sourceMap设为false

productionSourceMap: false,

这样打包出来的文件不包括页面代码,整体体积会小一些

2、代码压缩(H5端)

build文件夹下,webpack.prod.js,开启html,css,js文件压缩

const HtmlWebpackPlugin = require('html-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

new HtmlWebpackPlugin({
      filename: process.env.NODE_ENV === 'testing'
        ? 'index.html'
        : config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
       }
}),

new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false
        }
      },
      sourceMap: config.build.productionSourceMap,
      parallel: true
}),

new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
}),

3、CDN加速(服务端)

4、DNS采用和客户端API相同的域名(服务端)

DNS会在系统级别进行缓存,对于WebView的地址,如果使用的域名与native的API相同,则可以直接使用缓存的DNS而不用再发起请求图片。这一步优化大概可以缩小几十ms。

5、app离线包(服务端、app端)

页面发布到CDN上面,WebView发起网络请求去拉取。当用户在弱网络或者网速比较差的环境下,这个加载时间会很长。于是可以通过离线预推的方式把页面的资源提前拉取到本地,当用户加载资源的时候,相当于从本地加载,即使没有网络,也能展示首屏页面。

6、服务端渲染,直出首屏html(服务端)

关于这一块,操作起来有点难度,对后端也不太懂,详见第二篇参考博客。

 

和app交互

这一步不一定会有。如果通过dsbridge或者jsbridge等实现app和web端的交互,进入页面,请求需要app参数才能发起请求的话,才会有这一步。这一步的优化,目前方案是,精简交互协议的数据,只传必要的参数。

 

JS请求数据

1、Gzip压缩(服务端、H5端)

H5端开启gzip开关

//index.js
productionGzip: true,

//webpack.pro.js
if (config.build.productionGzip) {
  const CompressionWebpackPlugin = require('compression-webpack-plugin')
  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

若执行报错,缺少compression-webpack-plugin,则需执行如下安装语句(注意要指明版本1.1.12,版本太高依然会报错)

npm install --save compression-webpack-plugin@1.1.12

2、客户端初始化期间代理数据请求(app端)

顾名思义,先提前确定H5页面的请求,手机端进入webview初始化页面时执行这些请求。待webview页面初始化完成后,手机端代理H5页面请求,直接返回已请求回来的接口数据。

这是个行之有效,但对于请求不多的页面改善效果有限的方法。同时也会增加手机端和H5端的代码复杂度。

 

更新数据,页面完成渲染

1、图片懒加载

安装插件

npm install vue-lazyload --save

使用

<img v-lazy="imageUrl" class=""/>

2、路由懒加载

常用的懒加载方式有两种:1、import方式(推荐) 2、异步方式

懒加载之前:

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
    routes: [
     {
          path: '/',
        name: 'HelloWorld',
        component:HelloWorld
     }
    ]
})

import方式

import Vue from 'vue'
import Router from 'vue-router'

const HelloWorld = ()=>import("@/components/HelloWorld")

Vue.use(Router)

export default new Router({
    routes: [
     {
          path: '/',
        name: 'HelloWorld',
        component:HelloWorld
     }
    ]
})

异步方式:

import Vue from 'vue'
import Router from 'vue-router'
//import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
    routes: [
     {
          path: '/',
        name: 'HelloWorld',
        component:resolve=>(require(["@/components/HelloWorld"],resolve))
     }
    ]
})

3、组件懒加载

和路由懒加载同理

懒加载之前:

<template>
  <div>
      <HelloWorld></HelloWorld>
  </div>
</template>

<script>
import HelloWorld from './HelloWorld'
export default {
  components:{
    "HelloWorld":HelloWorld
  }
}
</script>

import方式:

<template>
  <div>
      <HelloWorld></HelloWorld>
  </div>
</template>

<script>
const HelloWorld = ()=>import("./HelloWorld");
export default {
  components:{
    "HelloWorld":HelloWorld
  }
}
</script>

异步方式:

<template>
  <div>
      <HelloWorld></HelloWorld>
  </div>
</template>

<script>
export default {
  components:{
    "HelloWorld":resolve=>(['./HelloWorld'],resolve)
  }
}
</script>

 

 

参考博客:

美团技术方案

腾讯手Q Hybrid框架VasSonic

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
React H5的性能优化是开发过程中非常重要的一部分,下面是一些常见的优化策略: 1. 使用React.memo()来优化组件渲染:React.memo()可以将组件包裹起来,以减少不必要的渲染。它会对组件的 props 进行浅比较,如果 props 没有变化,则不会重新渲染组件。 2. 使用shouldComponentUpdate()或React.PureComponent来避免不必要的渲染:这些方法可以在组件更新之前进行比较,如果 props 或 state 没有变化,则可以阻止组件重新渲染。 3. 避免在render()方法中进行昂贵的计算或操作:render()方法应该只负责渲染组件,不应该包含复杂的计算逻辑或操作。 4. 使用React.lazy()和React.Suspense来实现按需加载:将大型组件拆分为多个小组件,并使用React.lazy()和React.Suspense实现按需加载,可以减少初始加载时间。 5. 使用Key属性来优化列表渲染:在使用map()方法渲染列表时,为每个子元素添加唯一的key属性,这样React可以更高效地更新列表。 6. 使用shouldComponentUpdate()或React.memo()来减少子组件的重新渲染:如果子组件的props没有变化,则可以通过shouldComponentUpdate()或React.memo()阻止子组件的重新渲染。 7. 使用虚拟化技术来优化大型列表的渲染:使用React-virtualized或react-window等库可以只渲染可见区域内的列表项,以提高性能。 8. 使用性能分析工具来找出性能瓶颈:使用React DevTools或Chrome DevTools等工具可以帮助你分析组件的渲染性能,找出潜在的性能问题。 以上是一些常见的React H5性能优化策略,你可以根据具体情况选择合适的方法来提升应用的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KWMax

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值