0


离线H5及性能优化

app内H5页面离线技术和性能优化工作总结

前提:需要app native支持html文件存储(仅仅离线化html文件)

技术实现思路:

  1. 访问H5地址
  2. app识别是否有 对应版本/离线H5的html文件 (没有就去服务器下载)
  3. webview打开html
  4. 是否有js、css等静态资源(第一次没有,要花网络请求时间去请求)
  5. 静态资源做好本地缓存设置,可以设置http的response-headers缓存
  6. 渲染页面

一些注意点

  1. 离线方案中仅仅离线了HTML文件,其他的资源首次以在线形式进行访问,然后充分利用CDN缓存。
  2. 二次访问,达到离线+缓存资源实现页面快速渲染。
  3. 更新分成两部分:离线HTML文件更新,由口袋离线应用包通过资源版本号管理,每次发版会触发重新拉取;资源更新,由html中资源路径的变化控制,每次发版,资源路径会变化。
  4. 多页面部分资源尽量做到共用,做到缓存最大使用

根据业务代码目录结构打包html产物:
modules.js

const glob = require('glob');
const fs = require('fs');
const path = require('path');
const resolveApp = (pathname) => path.resolve(process.cwd(), pathname);
const APP_DIR = resolveApp('src/views/');

function handleEntryConfig(checkPath) {
    const chunk = [];
    const list = glob.sync(checkPath).map(file => {
        const data = path.parse(file);
        // 拿到.html存在对应的.js
        if (fs.existsSync(`${data.dir}${path.sep}${data.name}.js`)) {
            const dir_path = data.dir.replace(APP_DIR, '');
            // console.log('dir_path====', dir_path);
            const arr = dir_path.split(path.sep).filter(Boolean);
            const name = arr.join('_');
            let filename = '';
            if (data.name === 'index') {
                filename = name;
            } else {
                filename = `${name}_${data.name}`;
            }
            chunk.push({
                filename: `${filename}.html`,
                template: file,
                chunk: filename,
            });
            return {
                [filename]: `${data.dir}${path.sep}${data.name}.js`,
            };
        }
    });
    const entry = list.reduce(function (reduce, item) {
        return Object.assign(reduce, item);
    }, {});
    // console.log('输出页面配置=====', { entry: entry, chunk: chunk, list: list });
    return {
        chunk,
        entry,
        listEntry: list,
    };
}
module.exports = function (options) {
    let chunk = [],
        entry = {},
        list = [];
    const checkPath = `${APP_DIR}/**/*.html`; // 查找目录入口, 默认查找src/views下面所有的html
    const modules = require('../modules/')(options);
    // sirus离线打包
    if (options.pages) {
        modules.increase = [options.pages];
    }
    // dev环境pack为空或增量,increase存在配置
    if (['', 'inc'].includes(options.pack) && modules.increase.length > 0) {
        modules.increase.forEach(module => {
            const path = resolveApp(`${APP_DIR}/${module}`);
            const data = handleEntryConfig(`${path}/**/*.html`);
            // console.log('data 数据======', data);
            data.chunk.forEach(item => {
                chunk.push(item);
            });
            list = list.concat(data.listEntry);
            Object.assign(entry, data.entry);
        });
    } else if (options.pack === 'all' || modules.increase.length === 0) {
        // all 或为空则全量
        const data = handleEntryConfig(checkPath);
        chunk = data.chunk;
        entry = data.entry;
        list = list.concat(data.listEntry);
    }
    // console.log('最终输出页面配置=====', { entry: entry, chunk: chunk, listEntry: list });
    return {
        chunk,
        entry,
        listEntry: list,
    };
};

modules.js

module.exports = {
    ignore: [], // 忽略构建的模块
    increase: ['xxx/xxxxxx'], // 为空则打全量,否则构建指定的模块
};

webpack.js打包部分引入modules.js中运行出来的产物:
entry赋值给entry使用;
chunk给HtmlWebpackPlugin,打包chunk使用

性能优化部分

  1. 使用 link标签 对cdn资源域名、接口资源域名 进行提前预建联,字体文件预加载
<link rel="preconnect" href="https://cdn-xxx.xxxx.xxx.xx" />
<link rel="dns-prefetch" href="https://cdn-xxx.xxxx.xxx.xx" />
<link rel="dns-prefetch" href="https://api-xxx.xxxx.xxx.xx" />
<link rel="preload" as="font" type="font/woff2" crossorigin="anonymous" href="https://xxx.xx/woff2" />
  1. cdn资源、公用js库,不经常更新版本的设置缓存,加载缓存的文件
  2. 分屏加载组件,非首屏的组件做动态加载,降低了首屏加载的js大小
<!--第二屏渲染组件-->
<component ref="dynamicComponent" :is="comName" :prdCode="prdCode" :templateId="templateId"></component>

mounted() {
    this.$nextTick(() => {
        this.lazyLoadUnFirstBundle();
    });
}
   
lazyLoadUnFirstBundle() {
    this.comName = () =>
    import(/* webpackChunkName: "deposit_structured_detai_second_screen" */ './detail_part2.vue').then(
        m => m.default,
    );
},
  1. 首屏数据做LocalStorage的缓存,注意5M内存满了没法继续存时清空旧的
  2. 首屏渲染之后,再使用loadjs加载三方组件,比如分享、电梯、广告弹窗等js
  3. 函数、变量的引入使用按需引入
  4. 编码时考虑tree shaking
  5. 按需加载polyfill.js替代babel编译
  6. 优化FCP前的接口请求,修改接口的调用时机,非必要的接口后置,可合并的接口合并
标签: 性能优化

本文转载自: https://blog.csdn.net/qq_39302236/article/details/140174473
版权归原作者 Chngoshawk 所有, 如有侵权,请联系我们删除。

“离线H5及性能优化”的评论:

还没有评论