Vue2 async components examples?

Hello! Sorry for my bad english, but I need a help.

I read docs https://vuejs.org/guide/components.html#Async-Components but I didn’t understand how I can require components with Ajax.

I want put components (pages of app) in page-folder on server. I will use vue-router, and when user will address to url, should be loaded component from server.

Can I see such examples, please? :slight_smile:

And one more thing! Does vue-resource work with Vue2 ?

First let me ask you, do you use some module bundler like Webpack, Browserify? Or do you just include Vue in the script tag from cdn?

Regarding vue-resource, yes it works with Vue 2.

I don’t use module bundler like Webpack, Browserify. I read a lot about Webpack, but didn’t understand how it works. The only thing what I understood, that need for Node.js. But I never use server js scripts. I include Vue in the script tag only from cdn.

Hi @razorg1991

Sorry for late response but had busy day at work :stuck_out_tongue: Now about your question. Well it would be definitely easier to lazy load pages of your site and the codebase would be much more maintainable if you’d just use webpack There’s plenty of tutorials out there and ready to use Vue boilerplates,but if you already decided not to use it.there is one solution I can think of that can resolve your problem and it’s actually quite simple. Here’s the example:

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Vue test</title>
</head>
<body>

  <div id="app">
    <router-link to="/">/home</router-link>
    <router-link to="/contact">/contact</router-link>

    <router-view></router-view>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/2.0.1/vue-router.min.js"></script>
  <script>

    function loadComponent(componentName, path) {
      // Promise polyfill required!!!
      return new Promise(function(resolve, reject) {
        var script = document.createElement('script');

        script.src = path;
        script.async = true;

        script.onload = function() {
          var component = Vue.component(componentName);

          if (component) {
            resolve(component);
          } else {
            reject();
          }
        };
        script.onerror = reject;

        document.body.appendChild(script);
      });
    }

    var router = new VueRouter({
      mode: 'history',
      routes: [
        {
          path: '/',
          component: {
            template: '<div>Home page</div>'
          },
        },
        {
          path: '/contact',
          component: function(resolve, reject) {
            loadComponent('contact', 'contact.js').then(resolve, reject);
          }
        }
      ]
    });

    var app = new Vue({
      el: '#app',
      router: router,
    });
  </script>

</body>
</html>

// contact.js

Vue.component('contact', {
  template: '<div>Contact page</div>'
});

You probably already see how it works. I created loadComponent function that takes 2 arguments - component name and path to the script wherein the component is located. And there’s no magic here. We simply create new script, append it to the DOM, listen to onload event and when the script is fully loaded we resolve the promise with given componen. Of course you don’t have to use Promise if you don’t want to, then you change the function and use callbacks:

function loadComponent(opts) {
  var script = document.createElement('script');
  
  opts.onLoad = opts.onLoad || function() {};
  opts.onError = opts.onError || function() {};

  script.src = opts.path;
  script.async = true;

  script.onload = function() {
    var component = Vue.component(opts.name);

    if (component) {
      opts.onLoad(component);
    } else {
      opts.onError();
    }
  };
  script.onerror = opts.onError;

  document.body.appendChild(script);
}

loadComponent({
  name: 'contact',
  path: 'contact.js',
  onLoad: resolve,
  onError: reject
});

I hope I have explained this to you clearly enough but if you have some future questions please ask :slight_smile:

2 Likes

Sqal, I am very grateful for the detailed answer! Thank :grinning:
These days, I read the nice article about webpack and understood how it works! :slight_smile: It is symbiosys of CommonJS, RequireJS and AMD.
Do I understand correctly, what webpack on node.js create only file-autoloader called bundler. I must be connected it in html src-directive, and it do all that is necessary without the node.js? If I want require components sync, I must write code in main.js file with CommonJS syntax, and vice versa, async - with AMD syntax.
If I’m wrong correct me, please.

And now about async components in Vue. I read this https://vuejs.org/guide/components.html#Async-Components

As I understand, this code Vue.component('async-webpack-example', function (resolve) { // This special require syntax will instruct Webpack to // automatically split your built code into bundles which // are loaded over Ajax requests. require(['./my-async-component'], resolve) })
I must place in main.js file and perform “webpack” command in cli. It will be created bundler.js, want to connect in html src-directive?

If you do not complicate, can you show me this code with vue-router? :slight_smile:

how about this demo

router is not necessary

gravedigger??

Hello,

I tried you solution with your function loadComponent.
Is there a solution to have the HTML template like that:

<template id="contact">
 <div>Contact page</div>
</template> 

<script>
Vue.component('contact', {
  template: '#contact'
});
</script>

Thanks.