Skip to content

Commit a9c916b

Browse files
feat: Upgrade to Vue 3 (#44)
BREAKING CHANGE: Require Vue 3 and Vue Router 4
1 parent c62f9a0 commit a9c916b

File tree

12 files changed

+985
-3140
lines changed

12 files changed

+985
-3140
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
node_modules
22
dist
3+
cypress/videos
4+
cypress/screenshots

cypress/integration/spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
describe('My First Test', () => {
22
it('Does not do much!', () => {
3-
cy.visit('http://localhost:4000')
3+
cy.visit('http://localhost:3000')
44
cy.wait(1000)
55
cy.window().then(({ pages }) => {
66
expect([...pages]).to.deep.equal([1, 2, 3])

cypress/videos/prefetch_spec.js.mp4

-55.2 KB
Binary file not shown.

example/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Document</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
<script type="module" src="./index.jsx"></script>
12+
</body>
13+
</html>

example/index.js

Lines changed: 0 additions & 105 deletions
This file was deleted.

example/index.jsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { createApp, h } from 'vue'
2+
import { createRouter, createWebHashHistory, RouterView } from 'vue-router'
3+
import RoutePrefetch from '../src'
4+
import Nav from './nav.vue'
5+
6+
const app = createApp({
7+
setup() {
8+
return () => h(RouterView)
9+
}
10+
})
11+
12+
const router = createRouter({
13+
history: createWebHashHistory(),
14+
routes: [
15+
{
16+
path: '/',
17+
component: {
18+
render() {
19+
return (
20+
<div>
21+
<h1>hi</h1>
22+
<Nav />
23+
</div>
24+
)
25+
}
26+
}
27+
},
28+
{
29+
path: '/async-page',
30+
meta: {
31+
prefetch(route) {
32+
console.log(route)
33+
}
34+
},
35+
component: () => import('./async-page.vue')
36+
}
37+
]
38+
})
39+
40+
app.use(router)
41+
app.use(RoutePrefetch)
42+
43+
window.pages = new Set()
44+
45+
const createPage = id => async () => {
46+
console.log(`fetching page ${id}`)
47+
window.pages.add(id)
48+
return {
49+
render() {
50+
return (
51+
<div>
52+
<h1>page {id}</h1>
53+
<Nav />
54+
</div>
55+
)
56+
}
57+
}
58+
}
59+
60+
for (let i = 0; i < 6; i++) {
61+
router.addRoute({
62+
path: `/page/${i + 1}`,
63+
component: createPage(i + 1)
64+
})
65+
}
66+
67+
app.mount('#app')

example/nav.vue

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<template>
2+
<div>
3+
<ul>
4+
<li>
5+
<router-link to="/page/1">page 1</router-link>
6+
</li>
7+
<li>
8+
<router-link to="/page/2">page 2</router-link>
9+
</li>
10+
<li>
11+
<router-link to="/page/3">page 3</router-link>
12+
</li>
13+
</ul>
14+
<ul style="margin-top: 110vh;" id="bottom">
15+
<li>
16+
<router-link to="/page/4" :prefetchFiles="['/foo']">
17+
page 4
18+
</router-link>
19+
</li>
20+
<li>
21+
<router-link to="/page/5">page 5</router-link>
22+
</li>
23+
<li>
24+
<router-link to="/async-page">async-page</router-link>
25+
</li>
26+
<li>
27+
<router-link to="/page/6">page 6</router-link>
28+
</li>
29+
<li>
30+
<router-link to="/page/1">page 1</router-link>
31+
</li>
32+
</ul>
33+
</div>
34+
</template>

example/vite.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import vue from '@vitejs/plugin-vue'
2+
import { defineConfig } from 'vite'
3+
4+
export default defineConfig({
5+
plugins: [vue()],
6+
esbuild: {
7+
jsxFactory: 'h'
8+
}
9+
})

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"lint": "xo",
1515
"build": "bili --format esm,cjs,esm-min --minimal",
1616
"prepublishOnly": "npm run build",
17-
"example": "poi example/index.js --serve --jsx vue",
17+
"example": "vite example",
1818
"commit": "git-cz",
1919
"cy:run": "cypress run",
2020
"cy:open": "cypress open",
@@ -27,10 +27,12 @@
2727
"author": "egoist<[email protected]>",
2828
"license": "MIT",
2929
"devDependencies": {
30+
"@vitejs/plugin-vue": "^1.4.0",
31+
"@vue/compiler-sfc": "^3.1.5",
3032
"babel-eslint": "^10.0.1",
3133
"bili": "^4.0.9",
3234
"commitizen": "^3.0.5",
33-
"cypress": "^3.3.2",
35+
"cypress": "^8.2.0",
3436
"cz-conventional-changelog": "^2.1.0",
3537
"eslint-config-prettier": "^3.3.0",
3638
"eslint-config-rem": "^4.0.0",
@@ -40,12 +42,11 @@
4042
"husky": "^1.0.0-rc.13",
4143
"lint-staged": "^7.2.0",
4244
"npm-run-all": "^4.1.5",
43-
"poi": "^12.4.6",
4445
"prettier": "^1.15.2",
4546
"semantic-release": "^17.3.0",
46-
"vue": "^2.5.22",
47-
"vue-router": "^3.0.2",
48-
"vue-template-compiler": "^2.5.22",
47+
"vite": "^2.4.4",
48+
"vue": "^3.1.5",
49+
"vue-router": "^4.0.10",
4950
"xo": "^0.23.0"
5051
},
5152
"xo": {

src/index.js

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import prefetch from './prefetch'
22
import { canPrefetch, supportIntersectionObserver, inBrowser } from './utils'
33

44
function installRouterPrefetch(
5-
Vue,
5+
/** @type {import('vue').App} */
6+
app,
67
{ componentName = 'RouterLink', prefetch: enablePrefetch = true } = {}
78
) {
89
const observer =
@@ -29,18 +30,18 @@ function installRouterPrefetch(
2930
}, timeout)
3031
}
3132

32-
const RouterLink = Vue.component('RouterLink') || Vue.component('router-link')
33+
const RouterLink = app.component('RouterLink') || app.component('router-link')
3334

3435
if (process.env.NODE_ENV === 'development' && !RouterLink) {
3536
console.error(
36-
`[vue-router-prefetch] You need to call Vue.use(VueRouter) before this plugin!`
37+
`[vue-router-prefetch] You need to call app.use(VueRouter) before this plugin!`
3738
)
3839
}
3940

4041
const Link = {
4142
name: componentName,
42-
extends: RouterLink,
4343
props: {
44+
...RouterLink.props,
4445
prefetch: {
4546
type: Boolean,
4647
default: enablePrefetch
@@ -53,12 +54,15 @@ function installRouterPrefetch(
5354
default: 2000
5455
}
5556
},
57+
setup(props, context) {
58+
return RouterLink.setup(props, context)
59+
},
5660
mounted() {
5761
if (this.prefetch && observer && canPrefetch) {
5862
requestIdleCallback(this.observe, { timeout: this.timeout })
5963
}
6064
},
61-
beforeDestroy() {
65+
beforeUnmount() {
6266
this.unobserve()
6367
},
6468
methods: {
@@ -72,21 +76,28 @@ function installRouterPrefetch(
7276
observer.unobserve(this.$el)
7377
}
7478
},
75-
getComponents() {
76-
return this.$router.getMatchedComponents(this.to).filter(Component => {
77-
return Component.cid === undefined && typeof Component === 'function'
78-
})
79+
getRouteComponents(route) {
80+
return route.matched
81+
.map(record => {
82+
return Object.values(record.components)
83+
})
84+
.flat()
85+
.filter(Component => {
86+
return (
87+
Component.cid === undefined && typeof Component === 'function'
88+
)
89+
})
7990
},
8091
linkPrefetch() {
81-
const { route } = this.$router.resolve(this.to)
92+
const route = this.$router.resolve(this.to)
8293

8394
if (route.meta.__prefetched) return
8495

8596
route.meta.__prefetched = true
8697

8798
if (route.meta.prefetch !== false) {
8899
// Prefetch route component
89-
const components = this.getComponents()
100+
const components = this.getRouteComponents(route)
90101
for (const Component of components) {
91102
this.$emit('prefetch', this.to)
92103
Component() // eslint-disable-line new-cap
@@ -113,12 +124,13 @@ function installRouterPrefetch(
113124
}
114125
}
115126

116-
Vue.component(Link.name, Link)
127+
// `app.component(Link.name, Link)` will emit a warning
128+
app._context.components[Link.name] = Link
117129
}
118130

119131
export {
120132
prefetch,
121-
// Export as `install` to make `Vue.use(require('vue-router-prefetch'))` work
133+
// Export as `install` to make `app.use(require('vue-router-prefetch'))` work
122134
installRouterPrefetch as install
123135
}
124136

0 commit comments

Comments
 (0)