Use Vue component after Webpack build - vue.js

I have a CMS that delivers static HTML pages. For that CMS, I want to develop components with Vue that then can be used in the CMS individually.
As I understood, Vue is the perfect solution for that.
As TypeScript gets more and more common, I want to use TypeScript with Babel and Webpack, so the CLI project gave me a perfect boilerplate.
When I run npm run build, I get an index.html in the dist folder with my <div id="app"></div>-container. This could be my root element/template in CMS, and then just pass the components in it.
Sadly, everything in the app-container is rendered out.
I already registered my components inside the main.ts file, and removed the line render: (h)=>h(App), but it also replaces my container contents.
Main.ts:
import Vue from 'vue';
import App from './App.vue';
import ButtonLink from './components/ButtonLink.vue';
Vue.config.productionTip = false;
// Adding the component to my Vue context
Vue.component('ButtonLink', ButtonLink);
new Vue({
// render: (h) => h(App),
}).$mount('#app');
Excerpt of index.html in dist dir:
<div id=app>
<ButtonLink href="https://google.com">A link </ButtonLink>
</div>
Link to full project: https://gitlab.com/cedricwe/vue-problem/tree/master
What did I do wrong? Is this even possible?

It looks like you're using in-DOM templates without the runtime compiler, which would yield this browser console warning:
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
(found in <Root>)
The runtime compiler is excluded by default to reduce the bundle size. You could enable it in a Vue CLI project with the runtimeCompiler flag in vue.config.js in the root of your project:
module.exports = {
runtimeCompiler: true
}

What you really want to do is provide your Vue instance a "mounting point". In this case we normally use the el option something along the lines of this would work instead:
import Vue from 'vue';
import App from './App.vue';
import ButtonLink from './components/ButtonLink.vue';
Vue.config.productionTip = false;
new Vue({
el: '#app', // mounts this instance to #app but doesn't render it
components: {
ButtonLink // optionally have it local to your instance vs global
}
});

Related

Rollup, VueJS, install Vue Portal

How can I install an external package in Rollup in VueJS. I'm trying to install VuePortal, but I need to use Vue.use(PortalVue), but I don't where put it.
I tried with a package called rollup-plugin-auto-external, and I put it in:
plugins: [
...
autoExternal(),
...
],
Also I put into the externals's object, but nothing.
Thanks
You don't need a rollup plugin to use PortalVue.
Vue.use(PortalVue) should go in the entry point file, where you setup the root Vue instance (e.g., main.js, index.js, app.js, etc.).
For example:
// main.js
import Vue from 'vue'
import App from './App.vue'
import PortalVue from 'portal-vue'
Vue.use(PortalVue)
new Vue({
render: h => h(App)
}).$mount('#app')

Vue is not defined in a standalone web component

I am building a standalone Vue component and using it in another Vue project.
Build component:
vue build --target wc --inline-vue --name user-menu user-menu.vue
It's a simple component so far without functionality, just markup.
Then, in the main project in package.json:
"devDependencies": {
"user-menu": "git+https://........user-menu.git",
Then, in the main.js:
import Vue from "vue";
import UserMenu from "user-menu"
....
Vue.use(UserMenu);
const app = new Vue(config).$mount("#root");
window.app = app;
Vue.use(UserMenu);
And it says:
user-menu.js?e2ea:1446 Uncaught ReferenceError: Vue is not defined
on a row
module.exports = Vue;
But the Vue CLI 3 documentation says that:
In web component mode, Vue is externalized. This means the bundle will
not bundle Vue even if your code imports Vue. The bundle will assume
Vue is available on the host page as a global variable.
Any idea how to fix that?
Finally I came to the following solution: the component should not be built at all. Source files are enought to be imported like this:
import UserMenu from "user-menu/user-menu";
Pay attention that the path should point at the imported vue file, not just to the folder. But the extension "vue" must be skipped.
The final application will build it all together.

Vue-plugin - Not being able to import local linked custom plugin node module in another project

I created a very basic vue-plugin with some component that will be used in another project. The plugin code can be found here. The plugin works fine when tested independently.
In order to use this plugin in another project, I build the plug-in code with
vue-cli-service build --target lib --name testplugin ./src/index.js
This plugin will never be published to NPM registry and will be used only internally. So to test plugin module in another project, I run npm link on plugin dir and then npm link testplugin in another project.
Then I use it in another project like below -
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import router from '#/router'
import { testplugin } from 'testplugin'
Vue.config.productionTip = false
console.log(testplugin)
Vue.use(testplugin, { })
Vue.use(VueRouter)
new Vue({
router: router,
render: h => h(App),
}).$mount('#app')
The project compiles fine but testplugin is undefined. When I check node_modules directory, I can see my testplugin symlinked there.
I have tried diff approaches with no success. Any pointers would be helpful. Thanks.

Vuetify Styles not visible

I am a beginner in the world of Vue, so please bear with my foolish question(s).
I have a boilerplate code for a Vue project which I cloned from:
Vue Enterprise Boilerplate
I wanted to use Vuetify components, so I followed the following steps:
1. Cloned the vue-enterprise-boilerplate
2. npm install vuetify --save
3. In my main.js I added the vuetify dependency like:
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';
Vue.use(Vuetify);
4. I am using Vue CLI 3 (which comes with the boilerplate), also I have installed the CCS Loader.
5. Now in my app.vue, I have a simple button like:
<v-app>
<v-btn color="primary">Test</v-btn>
</v-app>
But when I run the app, I only see the outline of the button, but the styles are missing. Here is a screenshot below:
Also here is the dev-tools snapshot:
As you can see, the vuetify.min.css is being referenced, I am unable to debug why this is not behaving as per the Vuetify guides.
What steps am I missing?
What fixed the issue for me was the adding of class .v-application at the top most html tag (or the first one after template tag). Usually if I add <v-app> it all works but for some reason using vuitify 2.0.4 this didn't worked (may be because I'm not using vue-cli and webpack but parcel.js).
So adding this class solved the same issue for me.
EDIT
Actually I just found why v-app was ignored. Since I'm using vuetify 2.0.4. without vue-cli and webpack I need to include the vuetify components by my self like so:
import Vue from 'vue'
import Vuetify, {
VCard,
VImg,
VCardTitle,
VBtn,
VCardActions,
VCardText,
VProgressCircular,
VSpacer,
VDialog,
VDivider,
VAlert,
VApp,
} from 'vuetify/lib'
Vue.use(Vuetify, {
components: {
VCard,
VImg,
VCardTitle,
VBtn,
VCardActions,
VCardText,
VProgressCircular,
VSpacer,
VDialog,
VDivider,
VAlert,
VApp,
},
})
import 'material-design-icons-iconfont/dist/material-design-icons.css';
export default new Vuetify({})
Which is then imported in the vue app like this:
import Vue from "vue";
import vuetify from './src/vuetify'
import VocabularyApp from "./src/App.vue";
new Vue({
vuetify,
render: h => h(VocabularyApp)
}).$mount('#app-tutor');
So v-app wasn't working as I didn't included it in the list of components that I need for my app to work. More you can find here.
Welcome to the vuetiful world of vue.
You are looking into the shadow dom, please inspect the button element not the div element inside button element. The parent button element of the div will have classes like .primary .error based on the prop you give.
See the screenshot:
I hope this helps.
In my case I used stylus and had the css.requireModuleExtension = false option in vue.config.js. Styles just didn't load. Switching it to the true or removing this option did the trick.
// vue.congif.js
module.exports = {
// ...
css: {
// ...
requireModuleExtension: true
}
// ...
}

Vue.js migration to 2.0: Failed to mount component: template or render function not defined. (found in root instance)

// Edit: I think i have the problem solved. i needed the standalone build from vue...
i have migrated my vue.js 1.0 app to vue.js 2.0 (with migration helper). But this error shows me in the console Failed to mount component: template or render function not defined. (found in root instance).
Here is my simplified main.js:
import Vue from 'vue';
import Router from 'vue-router';
import SiteHeader from './components/Header.vue';
import Content from './components/Content/Content.vue';
import SiteFooter from './components/Footer.vue';
Vue.use(Router);
const router = new Router({
mode: 'history',
root: '/',
routes: [
{ path: '/', component: Content }
]
});
new Vue({
router,
components: {
SiteHeader, SiteFooter
}
}).$mount('body');
The Content.vue is an normal vue file with template and script (nothing special here).
My ´router-view` is defined in an laravel.blade file
#if(Request::is('login'))
<login></login>
#else
<site-header></site-header>
<router-view></router-view>
<site-footer></site-footer>
#endif
For starters, you are not allowed to mount to the body element in Vue 2.0.
Also, as the error message states, you have not provided a template or render function.
I assume (as you did not show) you have template markup directly in the HTML page.
This can work, but only with the "standalone" version of Vue. However, the default export of Vue's npm package is the "runtime build", which can't parse such templade code.
Further information here:
https://vuejs.org/guide/installation.html#Standalone-vs-Runtime-only-Build