Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable prefetch for dynamic imports #18376

Open
tresko opened this issue Jan 20, 2023 · 31 comments
Open

Disable prefetch for dynamic imports #18376

tresko opened this issue Jan 20, 2023 · 31 comments

Comments

@tresko
Copy link
Contributor

tresko commented Jan 20, 2023

Environment

- Operating System: `MacOs`
- Node Version:     `v19.3.0`
- Nuxt Version:     `3.0.0`
- Nitro Version:    `1.0.0`
- Package Manager:  `yarn@1.22.19`
- Builder:          `vite`
- User Config:      `-`
- Runtime Modules:  `-`
- Build Modules:    `-`

Describe the issue

I am using dynamic import to import icons conditionally but I don't want to prefetch them.
This might stack up to many unused icons because it prefetches all icons from the ./icons folder.

When I want to load just Twitter icon, everything is imported.

<InlineIcon name="twitter" />

image001

Code

<template>
  <Icon />
</tempalte>

<script setup lang="ts">
const props =   defineProps<{name: string}>()

const Icon = computed(() => defineAsyncComponent(() => import(`../icons/${props.name}.svg?component`)));
</script>
@Baroshem
Copy link
Contributor

Have you maybe tried preloading these components? I think by default async components are prefetched by you should be able to manually oreload them

https://nuxt.com/docs/api/utils/preload-components

@SebastianBoergers
Copy link

Had a similar problem some months ago. With ALL Font-Awesome Icons including all premium styles etc. the build process never finished. It barely managed to (took 10+ minutes afaik instead of the usual 1~2) with just two sets active.

@manniL
Copy link
Member

manniL commented Feb 3, 2023

Another part of the issue as noted in #18723:

When dynamically importing a module (dayjs as an example) it get's added to the head of the page with rel="prefetch", even if not used right away.

Related: #14584

@manniL manniL changed the title Nuxt 3 - Is there any way to disable prefetch with dynamic import? Disable prefetch for dynamic imports Feb 3, 2023
@Pysdbi
Copy link

Pysdbi commented Feb 3, 2023

Why can't I control the file download type? LightHouse "First Contentful Paint" shows from 2.9 seconds due to <link rel="preload" ...>
FCP 1.5 seconds
preload components and files

@Zorii4
Copy link

Zorii4 commented Feb 3, 2023

I have the same problem.
First Contentful Paint: 1.8s but my project almost empty...
problem

@Pysdbi
Copy link

Pysdbi commented Feb 15, 2023

What do you mean by "workaround available"?

@danielroe
Copy link
Member

It is possible to remove dynamic import prefetching in the build:manifest hook.

nuxt.hook('build:manifest', (manifest) => {
  for (const key in manifest) {
    // or other logic
    manifest[key].dynamicImports = []
  }
})

@Pysdbi
Copy link

Pysdbi commented Feb 16, 2023

I zeroed manifest.dynamicImports, but it didn't solve problem with preload.

Copy link
Member

In that case, this is triggered directly by vite's preloading behaviour. If you can provide a reproduction, I can investigate further.

Note: some situations (but likely not the original reported issue here) might be somewhat ameliorated by #19008 which will be included in v3.2.1.

@madsleejensen
Copy link

I did a super hacky workaround because i couldnt find a better solution:

added the following nitro plugin at server/plugins/prefetch.js

import * as cheerio from 'cheerio';

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('render:html', (html, { event }) => {
    /**
     * @WORKAROUND: remove auto generated <link rel="prefetch" /> tags from the head
     * currently it automatically adds prefetch tags for all assets imported in the page
     */
    // https://github.com/nuxt/nuxt/issues/18376#issuecomment-1431318970
    // https://github.com/nuxt/nuxt/issues/18376

    html.head = html.head.map(head => {
      const $ = cheerio.load(head);
      $('link[rel=prefetch]').each(function() {
        $(this).remove();
      })

      return $.root().find('head').contents();
    })
  })
})

Looking forward to remove this workaround when a fix is found, the main problem i had was that all images loaded via import MyImage from '~/assets/test.png' would be prefetch messing up the LCP

@Pysdbi
Copy link

Pysdbi commented Feb 25, 2023

// file path: `./nuxt.config.js`
export default {
  // other params

  render: {
    bundleRenderer: {
      shouldPrefetch: () => false,
      shouldPreload: () => false,
    },
  },
}

This method does not work on nuxt 3.2.2

Atinux pushed a commit to nuxt/website-v2 that referenced this issue Mar 14, 2023
@konsavv
Copy link

konsavv commented Mar 17, 2023

@Pysdbi I have the version "nuxt": "^ 3.1.1" . I tried what you suggest and it doesn't work.

@scofield-ua
Copy link

Nothing from above doesn't really helps.

Setting dynamicImports to [] removes module preloading from the source file, but when you open it in the browser entry.js will add those modulepreload links again.

I was even trying to set it directly as vite extend config like this:

'vite:extend' ({ nuxt, config }) {
    config.build.modulePreload = { polyfill: false };
    config.build.resolveDependencies = () => [];    

    return config;
}

but result is the same.

vitejs/vite#9938 (comment)

@scofield-ua
Copy link

Looks like in my case, the problem was related to prefetch feature of NuxtLink, which is turned on by default and will prefetch css and js when link is in user's viewport.

So adding no-prefetch and this solved prefetching issues for me.

@Dreckr
Copy link

Dreckr commented Apr 19, 2023

In my case, the issue was that every image was being prefetched. All versions of an image used on img/picture srcset's were prefetched, and there was a weird behavior where Chrome was always prioritizing and waiting for the highest pixel density version. That obviously was slowing down my initial page load.

Inspired by @danielroe's workaround, I made my own that disables prefetch for image assets:

nuxt.hook('build:manifest', (manifest) => {
  const keysToRemove = []

  for (const key in manifest) {
    const file = manifest[key]

    if (file.assets) {
      file.assets = file.assets
        .filter(
          (asset: string) =>
            !asset.endsWith('.webp') &&
            !asset.endsWith('.jpg') &&
            !asset.endsWith('.png')
        )
    }
  }
})

The result was a 300ms faster initial page load and lot less images being transfered unnecessarily in my case, so I'm sharing this workaround here so that anybody can use it.

@lewebsimple
Copy link
Contributor

I'm getting the same kind of problems when auto-importing SVG icons from a directory using vite-svg-loader. The page load (in development mode at least) contains all the SVG files from the auto-imported directory.

This only occurs on 3.4.2 and forcing nuxt version 3.4.1 doesn't exhibit this behavior.

Reproduction here: https://stackblitz.com/edit/github-2upgzp

@AdrianGrochowski
Copy link

@Dreckr where should I put this code in my Nuxt application ?

@phaust
Copy link

phaust commented May 11, 2023

In my case, the issue was that every image was being prefetched. All versions of an image used on img/picture srcset's were prefetched, and there was a weird behavior where Chrome was always prioritizing and waiting for the highest pixel density version. That obviously was slowing down my initial page load.

Inspired by @danielroe's workaround, I made my own that disables prefetch for image assets:

nuxt.hook('build:manifest', (manifest) => {
  const keysToRemove = []

  for (const key in manifest) {
    const file = manifest[key]

    if (file.assets) {
      file.assets = file.assets
        .filter(
          (asset: string) =>
            !asset.endsWith('.webp') &&
            !asset.endsWith('.jpg') &&
            !asset.endsWith('.png')
        )
    }
  }
})

The result was a 300ms faster initial page load and lot less images being transfered unnecessarily in my case, so I'm sharing this workaround here so that anybody can use it.

Thank you so much @Dreckr!
I had similar issues with img/picture srcsets and your workaround fixed them.

@phaust
Copy link

phaust commented May 11, 2023

@Dreckr where should I put this code in my Nuxt application ?

I put the workaround in the nuxt.config.ts file.

export default defineNuxtConfig({
  …
  hooks: {
    'build:manifest': (manifest) => {
      const keysToRemove = []

      for (const key in manifest) {
        const file = manifest[key]

        if (file.assets) {
          file.assets = file.assets
            .filter(
              (asset: string) =>
                !asset.endsWith('.webp') &&
                !asset.endsWith('.jpg') &&
                !asset.endsWith('.png')
            )
        }
      }
    }
  },
  …
})

@max-arias
Copy link

Anyone have a workaround for the client? From what I can gather most of these workarounds only affect the server/TTFB. Unless Im wrong?

@yaquawa
Copy link

yaquawa commented Sep 6, 2023

any updates ?!

1 similar comment
@This-is-ellesar
Copy link

any updates ?!

@Red-Asuka
Copy link

How to completely disable prefetch? This has a significant impact on website performance, especially in mobile device scoring.

@akumanara
Copy link

I am also having this problem. it prefetches the swiper bundle from another page other than the page i am visiting and i get a bad rating on pagespeed

@JieJieeee
Copy link

What exactly can I do to remove preload&prefetch?I searched all over the internet and couldn't help it
image

@or2e
Copy link

or2e commented Nov 3, 2023

@JieJieeee
at the moment, there's a way

Stay tuned for further updates on this topic here

@brettsprads
Copy link

This is still not working, in 2024 there still isn't a Nuxt 3 way to stop preloading / prefetching.

@RomanSkrypnik
Copy link

RomanSkrypnik commented Mar 4, 2024

@danielroe Any updates?
It hits project performance

@jmdmacapagal
Copy link

jmdmacapagal commented Mar 15, 2024

any updates regarding prefetching of components?

@simkuns
Copy link

simkuns commented May 2, 2024

I did it like this:

export default defineNuxtConfig(() => {
  hooks: {
    'build:manifest'(manifest) {
      for (const key in manifest) {
        const file = manifest[key];

        if (file.prefetch) {
          file.prefetch = false;
        }

        // Prevents inclusion of <link rel="stylesheet" /> during SSR since styles are inlined anyway (checked with Postman)
        if (file.resourceType === 'script') {
          file.css = [];
        }
      }
    },
  },
});

and every component inside pages/layouts which is below the fold is wrapped in NuxtLazyHydrate and prefixed with Lazy

<template>
  <!-- components below the fold  -->
  <NuxtLazyHydrate when-visible>
    <LazyExampleComponent />
  </NuxtLazyHydrate>
</template>

this way I was able to improve Lighthouse score from 29 to 93.

@dsvgl
Copy link

dsvgl commented May 2, 2024

Thx @simkuns will test it out!
For reference, nuxt-lazy-hydrate is great: https://github.com/Baroshem/nuxt-lazy-hydrate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests