尝试用 pm.js spa 方案改造了一个原生 js 的 admin 模板项目,性能大幅提升

2021-01-22 14:55:04 +08:00
 lesismal

前阵子发布过 pm.js ,原帖在这里:

发布 pm.js ,包括但不限于帮助构建 web 原生单页面

非专业前端,用词未必准确,脸皮防御值高,欢迎来喷。。。

最近随便 fork 了个 admin 的模板项目,用 pm.js 改造了下,去掉了多个页面大量的重复内容、避免不必要的重复加载、重复下载之类的,对比 fork 原作,切换内容顺滑、性能要好太多,不谦虚地说,就是性能基本能达到极致了

我对前端不算熟悉,所以暂时主要研究研究框架相关

有兴趣的朋友欢迎多来指点、给些批评建议(性能提升跟 fork 原作对比就可以了):

https://github.com/3rdrepo/adminkit

2661 次点击
所在节点    JavaScript
10 条回复
bmwh123
2021-01-22 17:28:40 +08:00
有一个问题就是设置成 display none 的页面也是会加载的,那首屏的加载时间随着项目膨胀也会变长很多,这个怎么解决的呀
lesismal
2021-01-22 18:13:28 +08:00
@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(){...}, //被隐藏时调用
}
lesismal
2021-01-22 18:17:22 +08:00
@bmwh123 还提供了$pm.release(page),可以用于释放单个 page 的内容,如果应用层子页面内容太多想减少总资源占用压力,可以根据自己的需要、在 onhide(page) 中选择是否对该子页面内容释放,就是对该 dom 元素的 innerHTML 设置为""。
lesismal
2021-01-22 21:04:22 +08:00
@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(...) 时才去加载的,并不是进到主页默认就把所有加载进来
lesismal
2021-01-22 21:05:45 +08:00
not lazy 的是进来就加载的,都可配,业务层自由管理
alan0liang
2021-01-23 11:43:13 +08:00
原作问题真的是太大了……基本怎么优化都能好很多
一个 1.6M 的 app.js (优化:split chunks )被所有页面使用(优化:分 entrypoint 按需加载),还没有缓存(优化:immutable + 缓存),还没有 CDN (优化:静态资源单独走 CDN ),这能不慢吗🤣
lesismal
2021-01-23 12:34:03 +08:00
@alan0liang 是啊,我找了好几个 bootstrap admin template,都差不多的情况。可能这些主要是为了展示 template 功能、没做优化,但是既然是作为 template,别人拿来用也是希望快速实现功能,所以性能问题还是太不友好了。
还有很大程度上其实应该是使用传统原生 js 方式的的老技术、工程体系的锅,react vue 崛起之前的前端社区的大部分人缺少工程思维,react vue 崛起后框架强行工程优化了
bmwh123
2021-01-25 09:28:09 +08:00
@lesismal 听起来感觉蛮不错的 项目有文档嘛 我再研究研究,要是可以用到公司的老项目上就好了
lesismal
2021-01-25 15:34:52 +08:00
@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;">&nbsp;</div>
<button class="button">
<a href="#page_1" class="button">Page 1<br>Click Me</a>
</button>
<div style="height: 2px;">&nbsp;</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();
lesismal
2021-01-25 15:36:15 +08:00
完整的例子可以看这里:
https://github.com/lesismal/pm/tree/master/examples/bind_src_dst

还有个项目是 fork 了个别人的 admin template,用 pm.js 改造了下,可以直接对比 fork 的原作,性能提升太明显了。。
https://github.com/3rdrepo/adminkit

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/747412

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX