Fresh Laravel 9 installation with vue 3 scaffold and vite not redering component - vue.js

I did a fresh laravel 9.19 installation with vue scaffolding and vite.js. everything works well just that the vue example component that comes with the fresh install of laravel refused to be rendered on the browser.
my environment
chrome Version - 108.0.5359.125 (Official Build) (64-bit)
node version - 19.3
Laravel 9.19
basically, as of today i'm using the latest version of everything.
I get a blank white screen on my browser with no errors on the console but the vue component is not rendering
I have tried suggestions from Laracast which is similar to my issue but nothing worked
content of my files
package.json
{
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build"
},
"devDependencies": {
"#popperjs/core": "^2.11.6",
"#vitejs/plugin-vue": "^3.0.1",
"axios": "^1.1.2",
"bootstrap": "^5.2.3",
"laravel-vite-plugin": "^0.7.0",
"lodash": "^4.17.19",
"postcss": "^8.1.14",
"sass": "^1.56.1",
"vite": "^3.0.0",
"vue": "^3.2.37"
}
}
vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: [
// 'resources/sass/app.scss',
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js',
},
},
});
resouces/js/app.js file
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
import './bootstrap';
import { createApp } from 'vue';
/**
* Next, we will create a fresh Vue application instance. You may then begin
* registering components with the application instance so they are ready
* to use in your application's views. An example is included for you.
*/
const app = createApp({});
import ExampleComponent from './components/ExampleComponent.vue';
app.component('example-component', ExampleComponent);
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// Object.entries(import.meta.glob('./**/*.vue', { eager: true })).forEach(([path, definition]) => {
// app.component(path.split('/').pop().replace(/\.\w+$/, ''), definition.default);
// });
/**
* Finally, we will attach the application instance to a HTML element with
* an "id" attribute of "app". This element is included with the "auth"
* scaffolding. Otherwise, you will need to add an element yourself.
*/
app.mount('#app');
resouces/views/layouts/app.blade.php
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
<!-- Scripts -->
#vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body>
<div id="app">
{{-- vue component goes here --}}
</div>
</body>
</html>
resources/js/components/ExampleComponent.vue
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">Example Component</div>
<div class="card-body">
I'm an example component.
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
console.log('Component mounted.')
}
}
</script>

So i changed the boilerplate code in my resouces/js/app.js file and it worked. i don't know why.
i changed this
import './bootstrap';
import { createApp } from 'vue';
const app = createApp({});
import ExampleComponent from './components/ExampleComponent.vue';
app.component('example-component', ExampleComponent);
app.mount('#app');
to this
import './bootstrap';
import { createApp } from 'vue';
import ExampleComponent from './components/ExampleComponent.vue';
createApp(ExampleComponent).mount('#app');

So I recently just encountered this issue. I got a blank page when I run npm run dev. Thankfully on the console, I got the error message in the image below.
So I went ahead to my app.js to change my Vue import from
import { createApp } from "vue";
to
import { createApp } from 'vue/dist/vue.esm-bundler';

Related

Uncaught TypeError: Cannot use 'in' operator to search for 'path' in undefined

hi iam tring to learn about vue-router and i watched more than 1 tutrial but i got this error 'Cannot use 'in' operator to search for 'path' in undefined 'and the router-link tags unclickable
here is my versions in pack json
"dev": "vite",
"build": "vite build"
"devDependencies"
"axios": "^0.27",
"laravel-vite-plugin": "^0.5.4",
"lodash": "^4.17.19",
"postcss": "^8.1.14",
"vite": "^3.0.9"
},
"dependencies"
"#vitejs/plugin-vue": "^3.0.3",
"vue": "^3.2.36",
"vue-loader": "^17.0.0",
"vue-router": "^4.1.3"
app.js
import './bootstrap';
import { createApp } from 'vue';
import ExampleComponent from './components/ExampleComponent.vue'
import About from './components/about.vue'
import {createRouter} from 'vue-router'
import {createWebHistory} from 'vue-router'
const routes =[
{path : "/", component :ExampleComponent ,name : 'home'},
{path : "/about", component : About ,name : 'about'}
]
const router =createRouter({
el : '#app',
history : createWebHistory,
routes,
})
const app =createApp()
app.use(router)
app.mount('#app')
welcome.blade
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
#vite('resources/css/app.css')
</head>
<body>
<div id="app">
<router-link to ="/">home</router-link>
<router-link to ="/about">about</router-link>
#vite('resources/js/app.js')
</div>
</body>
</html>
Not sure about the error yet, but the links are wrong because you're using named routes so you should use another syntax for the links in the HTML (welcome.blade):
https://router.vuejs.org/guide/essentials/named-routes.html#named-routes
Or remove the name attributes from your routes in app.js.
Also pay a bit more attention to indentation and whitespace as that might also throw the compiler off and might be the reason you get the error it should look like this:
const routes = [
{path : "/", component: ExampleComponent, name: "home"},
{path : "/about", component: About, name: "about"}
]
Hope this helps you out.

Vue3 works with unpkg but not with npm + webpack

I'm trying to set up Vue3 so that I can use it via npm + webpack. For some reason the component does not get mounted and no error is shown. If I instead use unpkg it works. How can I make the npm + webpack option work?
I have "vue": "^3.1.5" in my package.json and the following webpack config:
module.exports = {
mode: 'production',
entry: {
provider: './src/components/provider.js',
requester: './src/components/requester.js',
},
optimization: {
minimize: false
},
output: {
path: `${__dirname}/../public`,
filename: '[name].js',
}
}
requester.js:
import { createApp } from 'vue'
createApp({
template: `
<div>
<div>
<h2>NĂºmeros recibidos</h2>
{{ receivedNumbers }}
<ul>
<li v-for="n in receivedNumbers">{{ n }}</li>
</ul>
</div>
</div>
`,
data() {
return {
receivedNumbers: [1,2,3],
numberRequestIsOpen: false,
}
},
}).mount('#requester-component');
requester.html
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<h1>requester</h1>
<div id="requester-component"></div>
<script src="requester.js"></script>
</body>
</html>
resulting html
<h1>requester</h1>
<div id="requester-component" data-v-app=""><!----></div>
<script src="requester.js"></script>
In the other hand, if I add <script src="https://unpkg.com/vue#next"></script> in the head tag of my html and change the js to:
Vue.createApp({
//
}).mount('#requester-component');
then the resulting html is
<h1>requester</h1>
<div id="requester-component" data-v-app=""><div><div><h2>NĂºmeros recibidos</h2> [
1,
2,
3
] <ul><li>1</li><li>2</li><li>3</li></ul></div></div></div>
<script src="requester.js"></script>
which is the expected output.
Link to the repo in case it helps to play around. Last commit adds the unpkg has, and the previous one has the npm version
https://github.com/vuejs/vue-next/issues/4275
In order to use the functionality of the vue.js template, you need to load the finished package with the compiler and runtime, but vue.js by default loads the runtime only version, so you need to explicitly specify the version (vue.esm-bundler.js)
Adding
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm-bundler.js'
}
}
solved the issue.

VueJs - import component in asp.net core project

I have asp.net core project, which uses vuejs framework (javascript)
This is a sample of the page structure (with everything stripped out for simplicity)
//Index.cshtml
<div id="page-1">
</div>
<script src='~/page-1.js' defer></script>
//page-1.js
(function () {
var Page1Vue = new Vue({
el: "#page-1",
});
})();
everything works fine (mounted, all methods etc)
I want to bring in this external component https://vue-multiselect.js.org/, but cannot get it to work.
Has anyone any pointers on to integrate an external component into an existing instance.
import external library in _Layout.cshtml, please import esm.js library
<script type="importmap">
{
"imports": {
"vue": "/lib/vue.esm.browser.js_2.6.11/vue.esm-browser.js",
"vue-multiselect":"https://cdnjs.cloudflare.com/ajax/libs/vue-multiselect/3.0.0-alpha.2/vue-multiselect.esm.min.js"
}
}
</script>
insert multiselect node into Index.cshtml
<div id="app">
<multiselect v-model="value" :options="options"></multiselect>
</div>
create Vue Component into Index.cshtml
<script type="module">
import { createApp } from 'vue'
import VueMultiselect from 'vue-multiselect'
createApp({
data () {
return {
value: null,
options: ['list', 'of', 'options']
}
}
})
.component('multiselect', VueMultiselect)
.mount('#app')
</script>
#section Scripts
{
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect#2.1.0/dist/vue-multiselect.min.css">
}
the result as below

Font awesome icons in buefy

I'm trying to switch my project from bulma + jQuery to buefy. I load buefy, vue and font awesome from a cdn. (buefy#0.6.7, vue#2.5.17, font awesome 5.2.0). The main problem I have with icons. My project uses font awesome icons. And default buefy iconPack is material design. It must support font awesome. I've tried to change the default icon pack, but that does nothing:
Vue.use(Buefy.default, {
defaultIconPack: 'fas',
});
the same nothing:
Vue.use(Buefy, {
defaultIconPack: 'fas',
});
So I need to point the iconpack explicitly for every icon.
The second problem is that even in this case buefy adds fa-lg that I don't need at all. For example for b-tab-item component
<b-tab-item label="Similarity" icon="search" icon-pack="fas"></b-tab-item>
It renders:
<i class="fas fa fa-search fa-lg"></i>
Is it possible to change this buefy behaviour?
to anyone that may still struggle with this. my problems was solved by using this in my main.js:
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'
import { library } from '#fortawesome/fontawesome-svg-core';
// internal icons
import { fas } from "#fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "#fortawesome/vue-fontawesome";
library.add(fas);
Vue.component('vue-fontawesome', FontAwesomeIcon);
Vue.use(Buefy, {
defaultIconComponent: "vue-fontawesome",
defaultIconPack: "fas",
customIconPacks: {
fas: {
sizes: {
default: "lg",
"is-small": "1x",
"is-medium": "2x",
"is-large": "3x"
},
iconPrefix: ""
}
}
});
make sure to install all the dependencies using npm:
$ npm i --save #fortawesome/fontawesome-svg-core
$ npm i --save #fortawesome/free-solid-svg-icons
$ npm i --save #fortawesome/vue-fontawesome
then you can use it in your components as follows:
<b-icon
pack="fas"
icon="user"
size="is-large"
type="is-success"></b-icon>
This is working code for me in buefy
in main.js
import { library } from '#fortawesome/fontawesome-svg-core'
import { fas } from '#fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/vue-fontawesome'
library.add(fas)
Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.use(Buefy, { defaultIconPack: 'fas' })
and in index.html
place in head tag
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
crossorigin="anonymous"
/>
make sure first off you add the fortawesome npm package
If you run:
yarn add #fortawesome/fontawesome-free
And then import:
import '../node_modules/#fortawesome/fontawesome-free/js/all.js'
It should then work. Importing from a CDN doesn't seem to work.
Further to original answer. This is working code for me using a CDN:
main.js
import Vue from 'vue'
import App from './App.vue'
import Buefy from 'buefy';
import 'buefy/dist/buefy.css'
Vue.use(Buefy, {
defaultIconPack: 'fas'
});
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
template
<template>
<div class="container">
<b-tabs
is-boxed>
<b-tab-item label="Search" icon="search"></b-tab-item>
<b-tab-item label="Music" icon="music"></b-tab-item>
<b-tab-item label="Videos" icon="video"></b-tab-item>
</b-tabs>
</div>
</template>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<title>buefy-test</title>
</head>
<body>
<noscript>
<strong>We're sorry but buefy-test doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

Can we make vue.js application without .vue extension component and webpack?

Note: Can we write vue.js large application without using any compiler for code like currently i see all example use webpack now to make vue.js code compatible for browser .
I want make vue.js application without webpack and without using .vue extension. Is it possible? if it is possible, can you provide a link or give sample how to use routing in that case.
As we make component in .vue extension can be make component in .js extension and use application as we do in angular 1 where we can make whole app without any trans-compiler to convert the code.
Can be done that in html , css , js file only and no webpack sort of thing.
What i have done .
index.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vueapp01</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
main.js this file added in webpack load time
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
App.vue
<template>
<div id="app">
<img src="./assets/logo.png">
Hello route
Helloworld route
{{route}}
<router-view/>
<!-- <hello></hello> -->
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
route : "This is main page"
}
}
}
</script>
router
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '#/components/HelloWorld'
import Hello from '../components/Hello'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/hello',
name: 'Hello',
component: Hello
}
]
})
I have done something like this . Can we do this by just html , css , js file only with not webpack to compile code . Like we do in angular 1 .
Thanks
As stated in this jsFiddle: http://jsfiddle.net/posva/wtpuevc6/ , you have no obligation to use webpack or .vue files.
The code below is not from me and all credit goes to this jsFiddle creator:
Create an index.html file:
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
<script src="https://npmcdn.com/vue-router/dist/vue-router.js"></script>
<script src="/js/Home.js"></script>
<script src="/js/Foo.js"></script>
<script src="/js/router.js"></script>
<script src="/js/index.js"></script>
<div id="app">
<router-link to="/">/home</router-link>
<router-link to="/foo">/foo</router-link>
<router-view></router-view>
</div>
Home.js
const Home = { template: '<div>Home</div>' }
Foo.js
const Foo = { template: '<div>Foo</div>' }
router.js
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/foo', component: Foo }
]
})
index.js
new Vue({
router,
el: '#app',
data: {
msg: 'Hello World'
}
})
Appreciate the framework...
Just a sidenote: .vue files are really awesome, you should definitely try them if not using them is not a requirement
I have started learning vue.js also and I am not familiar with webpack and stuff and I also wanted to still separate and use .vue files as it makes management and code cleaner.
I have found this library:
https://github.com/FranckFreiburger/http-vue-loader
and a sample project using it:
https://github.com/kafkaca/vue-without-webpack
I am using it and it seems to work fine.
You perfectly can, but with a lot of disadvantages. For example: you cannot easily use any preprocessor, like Sass or Less; or TypeScript or transpile source code with Babel.
If you don't need support for older browser, you can use ES6 modules today. Almost all browsers support it. See: ES6-Module.
But Firefox doesn't support dynamic import(). Only Firefox 66 (Nightly) support it and need to be enabled.
And if that wasn't enough, your web application will not be indexed. It's bad for SEO.
For example, Googlebot can craw and index Javascript code but still uses older Chrome 41 for rendering, and it's version don't support ES6 modules.
If that are not disadvantages for you, then you can do this:
Remove any thirty party library import like Vue, VueRouter, etc. And include those in the index.html file using script tags. All global variables are accesible in all es6 modules. For example, remove this line from main.js and all .vue files:
import Vue from 'vue';
And add this line in your index.html:
<script src="https://npmcdn.com/vue/dist/vue.js"></script>
Rewrite all .vue files and change file extension to .js. For example, rewrite something like this:
<template>
<div id="home-page">
{{msg}}
</div>
</template>
<script>
export default {
data: function() {
return { msg: 'Put home page content here' };
}
}
</script>
<style>
#home-page {
color: blue;
}
</style>
to something like this:
let isMounted = false; /* Prevent duplicated styles in head tag */
export default {
template: `
<div id="home-page"> /* Put an "id" or "class" attribute to the root element of the component. Its important for styling. You can not use "scoped" attribute because there isn't a style tag. */
{{msg}}
</div>`,
mounted: function () {
if (!isMounted) {
let styleElem = document.createElement('style');
styleElem.textContent = `
#home-page {
color: blue;
}
`;
document.head.appendChild(styleElem);
isMounted = true;
}
},
data: function () {
return {
msg: 'Put home page content here'
};
}
}
It is all. I put an example in this link
P.S. Text editing without syntax highlighting can be frustrating. If you use Visual Studio Code you can install Template Literal Editor extension. It allows editing literal strings with syntax highlight. For styles select CSS syntax, and for templates HTML syntax. Unknown tag in HTML are highlighted differently. For solve this, change the color theme. For example, install Brackets Dark Pro color theme or any theme do you like.
Regards!
For sure you can. We did a project with Vue, and we had couple of problems during compiling .vue files.
So we switched to structure with three separate files.
But be aware that you need webpack anyway. The idea of Vue was to split huge projects into components, so using template inside .js file it's pretty normal.
So take a look at
html-loader
And
css-loader
Using these modules you can write something like this:
component.js
// For importing `css`. Read more in documentation above
import './component.css'
// For importing `html`. Read more in documentation above
const templateHtml = require('./component.html')
export default {
name: 'ComponentName',
components: { /* your components */ },
mixins: [/* your mixins */ ],
template: templateHtml,
computed: .....
}
component.css
#header {
color: red
}
component.html
<div id="header"></div>
BUT
You need to know that HTML file should be written in the same way as I you will have it in template property.
Also, take a look at this repo, maybe you will find something useful here
Vue-html-loader. It is a fork from html-loader by Vue core team.
In vuejs 3 you you can do it in an ES6 modular fashion (no webpack or other tools required):
index.html
<!DOCTYPE html>
<html>
<head>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue#3.0.11/dist/vue.esm-browser.js",
"vue-router": "https://unpkg.com/vue-router#4.0.5/dist/vue-router.esm-browser.js",
"html" : "/utils/html.js"
}
}
</script>
<script src="/main.js" type="module"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
main.js
import { createApp, h } from 'vue';
import {createRouter, createWebHashHistory} from 'vue-router';
import App from './components/App.js';
const routes = [//each import will be loaded when route is active
{ path: '/', component: ()=>import('./components/Home.js') },
{ path: '/about', component: ()=>import('./components/About.js') },
]
const router = createRouter({
history: createWebHashHistory(),
routes,
})
const app = createApp({
render: () => h(App),
});
app.use(router);
app.mount(`#app`);
components/App.js
import html from 'html';
export default {
name: `App`,
template: html`
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
<router-view></router-view>
`};
components/Home.js
import html from 'html';
export default {
template: html`
<div>Home</div>
`};
components/About.js
import html from 'html';
export default {
template: html`
<div>About</div>
`};
utils/html.js
// html`..` will render the same as `..`
// We just want to be able to add html in front of string literals to enable
// highlighting using lit-html vscode plugin.
export default function () {
arguments[0] = { raw: arguments[0] };
return String.raw(...arguments);
}
Notes:
Currently (04/2021) importmap works only on chrome (firefox in progress). To make the code compatible with other browsers also, just import (on each .js file) the dependencies directly from the urls. In this case though vue-router.esm-browser.js still imports 'vue', so you should serve an updated version of it, replacing import { .... } from 'vue' with import { .... } from 'https://unpkg.com/vue#3.0.11/dist/vue.esm-browser.js'
To avoid waterfall loading effect, you can add <link rel="modulepreload" href="[module-name]"> entries to index.html to start preloading some or all modules asynchronously before you need them.
A Related article
Vue can be included on a single html page quite simply:
Vue 3 minimal example:
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<div id="app">{{ message }}</div>
<script>
const { createApp } = Vue
createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
Vue 2 minimal example, with Vuetify
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<v-main>
<v-container>Hello world</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
})
</script>
</body>
</html>
vue 2 guides:
https://v2.vuejs.org/v2/guide/installation.html#CDN
https://vuetifyjs.com/en/getting-started/installation/#usage-with-cdn
vue 3 guide: https://v2.vuejs.org/v2/guide/installation.html#CDN