Skip to content

Commit 74af02e

Browse files
authored
chore(docs): improve page load time by pre-parsing README.md at build time (#5290)
Co-authored-by: Jacob Müller
1 parent c0c8a68 commit 74af02e

File tree

21 files changed

+372
-207
lines changed

21 files changed

+372
-207
lines changed

docs/components/carbon-ad.js

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,38 @@ export default {
1919
default: 'bootstrap-vuejsorg'
2020
}
2121
},
22+
data() {
23+
return {
24+
mounted: false
25+
}
26+
},
2227
computed: {
2328
src() {
2429
return `${this.url}?serve=${this.serve}&placement=${this.placement}`
2530
}
2631
},
32+
mounted() {
33+
this.$nextTick(() => {
34+
requestAnimationFrame(() => {
35+
this.mounted = true
36+
})
37+
})
38+
},
39+
beforeDestroy() {
40+
this.mounted = false
41+
},
2742
render(h) {
28-
return h('aside', { staticClass: 'bv-carbon-ad' }, [
29-
h('client-only', [
30-
h('script', {
31-
attrs: {
32-
id: this.id,
33-
async: 'async',
34-
type: 'text/javascript',
35-
src: this.src
36-
}
37-
})
38-
])
39-
])
43+
let $script = h()
44+
if (this.mounted) {
45+
$script = h('script', {
46+
attrs: {
47+
id: this.id,
48+
async: 'async',
49+
type: 'text/javascript',
50+
src: this.src
51+
}
52+
})
53+
}
54+
return h('aside', { staticClass: 'bv-carbon-ad' }, [$script])
4055
}
4156
}

docs/components/header.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@
3030

3131
<div class="navbar-nav-scroll">
3232
<b-navbar-nav class="bd-navbar-nav flex-row">
33-
<b-nav-item to="/docs" active-class="active" exact>Docs</b-nav-item>
34-
<b-nav-item to="/docs/components" active-class="active">Components</b-nav-item>
35-
<b-nav-item to="/docs/directives" active-class="active">Directives</b-nav-item>
36-
<b-nav-item to="/docs/icons" active-class="active">Icons</b-nav-item>
33+
<b-nav-item to="/docs" active-class="active" exact no-prefetch>Docs</b-nav-item>
34+
<b-nav-item to="/docs/components" active-class="active" no-prefetch>Components</b-nav-item>
35+
<b-nav-item to="/docs/directives" active-class="active" no-prefetch>Directives</b-nav-item>
36+
<b-nav-item to="/docs/icons" active-class="active" no-prefetch>Icons</b-nav-item>
3737
<b-nav-item to="/docs/reference" active-class="active">Reference</b-nav-item>
3838
<!-- TODO: Uncomment when we have themes
39-
<b-nav-item to="/themes" active-class="active">Themes</b-nav-item>
39+
<b-nav-item to="/themes" active-class="active" no-prefetch>Themes</b-nav-item>
4040
-->
41-
<b-nav-item to="/play" active-class="active">Play</b-nav-item>
41+
<b-nav-item to="/play" active-class="active" no-prefetch>Play</b-nav-item>
4242
</b-navbar-nav>
4343
</div>
4444

docs/components/main-docs.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import CarbonAd from '~/components/carbon-ad'
22
import Main from '~/components/main'
33
import QuickLinks from '~/components/quick-links'
4+
import Reload from '~/components/reload'
45
import Section from '~/components/section'
5-
import { parseReadme } from '~/utils'
66
import { mergeData } from 'vue-functional-data-merge'
77

88
// @vue/component
@@ -14,18 +14,25 @@ export default {
1414
type: String,
1515
default: 'main'
1616
},
17-
readme: {
17+
titleLead: {
18+
type: String,
19+
default: ''
20+
},
21+
body: {
1822
type: String,
1923
default: ''
2024
},
2125
meta: {
2226
type: Object,
2327
default: null
28+
},
29+
loadError: {
30+
type: Boolean,
31+
default: false
2432
}
2533
},
2634
render(h, { props, data, children }) {
27-
const { tag, readme, meta } = props
28-
const { titleLead, body } = parseReadme(readme || '')
35+
const { tag, titleLead, body, meta, loadError } = props
2936
const { version } = meta || {}
3037

3138
// Lead section
@@ -45,6 +52,9 @@ export default {
4552
])
4653
}
4754

55+
// Error handler
56+
const $error = loadError ? h(Reload) : h()
57+
4858
// Carbon Ad
4959
const $carbonAd = h(CarbonAd)
5060

@@ -59,6 +69,7 @@ export default {
5969

6070
return h(Main, mergeData(data, { props: { tag } }), [
6171
$leadSection,
72+
$error,
6273
$availableSinceSection,
6374
$carbonAd,
6475
$quickLinks,

docs/components/reload.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import Section from './section'
2+
3+
// @vue/component
4+
export default {
5+
name: 'BVReload',
6+
render(h) {
7+
const $heading = h('h1', [
8+
h('span', { staticClass: 'bd-content-title' }, 'Updated documentation')
9+
])
10+
const $lead = h(
11+
'p',
12+
{ staticClass: 'lead' },
13+
'Updated documentation is available. Please reload.'
14+
)
15+
const $button = h(
16+
'b-button',
17+
{
18+
props: { variant: 'primary' },
19+
on: {
20+
click: () => {
21+
window.location.reload(true)
22+
}
23+
}
24+
},
25+
'Reload page'
26+
)
27+
return h(Section, [$heading, $lead, h('p', [$button])])
28+
}
29+
}

docs/components/sidebar.vue

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@
77
<b-link
88
v-for="group in nav"
99
:key="group.base"
10-
:to="buildUrl('/docs/', [group.base])"
10+
:to="buildUrl('/docs', [group.base])"
1111
:exact="group.exact"
1212
router-tag="div"
1313
class="bd-toc-item"
1414
active-class="active"
1515
>
1616
<b-link
17-
:to="buildUrl('/docs/', [group.base])"
17+
:to="buildUrl('/docs', [group.base])"
1818
:exact="group.exact"
1919
class="bd-toc-link"
2020
active-class=""
21+
no-prefetch
2122
>
2223
{{ group.title }}
2324
<b-badge v-if="group.new" tag="small" variant="success" class="text-uppercase">New</b-badge>
@@ -29,13 +30,13 @@
2930
<b-link
3031
v-for="page in group.pages"
3132
:key="page.title"
32-
:to="buildUrl('/docs/', [group.base, page.slug])"
33+
:to="buildUrl('/docs', [group.base, page.slug])"
3334
router-tag="li"
3435
class="nav-item"
3536
active-class="active bd-sidenav-active"
3637
>
3738
<b-link
38-
:to="buildUrl('/docs/', [group.base, page.slug])"
39+
:to="buildUrl('/docs', [group.base, page.slug])"
3940
:exact="group.exact"
4041
class="nav-link"
4142
active-class=""
@@ -51,13 +52,41 @@
5152
</b-link>
5253

5354
<!-- TODO: Uncomment when we have themes
54-
<b-link to="/themes" exact router-tag="div" active-class="active">
55-
<b-link to="/themes" exact class="bd-toc-link" active-class="">Themes</b-link>
55+
<b-link
56+
to="/themes"
57+
router-tag="div"
58+
active-class="active"
59+
no-prefetch
60+
exact
61+
>
62+
<b-link
63+
to="/themes"
64+
active-class=""
65+
exact
66+
no-prefetch
67+
class="bd-toc-link"
68+
>
69+
Themes
70+
</b-link>
5671
</b-link>
5772
-->
5873

59-
<b-link to="/play" exact router-tag="div" active-class="active">
60-
<b-link to="/play" exact class="bd-toc-link" active-class="">Playground</b-link>
74+
<b-link
75+
to="/play"
76+
router-tag="div"
77+
active-class="active"
78+
exact
79+
no-prefetch
80+
>
81+
<b-link
82+
to="/play"
83+
active-class=""
84+
exact
85+
no-prefetch
86+
class="bd-toc-link"
87+
>
88+
Playground
89+
</b-link>
6190
</b-link>
6291
</nav>
6392
</template>
@@ -72,7 +101,12 @@ export default {
72101
},
73102
methods: {
74103
buildUrl(basePath, parts = []) {
75-
return `${basePath}/${parts.join('/')}`.replace(/(https?:\/\/)|(\/)+/g, '$1$2')
104+
parts = parts
105+
.filter(Boolean)
106+
.join('/')
107+
.replace(/\/$/, '')
108+
const path = [basePath, parts].filter(Boolean).join('/')
109+
return path.replace(/(https?:\/\/)|(\/)+/g, '$1$2')
76110
}
77111
}
78112
}

docs/nuxt.config.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ hljs.registerLanguage('plaintext', require('highlight.js/lib/languages/plaintext
1717

1818
// --- Constants ---
1919

20+
const RX_EXCLUDE_EXTENSIONS = /\.(s?css|js|ts)$/
2021
const RX_CODE_FILENAME = /^\/\/ ([\w,\s-]+\.[A-Za-z]{1,4})\n/m
2122

2223
const ANCHOR_LINK_HEADING_LEVELS = [2, 3, 4, 5]
@@ -33,9 +34,9 @@ const IS_PROD_DOCS =
3334
// Get routes by a given dir
3435
const getRoutesByDir = (root, dir, excludes = []) =>
3536
fs
36-
.readdirSync(`${root}/${dir}`)
37+
.readdirSync(`${[root, dir].filter(Boolean).join('/')}`)
3738
.filter(c => excludes.indexOf(c) === -1)
38-
.filter(c => !/\.(s?css|js|ts)$/.test(c))
39+
.filter(c => !RX_EXCLUDE_EXTENSIONS.test(c))
3940
.map(page => `/docs/${dir}/${page}`)
4041

4142
// --- Custom renderer ---
@@ -189,6 +190,7 @@ module.exports = {
189190

190191
config.resolveLoader.alias = config.resolveLoader.alias || {}
191192
config.resolveLoader.alias['marked-loader'] = path.join(__dirname, './utils/marked-loader')
193+
config.resolveLoader.alias['docs-loader'] = path.join(__dirname, './utils/docs-loader')
192194

193195
// Source maps make the bundles monstrous, do leave it off in prod mode
194196
if (isDev) {
@@ -198,6 +200,8 @@ module.exports = {
198200
config.module.rules.push({
199201
test: /\.md$/,
200202
use: [
203+
// Loaders are handled last to first
204+
{ loader: 'docs-loader' },
201205
{ loader: 'html-loader' },
202206
{
203207
loader: 'marked-loader',

docs/pages/docs/components/_slug.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ import Section from '~/components/section'
66
import docsMixin from '~/plugins/docs-mixin'
77
import { components as componentsMeta } from '~/content'
88

9-
const getReadMe = name =>
10-
import(`~/../src/components/${name}/README.md` /* webpackChunkName: "docs/components" */)
9+
const getReadmeData = name => {
10+
try {
11+
return import(`~/../src/components/${name}/README.md` /* webpackChunkName: "docs/components" */)
12+
} catch {
13+
return { default: { loadError: true } }
14+
}
15+
}
1116

1217
// @vue/component
1318
export default {
@@ -18,9 +23,11 @@ export default {
1823
return Boolean(componentsMeta[params.slug])
1924
},
2025
async asyncData({ params }) {
21-
const readme = (await getReadMe(params.slug)).default
22-
const meta = componentsMeta[params.slug]
23-
return { meta, readme }
26+
const name = params.slug
27+
const meta = componentsMeta[name]
28+
const readmeData = (await getReadmeData(name)).default
29+
const { titleLead = '', body = '', baseTOC = {}, loadError = false } = readmeData
30+
return { meta, titleLead, body, baseTOC, loadError }
2431
},
2532
render(h) {
2633
// Reference section
@@ -44,8 +51,10 @@ export default {
4451
key: this.$route.path,
4552
staticClass: 'bd-components',
4653
props: {
47-
readme: this.readme || '',
48-
meta: this.meta
54+
meta: this.meta,
55+
titleLead: this.titleLead,
56+
body: this.body,
57+
loadError: this.loadError
4958
}
5059
},
5160
[$referenceSection]

docs/pages/docs/directives/_slug.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ import Section from '~/components/section'
55
import docsMixin from '~/plugins/docs-mixin'
66
import { directives as directivesMeta } from '~/content'
77

8-
const getReadMe = name =>
9-
import(`~/../src/directives/${name}/README.md` /* webpackChunkName: "docs/directives" */)
8+
const getReadmeData = name => {
9+
try {
10+
return import(`~/../src/directives/${name}/README.md` /* webpackChunkName: "docs/directives" */)
11+
} catch {
12+
return { default: { loadError: true } }
13+
}
14+
}
1015

1116
// @vue/component
1217
export default {
@@ -17,9 +22,11 @@ export default {
1722
return Boolean(directivesMeta[params.slug])
1823
},
1924
async asyncData({ params }) {
20-
const readme = (await getReadMe(params.slug)).default
21-
const meta = directivesMeta[params.slug]
22-
return { meta, readme }
25+
const name = params.slug
26+
const meta = directivesMeta[name]
27+
const readmeData = (await getReadmeData(name)).default
28+
const { titleLead = '', body = '', baseTOC = {}, loadError = false } = readmeData
29+
return { meta, titleLead, body, baseTOC, loadError }
2330
},
2431
render(h) {
2532
const $referenceSection = h(Section, { class: ['bd-component-reference'] }, [
@@ -34,8 +41,10 @@ export default {
3441
{
3542
staticClass: 'bd-components',
3643
props: {
37-
readme: this.readme,
38-
meta: this.meta
44+
meta: this.meta,
45+
titleLead: this.titleLead,
46+
body: this.body,
47+
loadError: this.loadError
3948
}
4049
},
4150
[$referenceSection]

0 commit comments

Comments
 (0)