title: Vue js Prefetch components
body: <p>I recently learnt about lazy loading components and started using it. Now I am trying to prefetch the lazy loaded components as well as <code>vue-router</code> routes. But using the chrome devtools I found that lazy loaded chunks  are only loaded when we actually navigate to the lazy loaded route (in case of a vue-router route) or when the <code>v-if</code> evaluates to <code>true</code> and the component is rendered (in case of a lazy loaded component).</p>
  <p>I have also tried using the <code>webpackPrefetch: true</code> magic string in the router as well as component import statement but doing that does not seem to make any difference.</p>
  <p>Project structure:<br />
  Master-Detail layout</p>
  <p>router config:</p>
  <pre><code>import Vue from &quot;vue&quot;;
  import Router from &quot;vue-router&quot;;
  Vue.use(Router);
  
  var routes = [  
    {
      path: &quot;/DetailPage&quot;,
      component: () =&gt; import(/* webpackChunkName: &quot;Detail-chunk&quot; */ &quot;AppModules/views/MyModuleName/DetailPage.vue&quot;)
    },
    {
      path: &quot;/MasterPage&quot;,
      component: () =&gt; import(&quot;AppModules/views/MyModuleName/MasterPage.vue&quot;)
    }
  ]
  
  export const router = new Router({
    routes: routes,
    stringifyQuery(query) {
      // encrypt query string here
    }
  });
  
  export default router;
  </code></pre>
  <p>Master view:</p>
  <pre><code>&lt;template&gt; 
    &lt;div @click=&quot;navigate&quot;&gt;
      Some text
    &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
  export default {
    name: &quot;MasterPage&quot;,
    methods: {
      navigate() {
        this.$router.push({
          path: &quot;/DetailPage&quot;,
          query: {},
        });
      },
    },
  };
  &lt;/script&gt;
  </code></pre>
  <p>Details page:</p>
  <pre><code>&lt;template&gt;
    &lt;div&gt;    
      &lt;my-component v-if=&quot;showComponent&quot; /&gt;
      &lt;div @click=&quot;showComponent = true&quot;&gt;Show Component&lt;/div&gt;
    &lt;/div&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
  const MyComponent = () =&gt; import(/* webpackChunkName: &quot;MyComponent-chunk&quot; */ &quot;AppCore/components/AppElements/Helpers/MyComponent&quot;);
  export default {
    name: &quot;DetailPage&quot;,
    components: {
      MyComponent,
    },
    data() {
      return {
        showComponent: false
      }
    }
  };
  &lt;/script&gt;
  </code></pre>
  <p>vue.js.config file:</p>
  <pre><code>const path = require(&quot;path&quot;);
  
  const BundleAnalyzerPlugin = require(&quot;webpack-bundle-analyzer&quot;)
    .BundleAnalyzerPlugin;
  
  module.exports = {
    publicPath: &quot;some-url&quot;,
    outputDir: &quot;./some/path&quot;,
    chainWebpack: webapckConfig =&gt; {
      webapckConfig.plugin(&quot;html&quot;).tap(() =&gt; {
        return [
          {
            inject: true,
            filename: &quot;index.html&quot;,
            template: &quot;./public/index.html&quot;
          }
        ];
      });
    },
    productionSourceMap: true,
    configureWebpack: {
      plugins: [
        new BundleAnalyzerPlugin({
          analyzerMode: &quot;server&quot;,
          generateStatsFile: false,
          statsOptions: {
            excludeModules: &quot;node_modules&quot;
          }
        })
      ],
      output: {
        filename: &quot;some file name&quot;,
        libraryTarget: &quot;window&quot;
      },
      module: {
        rules: [
          {
            test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
            use: [
              {
                loader: &quot;url-loader&quot;,
                options: {
                  limit: 50000,
                  fallback: &quot;file-loader&quot;,
                  outputPath: &quot;/assets/fonts&quot;,
                  name: &quot;[name].[ext]?hash=[hash]&quot;
                }
              }
            ]
          }
        ]
      },
      resolve: {
        alias: {
          vue$: process.env.NODE_ENV == 'production' ? 'vue/dist/vue.min.js' : 'vue/dist/vue.js',
          AppCore: path.resolve(__dirname, &quot;..&quot;, &quot;..&quot;, &quot;AppCoreLite&quot;),
          AppModules: path.resolve(__dirname, &quot;..&quot;, &quot;..&quot;, &quot;AppModulesLite&quot;)
        }
      }
    }
  };
  </code></pre>
  <p>Both the async route and component do get split into separate chunks but these chunks are not prefetched.<br />
  When I navigate to the master view, I dont see <code>Detail-chunk.[hash].js</code> in the network tab. It gets requested only when the <code>navigate</code> method in the master page is executed (this the correct lazy load behaviour without prefetch).<br />
  Now when I am on the details page, <code>MyComponent-chunk.[hash].js</code> is only requested when the <code>showComponent</code> becomes <code>true</code> (on click of a button)<br />
  I've also read at a few places that <code>vue-cli</code> v3 does has prefetch functionality enabled by default and webpack magic string is not needed. I also tried that by removing the <code>webpackPrefetch</code> comment but it made no difference.</p>
  <p>I did <code>vue-cli-service inspect</code> and found that prefetch plugin is indeed present in the webpack config:</p>
  <pre><code> /* config.plugin('preload') */
      new PreloadPlugin(
        {
          rel: 'preload',
          include: 'initial',
          fileBlacklist: [
            /\.map$/,
            /hot-update\.js$/
          ]
        }
      ),
      /* config.plugin('prefetch') */
      new PreloadPlugin(
        {
          rel: 'prefetch',
          include: 'asyncChunks'
        }
      ),
  </code></pre>
  <p><em>UPDATE</em>: I tried removing the prefetch webpack plugin using <code>config.plugins.delete('prefetch');</code> and then using the webpack magic comment: <code>/* webpackPrefetch: true */</code> but it made no difference.</p>
  <p>How do I implement prefetch functionality?</p>