# How Luban H5 Plugin Registration and Loading Works: Complete Technical Guide

> Discover how Luban H5's plugin registration and loading system works with this technical guide. Understand component registration and global implementation.

- Repository: [小小鲁班/luban-h5](https://github.com/ly525/luban-h5)
- Tags: internals
- Published: 2026-03-06

---

**Luban H5 uses a centralized registry in [`src/plugins/index.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/index.js) that exports a `pluginsList` array of descriptor objects, which are globally registered as Vue components via a mixin both in the editor ([`src/main.js`](https://github.com/ly525/luban-h5/blob/main/src/main.js)) and preview engine ([`src/engine-entry.js`](https://github.com/ly525/luban-h5/blob/main/src/engine-entry.js)).**

The ly525/luban-h5 repository implements a modular frontend architecture where every visual element—from buttons to charts—is treated as a plugin. Understanding the Luban H5 plugin registration system is essential for extending the editor with custom components or debugging why elements appear in the design interface but fail to render in previews.

## The Central Plugin Registry ([`src/plugins/index.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/index.js))

At the heart of the system lies [`src/plugins/index.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/index.js), which serves as the **single source of truth** for all available components. This file imports every visual component (e.g., `lbp-button`, `lbp-video`, `lbp-line-chart`) and wraps each in a **descriptor object** containing metadata and the component reference.

The exported `pluginsList` constant is an array of these descriptors:

```javascript
// src/plugins/index.js
export const pluginsList = [
  {
    i18nTitle: { 'en-US': 'Button', 'zh-CN': '普通按钮' },
    title: '普通按钮',
    icon: 'hand-pointer-o',
    component: LbpButton,
    visible: true,
    name: LbpButton.name,
  },
  // …additional plugin entries
]

```

Each descriptor specifies:
- **`name`**: The component name used for global registration
- **`component`**: The imported Vue component object
- **`visible`**: Boolean controlling visibility in the shortcut panel
- **`i18nTitle`** and **`title`**: Localization support and display labels
- **`icon`**: Font Awesome icon class for the UI

## Global Vue Component Registration via Mixin

Rather than importing components locally in every view, Luban H5 registers plugins globally using a **Vue mixin** exported from the same registry file. The mixin executes during the `created` lifecycle hook and iterates over `pluginsList` to register each component with `Vue.component()`.

```javascript
// src/plugins/index.js (mixin implementation)
created() {
  this.mixinPlugins2Editor()
},
methods: {
  mixinPlugins2Editor() {
    pluginsList.forEach(p => Vue.component(p.name, p.component))
  }
}

```

This approach guarantees that any plugin defined in the central registry becomes immediately available as a global element throughout the application without manual import statements.

## Dual Bootstrap: Editor and Preview Engine

The plugin system initializes in two distinct entry points to support both the design interface and the runtime preview.

**Editor bootstrap** occurs in [`src/main.js`](https://github.com/ly525/luban-h5/blob/main/src/main.js), which simply imports the plugin file to trigger the mixin's registration logic:

```javascript
// src/main.js
import './plugins/index'

```

**Engine-side loading** happens in [`src/engine-entry.js`](https://github.com/ly525/luban-h5/blob/main/src/engine-entry.js), where the preview engine explicitly registers plugins inside its `install` function. This ensures components render correctly when users preview their H5 pages:

```javascript
// src/engine-entry.js
const install = function (Vue) {
  Vue.component(Engine.name, Engine)
  pluginsList.forEach(p => Vue.component(p.name, p.component))
}

```

This dual registration strategy ensures **parity** between the editor canvas and the final output—what you see in the designer is exactly what renders in the preview.

## Utility Plugins and Prototype Extensions

Before component registration completes, Luban H5 loads two utility plugins that provide foundational functionality:

**UI Plugin** ([`src/plugins/UI.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/UI.js)) installs Ant Design Vue and Font Awesome globally:

```javascript
// src/plugins/UI.js
import Vue from 'vue'
import Antd from 'ant-design-vue'
import 'ant-design-vue/dist/antd.css'
import 'font-awesome/css/font-awesome.min.css'

Vue.use(Antd)

```

**Prototype Plugin** ([`src/plugins/Prototype.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/Prototype.js)) attaches a `$lubanUtils` object to every Vue instance, currently providing an Axios-based request helper:

```javascript
// src/plugins/Prototype.js
import Vue from 'vue'
import axios from 'axios'

Vue.prototype.$lubanUtils = { request: axios }

```

These utilities load before visual components, ensuring dependencies like UI libraries and HTTP clients are available during component initialization.

## Shortcut Panel Integration

The left sidebar's shortcut panel consumes `pluginsList` to generate draggable component buttons. Located at [`src/components/core/editor/left-panel/shortcuts-panel/index.js`](https://github.com/ly525/luban-h5/blob/main/src/components/core/editor/left-panel/shortcuts-panel/index.js), this component filters `pluginsList` by the `visible` property and maps entries to interactive buttons:

```javascript
// shortcuts-panel/index.js (render logic)
[].concat(this.pluginsList, this.npmPackages)
  .filter(p => p.visible)
  .map(p => (
    <ShortcutButton
      clickFn={this.clone.bind(this, p)}
      title={p.i18nTitle[this.currentLang] || p.title}
      faIcon={p.icon}
    />
  ))

```

When users click a shortcut, the descriptor object passes to the editor's element manager, which instantiates a new page element using the plugin's metadata and component reference.

## Adding a Custom Plugin

To extend the editor with a custom component, create the Vue single-file component and add its descriptor to `pluginsList`:

**Step 1:** Create the component file.

```javascript
// src/plugins/custom/MyCustomPlugin.vue
<template>
  <div class="my-plugin">Hello, custom!</div>
</template>

<script>
export default {
  name: 'MyCustomPlugin'
}
</script>

```

**Step 2:** Import and register the descriptor.

```javascript
// src/plugins/index.js
import MyCustomPlugin from './custom/MyCustomPlugin'

export const pluginsList = [
  // …existing entries
  {
    i18nTitle: { 'en-US': 'My Custom', 'zh-CN': '自定义插件' },
    title: 'My Custom',
    icon: 'puzzle-piece',
    component: MyCustomPlugin,
    visible: true,
    name: MyCustomPlugin.name,
  },
]

```

After saving, the mixin automatically registers `MyCustomPlugin` globally. The component instantly appears in the shortcut panel and renders correctly in the preview engine without additional configuration.

## Summary

- **[`src/plugins/index.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/index.js)** maintains the central `pluginsList` registry containing descriptors for all visual components.
- A **Vue mixin** iterates over `pluginsList` during the `created` hook, calling `Vue.component()` to register each plugin globally.
- Both **[`src/main.js`](https://github.com/ly525/luban-h5/blob/main/src/main.js)** (editor) and **[`src/engine-entry.js`](https://github.com/ly525/luban-h5/blob/main/src/engine-entry.js)** (preview) import the registry to ensure components work in design and runtime contexts.
- **Utility plugins** ([`UI.js`](https://github.com/ly525/luban-h5/blob/main/UI.js) and [`Prototype.js`](https://github.com/ly525/luban-h5/blob/main/Prototype.js)) preload essential libraries and helpers before component registration.
- The **shortcut panel** dynamically generates UI buttons by filtering `pluginsList` for entries with `visible: true`.

## Frequently Asked Questions

### Where are plugins registered in Luban H5?

Plugins are registered in [`src/plugins/index.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/index.js) through the `mixinPlugins2Editor` method, which calls `Vue.component(p.name, p.component)` for every entry in the exported `pluginsList` array. This registration occurs during the Vue instance's `created` lifecycle hook.

### How do I add a custom component to the Luban H5 editor?

Create your Vue component, import it into [`src/plugins/index.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/index.js), and append a descriptor object to `pluginsList` containing the `name`, `component`, `title`, `icon`, and `visible` properties. The system automatically registers it globally and displays it in the left shortcut panel if `visible` is set to `true`.

### Why does the preview engine need separate plugin registration?

The preview engine ([`src/engine-entry.js`](https://github.com/ly525/luban-h5/blob/main/src/engine-entry.js)) operates as a distinct Vue application from the editor. It must independently register plugins via its `install` function to ensure that components render correctly when users preview their H5 pages outside the editing interface.

### What is the `$lubanUtils` object used for?

`$lubanUtils` is a prototype extension defined in [`src/plugins/Prototype.js`](https://github.com/ly525/luban-h5/blob/main/src/plugins/Prototype.js) that attaches shared utilities to every Vue instance. Currently, it provides a `request` property wrapping Axios for HTTP operations, making API calls accessible via `this.$lubanUtils.request` in any component.