🌐 Vue Import Loader
Automate component registration concerns and focus on building component logic!
Credits to the @nuxt/components for the idea ❤️
⭐️ Features
- 🌳 Tree-shaking Only imports unregistered components detected in the template
- ❤️ Chunking friendly Locally registers components for optimal code-splitting
- ⚡️ Async components Supports the full async component API
- 💠 Dynamic components Supports
<component is="dynamic-comp">
* - 🔥 Functional components Supports components in functional components
* The is
attribute must contain the possible values inline
🚀 Install
npm i vue-import-loader
🚦 Quick Setup
In your Webpack config, insert vue-import-loader
before vue-loader
:
Before
test: /\.vue$/ loader: 'vue-loader'
After ✨
test: /\.vue$/ use: loader: 'vue-import-loader' options: // Similar to Vue's "components" hash components: ComponentTag: 'component/path/component-tag.vue' ... 'vue-loader'
👨🏫 Examples
Dynamically resolve components to a directory
Use a resolver function to dynamically resolve components
test: /\.vue$/ use: loader: 'vue-import-loader' options: { if return `@/components/`; } 'vue-loader'
Asynchronously load components with `components` hash
Map the component to an object to make it asynchronous. Refer to the Options section for the object schema.
test: /\.vue$/ use: loader: 'vue-import-loader' options: components: SyncComp: '/components/sync-comp.vue' // Mapping to an object makes it asynchronous AsyncComp: component: '/components/async-comp.vue' // Optional configs loading: '/components/loading.vue' error: '/components/error.vue' magicComments: 'webpackChunkName: "async-comps"' 'vue-loader'
Asynchronously load components prefixed with `async-`
Return an object to make it asynchronous. Refer to the Options section for the object schema.
This demo shows how prefixing your components with async-
in the template can make them asynchronously loaded.
test: /\.vue$/ use: loader: 'vue-import-loader' options: { if kebab return component: `/components/.vue` // Optional configs loading: '/components/loading.vue' error: '/components/error.vue' magicComments: 'webpackChunkName: "async-comps"' ; return `/components/.vue`; } 'vue-loader'
⚙️ Options
-
components
Object|Function
Object
Similar to Vue'scomponents
hash. Key is the component tag in kebab-case or PascalCase.- Value can be:
String
: Component path for synchronous loading (supports aliases)Object
: Component data for asynchronous loading meeting the following schema:
- Value can be:
// Component path (Required)component: '...'// Loading component pathloading: '...'// Error component patherror: '...'// Delay in ms before Loading component is displayeddelay: 200// Timeout in ms before Error component is displayedtimeout: Infinity// Magic comments to configure the dynamic import:// https://webpack.js.org/api/module-methods/#magic-commentsmagicComponents:'webpackChunkName: "my-chunk-name"'Function
({ kebab, pascal }, fromComponent)
- Use a function to dynamically resolve component tags to component paths. Supports outputting a string for synchronous, and an object for asynchronous imports as defined above. For example, this function resolves components to the "components" directory:
{const componentPath = `../components/.vue`;if fsreturn `@/components/`;}
-
functional
(Experimental)Boolean
(Default:false
)- Whether to resolve components in functional components. Functional components are known to not support the
components
hash but can be hacked around by registering the components to the parent instead. Since this feature mutates the parent'scomponent
hash, it is disabled by default.
- Whether to resolve components in functional components. Functional components are known to not support the
💁♂️ FAQ
global registration?
How's this different from Vue's-
Global registration
- Bundles-in registered components regardless of whether they're actually used
- Registers components to the Vue runtime, making them available to all-components
- Could lead to component name collision in large code-bases
-
Vue Import loader
- Only bundles-in components that it detects in the app's Vue component templates
- Components are registered locally per-component for optimal code-splitting
- Nuanced control over which files get what components via resolution function
Nuxt.js Components?
How's this different from-
Nuxt.js Components
- Designed specifically for Nuxt.js
- Automatically resolves components in the "components" directory
- Supports async components but not the full API (eg.
loading
,error
,delay
,timeout
)
-
Vue Import loader
- Supports any Webpack build
- Resolves components using a user-configured component-map or a resolution function
- Has built-in static analysis to detect registered components
- Supports the full async component API
- Supports dynamic components if possible values are inline
- eg.
<component :is="condition ? 'comp-a' : 'comp-b'">
- eg.
- Supports functional components
Why wouldn't I want to use this?
The costs of implicitly registering components locally is close to registering components globally.
-
The benefit this has over global registration is that it doesn't import components blindly at the top-level of your App, but instead, imports them intelligently at each detected usage. Unused components will not be bundled-in.
-
Maintainability Your components might become harder to maintain because of the lack of explicitly declared dependencies.
- Automation magic It's better to have code you understand and can control than to leave it to magic.
- Debugging If there's a bug in your resolver, it might not be an obvious place to look or troubleshoot.
-
Build-tool coupling Module-level concerns are introduced into the build configuration; perhaps comparable to creating aliases. Doing this couples the app to the build via config and makes it harder to migrate to a different environment (new tools, upgrades, etc).