阿里云主机折上折
  • 微信号
Current Site:Index > Preloading and prefetching strategies

Preloading and prefetching strategies

Author:Chuan Chen 阅读数:29286人阅读 分类: Vue.js

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:

  1. Preloaded resources are marked with "High" priority.
  2. Prefetched resources are marked with "Lowest" priority.
  3. 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

上一篇:打包体积优化

下一篇:性能监测工具

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.