前阵子发布过 pm.js ,原帖在这里:
发布 pm.js ,包括但不限于帮助构建 web 原生单页面
非专业前端,用词未必准确,脸皮防御值高,欢迎来喷。。。
最近随便 fork 了个 admin 的模板项目,用 pm.js 改造了下,去掉了多个页面大量的重复内容、避免不必要的重复加载、重复下载之类的,对比 fork 原作,切换内容顺滑、性能要好太多,不谦虚地说,就是性能基本能达到极致了
我对前端不算熟悉,所以暂时主要研究研究框架相关
有兴趣的朋友欢迎多来指点、给些批评建议(性能提升跟 fork 原作对比就可以了):
1
bmwh123 2021-01-22 17:28:40 +08:00
有一个问题就是设置成 display none 的页面也是会加载的,那首屏的加载时间随着项目膨胀也会变长很多,这个怎么解决的呀
|
2
lesismal OP @bmwh123 有个 lazy 选项,lazy: true 的子页面是等到需要展示的时候才进行异步加载的,比如:
https://github.com/3rdrepo/adminkit/blob/dev/static/js/init.js#L18 每个页面可以配置: { src: "pages-profile.src", // 这个 id 的元素 onclick 时会切换内容到 dst dst: "pages-profile.html", url: "page/pages-profile.html", lazy: true, //如果 url 不为空,lazy 为 true 则等到首次显示 dst 内容时加载 url 对应的子页面 init: function() {...}, //首次显示时调用 onshow: function(){...}, //被显示时调用 onhide: function(){...}, //被隐藏时调用 } |
3
lesismal OP @bmwh123 还提供了$pm.release(page),可以用于释放单个 page 的内容,如果应用层子页面内容太多想减少总资源占用压力,可以根据自己的需要、在 onhide(page) 中选择是否对该子页面内容释放,就是对该 dom 元素的 innerHTML 设置为""。
|
4
lesismal OP @bmwh123 抱歉才看懂问题,前面的回答默认以为大家知道实际的机制了呢。。。
实际上单个大页面分为主页面和子页面,主页面里大概是这样子的: <div class="main"> <div id="nav"></div> <div id="dashboard.html"></div> <div id="charts-chartjs.html"></div> <div id="forms-basic-inputs.html"></div> <div id="forms-layouts.html"></div> <div id="icons-feather.html"></div> <div id="maps-google.html"></div> <div id="pages-blank.html"></div> <div id="pages-invoice.html"></div> <div id="pages-profile.html"></div> <div id="pages-settings.html"></div> <div id="pages-sign-in.html"></div> <div id="pages-sign-up.html"></div> <div id="tables-bootstrap.html"></div> <div id="ui-alerts.html"></div> <div id="ui-buttons.html"></div> <div id="ui-cards.html"></div> <div id="ui-general.html"></div> <div id="ui-grid.html"></div> <div id="ui-modals.html"></div> <div id="ui-typography.html"></div> <div id="footer"></div> </div> 每个子 div 的 id 对应一个子页面,然后才是上面 lazy 相关的回答,如果 lazy 默认是不加载的、而等用户首次点击触发 $pm.select(...) 或者代码 $pm.select(...) 时才去加载的,并不是进到主页默认就把所有加载进来 |
5
lesismal OP not lazy 的是进来就加载的,都可配,业务层自由管理
|
6
alan0liang 2021-01-23 11:43:13 +08:00 via Android
原作问题真的是太大了……基本怎么优化都能好很多
一个 1.6M 的 app.js (优化:split chunks )被所有页面使用(优化:分 entrypoint 按需加载),还没有缓存(优化:immutable + 缓存),还没有 CDN (优化:静态资源单独走 CDN ),这能不慢吗🤣 |
7
lesismal OP @alan0liang 是啊,我找了好几个 bootstrap admin template,都差不多的情况。可能这些主要是为了展示 template 功能、没做优化,但是既然是作为 template,别人拿来用也是希望快速实现功能,所以性能问题还是太不友好了。
还有很大程度上其实应该是使用传统原生 js 方式的的老技术、工程体系的锅,react vue 崛起之前的前端社区的大部分人缺少工程思维,react vue 崛起后框架强行工程优化了 |
9
lesismal OP @bmwh123 其实就是把老方案的内容摘出来放到单独的 html 子页面,index.html 里放上对应的 dom 元素,用 pm.bindPages 绑定这些 dom 元素的 id 和对应的子页面 url,可以手动 $pm.select 切换页面 也可以带上 src 配置项在对应的 dom onclick 时自动切换内容,或者配置的 dst 值就用 router,然后 $pm.listenRouter 用路由的方式自动切换,比如:
<div id="menu" class="side_bar"> <div style="height: 2px;"> </div> <button class="button"> <a href="#page_1" class="button">Page 1<br>Click Me</a> </button> <div style="height: 2px;"> </div> <button class="button"> <a href="#page_2">Page 2<br>Click Me</a> </button> </div> dom 树上两个 <a> 分别路由到: href="#page_1" href="#page_2" // 页面配置 && 绑定 let pages = [ { dst: "page_1", url: "page/page_1.html", }, { dst: "page_2", url: "page/page_2.html", // lazy 为 true 时则第一次显示时才进行加载,否则进入页面就开始加载 lazy: true, }, ]; $pm.bindPages(pages); // 显示 page_1 $pm.select("page_1"); // 监听路由变化、自动切换页面,比如路由切换到 #page_2 时,相当于执行 $pm.select("page_2") $pm.listenRouter(); |
10
lesismal OP 完整的例子可以看这里:
https://github.com/lesismal/pm/tree/master/examples/bind_src_dst 还有个项目是 fork 了个别人的 admin template,用 pm.js 改造了下,可以直接对比 fork 的原作,性能提升太明显了。。 https://github.com/3rdrepo/adminkit |