Import a Vue js component from Laravel Blade File

前端 未结 3 1623
甜味超标
甜味超标 2021-02-04 22:39

I have registered a some components as a global components in js/app.js file, But this makes the compiled app.js file larger.

//example         


        
3条回答
  •  清歌不尽
    2021-02-04 23:30

    To further extend on Salim Example, you can add Vue to the window and directly create the exported Vue Component within the Vue File.


      1. Autoload Vue Within Laravel Mix
      1. Globally Register Component As You Create Them
      1. Instead Of Requiring Each Component, Simplify With Laravel Mix
      1. Extend Laravel Mix, removing every import, require, register, & compile step - simply create a vue component and use it

    1) Autload Vue Within Laravel Mix


    webpack.mix.js

    const mix = require('laravel-mix');
    
    mix.autoload({vue: ['Vue', 'window.Vue']})
       .js(...)
       .css(...)
       .version()
    

    2) Register Vue Components Globally As You Create Them


    resources/js/components/profile/profile-image.vue

    
    
    
    

    3) Instead of requiring each component simply use Laravel Mix

    webpack.mix.js

    const mix = require('laravel-mix');
    
    mix.autoload({ 
      vue: [
         'Vue', 
         'window.Vue'
      ] 
    })
    .js([
          /* --------------------------------- 
           |   Card Components
           | ---------------------------------
           |
           | . Card.vue (Original)
           | . IconCard.vue (Topic Contextually Relevant Icon)
           | . DetailCard.vue (Shown On Detail Pages & Used To Summarize Index Tables)
           |
          */
          'resources/js/components/cards/card.vue',
          'resources/js/components/cards/icon-card.vue',
          'resources/js/components/cards/index-card.vue',
          'resources/js/components/cards/detail-card.vue',
          'resources/js/components/cards/organization-card.vue',
    
          /* --------------------------------- 
           |   Button Components
           | ---------------------------------
           |
           | . Button.vue (Original)
           | . ButtonRipple.vue (Interactive Click Effects)
           | . ButtonFabIcon.vue (Rounded, Material Design Icons)
           |
          */
          'resources/js/components/buttons/button.vue',
          'resources/js/components/buttons/primary.vue',
          'resources/js/components/buttons/success.vue',
          'resources/js/components/buttons/button-ripple.vue',
          'resources/js/components/buttons/primary-ripple.vue',
          'resources/js/components/buttons/success-ripple.vue',
          'resources/js/components/buttons/button-fab-icon.vue',
          'resources/js/components/buttons/primary-fab-icon.vue',
          'resources/js/components/buttons/success-fab-icon.vue',
    
    
    
          /* --------------------------------- 
           |   Fields Components
           | ---------------------------------
           |
           | . Form.vue (Create & Update)
           | . Detail.vue (Show, Edit, & Cards)
           | . Index.vue (Tables Ex: Sort, Search, Filter)
           |
          */
          'resources/js/components/fields/date/form.vue',
          'resources/js/components/fields/date/index.vue',
          'resources/js/components/fields/date/detail.vue',
    
          /** Then that one component we actually created ;D **/
          'resources/js/components/profile/profile-image.vue',
    
    ], 'resources/js/components/bootstrap.js')
    
    
    .babel([
          /* ------------------------------------------------------------------
           | Mounting Vue & Using "Babel" (Vanilla JS For Every Browsers)  
           | ------------------------------------------------------------------
           |
           | . Our Components are compiled
           | . Our Last File Being Added Will Mount Vue
           | . We'll Use ".babel()" While Adding This File
           | . "Babel" Simply Transforms All Javascript Into Vanilla JS
           |
          */
            'resources/js/components/bootstrap.js', 
            'resources/js/bootstrap/mount-vue.js'
    
    ], 'public/js/app.js')
    
    
    /*------------------------------*/
    /* Optimization Minification   
    /*------------------------------*/
    .minify('public/js/app.js');
    
    /*------------------------------*/
    /* Cache Busting Versioning   
    /*------------------------------*/
    if (mix.inProduction()) {
      mix.version();
    }
    

    4) Simplify Further By Extending Laravel Mix

    resources/js/mix-extensions/mix-every-vue-component.js

    import upperFirst from 'lodash/upperFirst'
    import camelCase from 'lodash/camelCase'
    
    const requireComponent = require.context(
      // The relative path of the components folder
      './components',
      // Whether or not to look in subfolders
      false,
      // The regular expression used to match base component filenames
      /Base[A-Z]\w+\.(vue|js)$/
    )
    
    requireComponent.keys().forEach(fileName => {
      // Get component config
      const componentConfig = requireComponent(fileName)
    
      // Get PascalCase name of component
      const componentName = upperFirst(
        camelCase(
          // Gets the file name regardless of folder depth
          fileName
            .split('/')
            .pop()
            .replace(/\.\w+$/, '')
        )
      )
    
    
      // Register component globally
      Vue.component(
        componentName,
        // Look for the component options on `.default`, which will
        // exist if the component was exported with `export default`,
        // otherwise fall back to module's root.
        componentConfig.default || componentConfig
      )
    })
    

    webpack.mix.js

    const mix = require('laravel-mix');
    
    class LaravelMixEveryVueComponent
    {
        public constructor() {
    
        }
    
    }
    mix.autoload({ 
      vue: [
         'Vue', 
         'window.Vue'
      ] 
    })
    .js([
          /* --------------------------------- 
           |   Card Components
           | ---------------------------------
           |
           | . Card.vue (Original)
           | . IconCard.vue (Topic Contextually Relevant Icon)
           | . DetailCard.vue (Shown On Detail Pages & Used To Summarize Index Tables)
           |
          */
          'resources/js/components/cards/card.vue',
          'resources/js/components/cards/icon-card.vue',
          'resources/js/components/cards/index-card.vue',
          'resources/js/components/cards/detail-card.vue',
          'resources/js/components/cards/organization-card.vue',
    
          /* --------------------------------- 
           |   Button Components
           | ---------------------------------
           |
           | . Button.vue (Original)
           | . ButtonRipple.vue (Interactive Click Effects)
           | . ButtonFabIcon.vue (Rounded, Material Design Icons)
           |
          */
          'resources/js/components/buttons/button.vue',
          'resources/js/components/buttons/primary.vue',
          'resources/js/components/buttons/success.vue',
          'resources/js/components/buttons/button-ripple.vue',
          'resources/js/components/buttons/primary-ripple.vue',
          'resources/js/components/buttons/success-ripple.vue',
          'resources/js/components/buttons/button-fab-icon.vue',
          'resources/js/components/buttons/primary-fab-icon.vue',
          'resources/js/components/buttons/success-fab-icon.vue',
    
    
    
          /* --------------------------------- 
           |   Fields Components
           | ---------------------------------
           |
           | . Form.vue (Create & Update)
           | . Detail.vue (Show, Edit, & Cards)
           | . Index.vue (Tables Ex: Sort, Search, Filter)
           |
          */
          'resources/js/components/fields/date/form.vue',
          'resources/js/components/fields/date/index.vue',
          'resources/js/components/fields/date/detail.vue',
    
          /** Then that one component we actually created ;D **/
          'resources/js/components/profile/profile-image.vue',
    
    ], 'resources/js/components/bootstrap.js')
    
    
    .babel([
          /* ------------------------------------------------------------------
           | Mounting Vue & Using "Babel" (Vanilla JS For Every Browsers)  
           | ------------------------------------------------------------------
           |
           | . Our Components are compiled
           | . Our Last File Being Added Will Mount Vue
           | . We'll Use ".babel()" While Adding This File
           | . "Babel" Simply Transforms All Javascript Into Vanilla JS
           |
          */
            'resources/js/components/bootstrap.js', 
            'resources/js/bootstrap/mount-vue.js'
    
    ], 'public/js/app.js')
    
    
    /*------------------------------*/
    /* Optimization Minification   
    /*------------------------------*/
    .minify('public/js/app.js');
    
    /*------------------------------*/
    /* Cache Busting Versioning   
    /*------------------------------*/
    if (mix.inProduction()) {
      mix.version();
    }
    

    4. Extend Laravel Mix Removing All Extra Steps

    laravel-mix-autoload-vuejs-extension.js

    const mix = require('laravel-mix');
    
    
    const CollectFiles = (folder, files = []) => {
        const isFolder = to => File(path.resolve(to)).isDirectory();
        const CombineFiles = (Files, Segments = []) => [ ...files, path.join(__dirname, Segments[0], '/', Segments[1])];
    
        return fs.readdirSync(folder).reduce((filed, file) =>
                isFolder(`${folder}/${file}`)
                    ? CollectFiles(`${folder}/${file}`, files)
                    : CombineFiles(files, [folder, file]),
            files
        ).map(string => string.replace(__dirname, ''));
    };
    
    
    class LaravelMixAutoloadVue
    {
        constructor()
        {
            this.LoadVueComponents = (to, output) => mix.js(CollectFiles(to), output);
    
            return mix;
        }
    
        dependencies()
        {
            return ['fs', 'path'];
        }
    
        name()
        {
            return ['vuejs'];
        }
    
        register(to, output)
        {
            if (typeof to === 'undefined') {
                return console.log(`Output is undefined for codesplit path ${to}`);
            }
    
            this.LoadVueComponents(to, output);
        }
    
        boot()
        {
            console.log("Booting Example");
        }
    }
    
    mix.extend('vuejs', new LaravelMixAutoloadVue());
    
    

    webpack.mix.js webpack.mix.js

    const mix = require('laravel-mix');
    require('./laravel-mix-autoload-vuejs`);
    
    mix.autoload({ 
      vue: [
         'Vue', 
         'window.Vue'
      ] 
    })
          /* -------------------------------------------------------------
           |  Laravel Mix Autoload Vue Extensions Handles All Components
           | -------------------------------------------------------------
          */
    .vuejs('resources/js/components/', 'resources/js/components/bootstrap.js') 
    .babel([
          /* ------------------------------------------------------------------
           | Mounting Vue & Using "Babel" (Vanilla JS For Every Browsers)  
           | ------------------------------------------------------------------
           |
           | . Our Components are compiled
           | . Our Last File Being Added Will Mount Vue
           | . We'll Use ".babel()" While Adding This File
           | . "Babel" Simply Transforms All Javascript Into Vanilla JS
           |
          */
            'resources/js/components/bootstrap.js', 
            'resources/js/bootstrap/mount-vue.js'
    
    ], 'public/js/app.js')
    
    
    /*------------------------------*/
    /* Optimization Minification   
    /*------------------------------*/
    .minify('public/js/app.js');
    
    /*------------------------------*/
    /* Cache Busting Versioning   
    /*------------------------------*/
    if (mix.inProduction()) {
      mix.version();
    }
    

提交回复
热议问题