Javascript

Vue.js

Please refer to the core Vue developer documentation first.

Plugins that wish to use custom Vue components must implement their own webpack config to build the components and add them to the window.Vue.components object.

Sample webpack config (derived from the config used in GLPI itself for Vue):

const webpack = require('webpack');
const path = require('path');
const VueLoaderPlugin = require('vue-loader').VueLoaderPlugin;

const config = {
    entry: {
        'vue': './js/src/vue/app.js',
    },
    externals: {
        // prevent duplicate import of Vue library (already done in ../../public/build/vue/app.js)
        vue: 'window _vue',
    },
    output: {
        filename: 'app.js',
        chunkFilename: "[name].js",
        chunkFormat: 'module',
        path: path.resolve(__dirname, 'public/build/vue'),
        publicPath: '/public/build/vue/',
        asyncChunks: true,
        clean: true,
    },
    module: {
        rules: [
            {
                // Vue SFC
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                // Build styles
                test: /\.css$/,
                use: ['style-loader', 'css-loader'],
            },
        ]
    },
    plugins: [
        new VueLoaderPlugin(), // Vue SFC support
        new webpack.ProvidePlugin(
            {
                process: 'process/browser'
            }
        ),
        new webpack.DefinePlugin({
            __VUE_OPTIONS_API__: false, // We will only use composition API
            __VUE_PROD_DEVTOOLS__: false,
        }),
    ],
    resolve: {
        fallback: {
            'process/browser': require.resolve('process/browser.js')
        },
    },
    mode: 'none', // Force 'none' mode, as optimizations will be done on release process
    devtool: 'source-map', // Add sourcemap to files
    stats: {
        // Limit verbosity to only usefull information
        all: false,
        errors: true,
        errorDetails: true,
        warnings: true,

        entrypoints: true,
        timings: true,
    },
    target: "es2020"
};

module.exports = config

Note the use of the externals option. This will prevent webpack from including Vue itself when building your components since it is already imported by the bundle in GLPI itself. The core GLPI bundle sets window._vue to the vue module and the plugin’s externals option will map any imports from ‘vue’ to that. This will drastically reduce the size of your imports.

For your entrypoint, it is mostly the same as the core GLPI one except you should use the defineAsyncComponent method in window.Vue instead of importing it from Vue itself.

Example entrypoint:

// Require all Vue SFCs in js/src directory
const component_context = import.meta.webpackContext('.', {
    regExp: /\.vue$/i,
    recursive: true,
    mode: 'lazy',
    chunkName: '/vue-sfc/[request]'
});
const components = {};
component_context.keys().forEach((f) => {
    const component_name = f.replace(/^\.\/(.+)\.vue$/, '$1');
    components[component_name] = {
        component: window.Vue.defineAsyncComponent(() => component_context(f)),
    };
});
// Save components in global scope
window.Vue.components = Object.assign(window.Vue.components || {}, components);

To keep your components from colliding with core components or other plugins, it you should organize them inside the js/src/Plugin/Yourplugin folder. This will ensure plugin components are registered as Plugin/Yourplugin/YourComponent. You can organize components further with additional subfolders.

Creative Commons License