Skip to content

Commit dcb86cd

Browse files
authored
feat(site): optimize the performance of the official website, use lazy loading for document examples (#2713)
* feat(site): optimize the performance of the official website, use lazy loading for document examples * feat(site): 还原mobile依赖
1 parent f0fb1f3 commit dcb86cd

File tree

5 files changed

+174
-161
lines changed

5 files changed

+174
-161
lines changed

examples/sites/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"build:saas:open": "vite build --mode saasopen",
1616
"build:saas:prod": "vite build --mode saasprod",
1717
"build": "vite build --mode pages && cp cp-component-md.sh ./dist",
18+
"build:visualizer": "vite build --mode visualizer",
1819
"build:open": "vite build --mode open",
1920
"prettier": "npx prettier --write ./**/*.{ts,tsx,css,less,scss,vue}",
2021
"stylelint": "npx stylelint ./src/**/*.scss ./src/**/*.less ./src/**/*.css --fix",
@@ -56,6 +57,7 @@
5657
"@opentiny-internal/unplugin-virtual-template": "workspace:~",
5758
"@opentiny/vue-mobile": "workspace:~",
5859
"@playwright/test": "~1.42.0",
60+
"rollup-plugin-visualizer": "^5.12.0",
5961
"@types/markdown-it": "^12.2.3",
6062
"@types/node": "^17.0.45",
6163
"@unocss/preset-icons": "^0.38.2",
@@ -82,7 +84,7 @@
8284
"unocss": "^0.39.3",
8385
"unplugin-vue-components": "^0.19.9",
8486
"uslug": "^1.0.4",
85-
"vite": "catalog:",
87+
"vite": "^4.3.8",
8688
"vite-plugin-dynamic-import": "1.5.0",
8789
"vite-plugin-html": "^3.0.0",
8890
"vite-plugin-inspect": "^0.5.0",
@@ -91,4 +93,4 @@
9193
"vite-svg-loader": "^3.6.0",
9294
"vue-tsc": "^1.8.5"
9395
}
94-
}
96+
}

examples/sites/src/views/components/cmp-config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// 批量导入vue组件示例文件, 进行vue组件示例的渲染
22
const vueFiles = import.meta.glob(`@demos/app/**/*.vue`)
3+
4+
// 所有demo组件实例
35
const vueComponents = Object.create(null)
46
for (const path in vueFiles) {
57
if (Object.prototype.hasOwnProperty.call(vueFiles, path)) {

examples/sites/src/views/components/components.vue

Lines changed: 35 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -20,84 +20,7 @@
2020
<div class="ti-rel cmp-container">
2121
<div class="flex-horizontal docs-content-main">
2222
<div class="docs-tabs-wrap">
23-
<div v-if="['interfaces', 'types', 'classes'].includes(cmpId)" id="TS" class="all-api-container">
24-
<div class="ti-f-c ti-f-wrap api-list">
25-
<div class="mt20" v-for="oneGroup in currJson.apis" :key="oneGroup.name">
26-
<div class="ti-f-r ti-f-pos-start ti-fw-bold">
27-
<div :id="`cmp-${oneGroup.name}`" class="ti-f18">
28-
{{ oneGroup.name }}
29-
</div>
30-
<div class="ti-ml12 ti-b-a-primary ti-c-primary ti-px8 ti-py4">
31-
{{ oneGroup.type }}
32-
</div>
33-
</div>
34-
<div v-for="(oneApiArr, key) in oneGroup" :key="key">
35-
<template v-if="key !== 'name' && key !== 'type' && oneApiArr.length > 0">
36-
<div class="ti-f18 ti-py28" :id="`${oneGroup.name}--${key}`">
37-
{{ key }}
38-
</div>
39-
<div class="api-table-box">
40-
<tiny-grid class="api-table" :data="tableData[oneGroup.name][key]" :expand-config="apiExpandConf">
41-
<tiny-grid-column
42-
v-if="tableData[oneGroup.name][key][0]?.type"
43-
class-name="api-table-expand-col"
44-
type="expand"
45-
width="32"
46-
>
47-
<template #default="{ row }">
48-
<async-highlight v-if="row.code" :code="row.code.trim()" types="ts"></async-highlight>
49-
</template>
50-
</tiny-grid-column>
51-
<tiny-grid-column field="name" :title="i18nByKey('name')" :width="columnWidth[key][0]">
52-
<template #default="{ row }">
53-
<span class="api-table-name">
54-
<a v-if="row.demoId" @click="jumpToDemo(row.demoId)">{{ row.name }}</a>
55-
<span v-else>{{ row.name }}</span>
56-
</span>
57-
<version-tip
58-
v-if="row.meta || row.versionTipOption"
59-
:meta="row.meta"
60-
v-bind="row.versionTipOption"
61-
render-type="tag"
62-
tip-subject="api"
63-
>
64-
</version-tip>
65-
</template>
66-
</tiny-grid-column>
67-
<tiny-grid-column
68-
v-if="tableData[oneGroup.name][key][0]?.type"
69-
field="type"
70-
:title="i18nByKey('propType')"
71-
:width="columnWidth[key][1]"
72-
>
73-
<template #default="{ row }">
74-
<a
75-
v-if="row.typeAnchorName"
76-
:href="`${row.typeAnchorName.indexOf('#') === -1 ? '#' : ''}${row.typeAnchorName}`"
77-
v-html="row.type"
78-
></a>
79-
<span v-else v-html="row.type"></span>
80-
</template>
81-
</tiny-grid-column>
82-
<tiny-grid-column
83-
v-if="key === 'props'"
84-
field="defaultValue"
85-
:title="i18nByKey('defValue')"
86-
:width="columnWidth[key][2]"
87-
></tiny-grid-column>
88-
<tiny-grid-column field="desc" :title="i18nByKey('desc')">
89-
<template #default="data">
90-
<span v-html="data.row.desc"></span>
91-
</template>
92-
</tiny-grid-column>
93-
</tiny-grid>
94-
</div>
95-
</template>
96-
</div>
97-
</div>
98-
</div>
99-
</div>
100-
<tiny-tabs v-else v-model="activeTab" ref="demoTabs" class="docs-content-tabs" @click="onTabsClick">
23+
<tiny-tabs v-model="activeTab" ref="demoTabs" class="docs-content-tabs" @click="onTabsClick">
10124
<tiny-tab-item :title="i18nByKey('demos')" name="demos">
10225
<!-- demos列表 -->
10326
<template v-if="currJson?.demos?.length">
@@ -106,14 +29,16 @@
10629
<demo
10730
v-for="demo in currJson.demos"
10831
:key="demo.name"
32+
:observer="observer"
33+
:isIntersecting="demo.isIntersecting"
10934
:demo="demo"
11035
:curr-demo-id="currDemoId"
11136
class="mb32"
11237
@mounted="demoMounted"
11338
/>
11439
</div>
11540
<div v-else>
116-
<demo v-if="singleDemo" :key="singleDemo.name" :demo="singleDemo" />
41+
<demo v-if="singleDemo" :isIntersecting="true" :key="singleDemo.name" :demo="singleDemo" />
11742
</div>
11843
</div>
11944
</template>
@@ -294,11 +219,10 @@ export default defineComponent({
294219
webDocPath: computed(() => ''),
295220
langKey: getWord('zh-CN', 'en-US'),
296221
cmpId: '',
222+
observer: null,
297223
currJson: { column: 1, demos: [], apis: [], types: {} },
298224
cmpTopMd: null,
299225
cmpFAQMd: null,
300-
evenDemo: computed(() => state.currJson.demos?.filter((d, i) => i % 2 === 0) || []),
301-
oddDemo: computed(() => state.currJson.demos?.filter((d, i) => i % 2 === 1) || []),
302226
currDemoId: '',
303227
demoAnchorLinks: computed(() => {
304228
const links =
@@ -481,6 +405,7 @@ export default defineComponent({
481405
// 用户打开官网有时候会带一些特殊字符的hash,try catch一下防止js报错
482406
scrollTarget = document.querySelector(`#${hash}`)
483407
} catch (err) {}
408+
484409
if (scrollTarget && !isRunningTest) {
485410
// doc-layout-scoller(滚动) > tabs > tab-content(relative), 造成 scrollTarget.offsetTop 是相对于 tab-content的距离
486411
// 所以滚动需要修正 tab-title的占位高度才行
@@ -556,6 +481,12 @@ export default defineComponent({
556481
// 3、加载cmpId.js 文件
557482
// eslint-disable-next-line no-eval
558483
const json = jsData ? eval('(' + jsData.slice(15) + ')') : {}
484+
485+
// 默认设置每个实例demo都不和视图相交
486+
json.demos?.forEach((item) => {
487+
item.isIntersecting = false
488+
})
489+
559490
state.currJson = {
560491
...json,
561492
demos: $clone(json.demos || []), // 克隆一下,避免保存上次的isOpen
@@ -635,6 +566,27 @@ export default defineComponent({
635566
if (docLayout) {
636567
docLayout.addEventListener('scroll', onDocLayoutScroll)
637568
}
569+
570+
const options = {
571+
root: docLayout,
572+
threshold: 0.2
573+
}
574+
575+
const callback = (entries) => {
576+
entries.forEach((entry) => {
577+
if (entry.isIntersecting) {
578+
// 当demo示例与视图相交才加载对应的vue组件
579+
const demoId = entry.target.id
580+
state.currJson.demos.forEach((item) => {
581+
if (item.demoId === demoId) {
582+
item.isIntersecting = true
583+
}
584+
})
585+
}
586+
})
587+
}
588+
589+
state.observer = new IntersectionObserver(callback, options)
638590
})
639591
}
640592
@@ -736,6 +688,7 @@ export default defineComponent({
736688
737689
onMounted(() => {
738690
loadPage()
691+
// 加载公共尾部
739692
const common = new window.TDCommon(['#footer'], {})
740693
common.renderFooter()
741694
setScrollListener()
@@ -766,6 +719,7 @@ export default defineComponent({
766719
<style lang="less" scoped>
767720
.docs-header {
768721
padding: 16px 40px;
722+
min-height: 102px;
769723
background-color: #fff;
770724
box-shadow: 12px 0 20px 6px rgba(0, 0, 0, 0.06);
771725

0 commit comments

Comments
 (0)