简体   繁体   中英

Webpack Dependency Management and Vue.js async component loading

I am trying to achieve Vue.js dynamic async component registration. This video gave me code that works perfectly fine, but it loads all modules even if they are not used.

import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
// Require in a base component context
const requireComponent = require.context(
  '../components/base', false, /base-[\w-]+\.vue$/,
)
requireComponent.keys().forEach(fileName => {
  // Get component config
  const componentConfig = requireComponent(fileName)
  // Get PascalCase name of component
  const componentName = upperFirst(
    camelCase(fileName.replace(/^\.\//,
      '').replace(/\.\w+$/,
      '')),
  )
  // Register component globally
  Vue.component(componentName, componentConfig.default || componentConfig)
})

What I tried to achieve was to create async components instead. Like so

import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'
// Require in a base component context
const requireComponent = require.context(
  '../components/base', false, /base-[\w-]+\.vue$/,
)
requireComponent.keys().forEach(fileName => {
  const componentPath = fileName.replace('./', '../components/base/');
  // Get PascalCase name of component
  const componentName = upperFirst(
    camelCase(fileName.replace(/^\.\//,
      '').replace(/\.\w+$/,
      '')),
  )
  // Register component globally
  Vue.component(componentName, () => import(componentPath))
})

If the case of the code above vue throws an error

vue.esm.js:591 [Vue warn]: Failed to resolve async component: function () {
    return __webpack_require__("./lib lazy recursive")(componentPath);
  }
Reason: Error: Cannot find module '../components/base/base-button.vue'

If I manually write down Vue.component('BaseButton', () => import('../components/base/base-button.vue')) it works without problem but when I try to do that dynamically it fails. Is it possible to do such async component registration if so how?

This doesn't work either:

const button = '../components/base/base-button.vue'
Vue.component('BaseButton', () => import(button))

only if I literally right the string into import function.

import cannot be used when the module path is fully dynamic. See the docs :

Fully dynamic statements, such as import(foo) , will fail because webpack requires at least some file location information. This is because foo could potentially be any path to any file in your system or project. The import() must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files.

You didn't specify the mode argument for require.context which defaults to "sync"; this means all modules matched will be loaded straight away. You want to use "lazy" which generates a lazy-loadable chunk for each module.

Untested, but I imagine it'll be something like this:

const context = require.context('../components/base', false, /base-[\w-]+\.vue$/, 'lazy');

context.keys().forEach(fileName => {
  const componentPath = fileName.replace('./', '../components/base/');

  // Get PascalCase name of component
  const componentName = upperFirst(
    camelCase(fileName.replace(/^\.\//,
      '').replace(/\.\w+$/,
      '')),
  );

  // Register component globally
  Vue.component(componentName, () => context(fileName));
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM