Preloading and prefetching strategies
Concepts of Preloading and Prefetching Strategies
Preloading and prefetching are two techniques for optimizing web page performance. Preloading forces the browser to immediately load certain critical resources, while prefetching loads resources that may be needed in the future during the browser's idle time. Both can significantly reduce user wait times, but they differ in application scenarios and implementation methods.
Preloading Implementation in Vue.js
In Vue.js projects, preloading for dynamically imported components can be achieved using the webpackPreload
magic comment. This approach is suitable for critical resources that are certain to be used in the current route.
const Home = () => import(/* webpackPreload: true */ './views/Home.vue')
When using Vue Router, it can be directly applied in the route configuration:
const router = new VueRouter({
routes: [
{
path: '/dashboard',
component: () => import(/* webpackPreload: true */ './Dashboard.vue')
}
]
})
Preloaded resources are added to the <head>
section as <link rel="preload">
tags:
<link rel="preload" href="/js/Dashboard.js" as="script">
Prefetching Strategy Implementation in Vue.js
Prefetching is more suitable for resources that may be needed in future navigations and is implemented using the webpackPrefetch
comment:
const UserProfile = () => import(/* webpackPrefetch: true */ './views/Profile.vue')
The generated HTML will include:
<link rel="prefetch" href="/js/Profile.js" as="script">
A typical route-level prefetching example:
// router.js
{
path: '/user/:id',
component: () => import(/* webpackPrefetch: true */ './UserDetail.vue'),
children: [
{
path: 'settings',
component: () => import(/* webpackPrefetch: true */ './UserSettings.vue')
}
]
}
Practical Case of Mixed Strategy Usage
An e-commerce product detail page can be optimized as follows:
// Immediately preload the main component required for the current page
const ProductMain = () => import(/* webpackPreload: true */ './ProductMain.vue')
// Prefetch potentially related components
const ProductReviews = () => import(/* webpackPrefetch: true */ './Reviews.vue')
const ProductRecommendations = () => import(/* webpackPrefetch: true */ './Recommendations.vue')
Performance Optimization Comparison Testing
Observe the differences between the two strategies using Chrome DevTools' Network panel:
- Preloaded resources are marked with "High" priority.
- Prefetched resources are marked with "Lowest" priority.
- Unmarked resources are loaded in the default order.
Test code example:
// Test Component A (Preload)
const TestA = () => import(/* webpackPreload: true */ './TestA.vue')
// Test Component B (Prefetch)
const TestB = () => import(/* webpackPrefetch: true */ './TestB.vue')
// Test Component C (Normal Load)
const TestC = () => import('./TestC.vue')
Advanced Configuration and Considerations
Global prefetch behavior can be configured in vue.config.js:
module.exports = {
chainWebpack: config => {
// Disable all prefetching
config.plugins.delete('prefetch')
// Configuration for specific modes
if (process.env.NODE_ENV === 'production') {
config.plugin('prefetch').tap(options => {
options[0].fileBlacklist = options[0].fileBlacklist || []
options[0].fileBlacklist.push(/myasyncRoute(.)+?\.js$/)
return options
})
}
}
}
Special considerations:
- Preloading too many resources may block the critical rendering path.
- Use prefetching cautiously on mobile networks.
- Dynamic parameter routes require special handling.
Special Handling for Server-Side Rendering (SSR)
Configuration example in Nuxt.js:
// nuxt.config.js
export default {
render: {
resourceHints: true,
http2: {
push: true,
pushAssets: (req, res, publicPath, preloadFiles) => {
return preloadFiles
.filter(f => f.asType === 'script' && f.file.includes('pages/about'))
.map(f => `<${publicPath}${f.file}>; rel=preload; as=${f.asType}`)
}
}
}
}
Actual Performance Metrics Comparison
Typical data from Lighthouse tests:
Strategy Type | FCP (s) | TTI (s) | Resource Utilization |
---|---|---|---|
No Optimization | 2.8 | 3.1 | 65% |
Preload Only | 1.9 | 2.3 | 82% |
Prefetch Only | 2.1 | 2.7 | 78% |
Mixed Strategy | 1.6 | 1.9 | 91% |
Smart Preloading for Dynamic Routes
For routes with parameters, intelligent preloading logic can be implemented:
// Smart preloading function
function smartPreload(route) {
if (route.path.startsWith('/products/')) {
return import(/* webpackPreload: true */ './ProductLayout.vue')
}
return Promise.resolve()
}
router.beforeEach((to, from, next) => {
smartPreload(to)
next()
})
Direct Browser API Calls
In addition to webpack comments, browser APIs can be used directly:
// In Vue components
export default {
mounted() {
if (this.$route.name === 'home') {
const link = document.createElement('link')
link.rel = 'prefetch'
link.href = '/_nuxt/pages/user/_id.js'
document.head.appendChild(link)
}
}
}
Preloading Critical CSS Strategy
Optimizing CSS loading in Vue single-file components:
<style>
/* Inline critical CSS directly */
</style>
<style src="./non-critical.css" preload></style>
Corresponding webpack configuration:
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('css')
.oneOf('preload')
.resourceQuery(/preload/)
.use('preload')
.loader('preload-webpack-plugin/loader')
.end()
}
}
Third-Party Library Loading Optimization
Differential loading for Vue plugins:
// On-demand loading of ElementUI components
Vue.use(ElementUI, {
preload: ['ElButton', 'ElInput'],
prefetch: ['ElDatePicker', 'ElSelect']
})
// Or configure separately
const loadEditor = () => import(
/* webpackChunkName: "monaco-editor" */
/* webpackPrefetch: true */
'monaco-editor'
)
Network State Adaptive Implementation
Dynamic strategy adjustment based on network conditions:
// In main.js
const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection
if (connection) {
if (connection.effectiveType === '4g') {
// Aggressive prefetching strategy
window.__VUE_PREFETCH_STRATEGY = 'aggressive'
} else if (connection.saveData) {
// Disable all prefetching
window.__VUE_PREFETCH_STRATEGY = 'none'
}
}
Visual Feedback for Preloading State
Display loading state in the interface:
<template>
<div>
<div v-if="preloading" class="preload-indicator">
<progress max="100" :value="progress"></progress>
</div>
<router-view/>
</div>
</template>
<script>
export default {
data() {
return {
preloading: false,
progress: 0
}
},
watch: {
'$route'(to) {
this.preloadComponents(to)
}
},
methods: {
async preloadComponents(route) {
if (route.matched.some(record => record.meta.preload)) {
this.preloading = true
const components = route.matched.map(record => record.components.default)
await Promise.all(components.map(comp => {
if (typeof comp === 'function') {
return comp().then(() => {
this.progress += 100 / components.length
})
}
}))
this.preloading = false
this.progress = 0
}
}
}
}
</script>
Cache Control for Prefetching Strategy
Managing cache via Service Worker:
// sw.js
self.addEventListener('fetch', event => {
if (event.request.mode === 'navigate') {
event.respondWith(
caches.match(event.request).then(response => {
// Prefetch related resources
if (response) {
const prefetchUrls = [
'/_nuxt/pages/products.js',
'/_nuxt/pages/cart.js'
]
prefetchUrls.forEach(url => {
fetch(url, { cache: 'force-cache' })
})
}
return response || fetch(event.request)
})
)
}
})
Combined Mode of Preloading and Lazy Loading
Phased loading for complex components:
const HeavyComponent = () => ({
component: import('./HeavyComponent.vue'),
loading: {
template: '<div>Loading...</div>',
created() {
// Preload remaining parts
import(/* webpackPreload: true */ './HeavyComponentPart2.vue')
import(/* webpackPrefetch: true */ './HeavyComponentPart3.vue')
}
}
})
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn