How to fix vue dynamic async components not found in production?

Viewed 1553

I'm dynamically importing components in nuxt.js using their path and filename. It works well in development, and when you first load the website, but in production when you navigate to a new page, the components don't load — error 404.

Edit: the components are visible, but are not reactive. So, they are rendering server side, but then not working on the client side.

I suspect this is an issue with webpack and i've tried using magic comments to keep the filenames but that hasn't changed anything.

I have a website with a custom CMS so I can use any component directly in my posts. e.g if I think the signup compononent would be better halfway down the page, then I can place it there.

I'm using the latest version of node.js, express, and nuxt.js.

The below code works great on initial load, but not when the route changes.

<template>
  <component :is="comp" />
</template>

<script>

export default {
  name: 'DynamicComponent',
  props: {
    componentName: {
      type: String,
      default: ''
    }
  },
  computed: {
    comp() {
      return () => import(`@/components/dynamic/${this.componentName}`)
    }
  }
}

</script>

My understanding of webpack is it will code split all the files in @/components/dynamic folder. It does do this, and it gives them all hashed filenames.

Any help would be much appreciated.

2 Answers

I think your problem is the way you are using reactive data within the computed method.

If you are using reactive data in a computed method, Vue tracks that relationship. So that when the reactive data changes, the computed value gets computed again.

In your case, the reactive data is not being used directly within computed method but in an anonymous function inside of it. So Vue cannot create the relationship.

Try rewriting it as

computed: {
    comp() {
      const componentName = this.componentName;
      return () => import(`@/components/dynamic/${componentName}`);
    }
  }

I think the issue is with publicPath configuration option in webpack. Your component may be referring wrong directory in production. Modify the publicPath option in vue.config.js during production build and it should work

Related