Vue comes with a runtime build which allows for CSP compliance.
The following addition to the webpack.mix.js allows mix to use the runtime version:
mix.webpackConfig({
resolve: {
alias: {
'vue$': 'vue/dist/vue.runtime.js'
}
}
});
This compiles the resources find but does not work during runtime as the templates are not compiled to render functions. In the link above, it is suggested that webpack + vue-loader can be used to pre-compile the templates.
However, I couldn't find a way to do this. It would be great if this could be included in the docs. If it is already included, please forgive my ignorance and point me to it :smiley:
Are you using single file components?
@DrJonki Yes, all the components in the project will be single file components. I suppose that's kind of necessary to get the pre-compilation?
@sausin Correct. The default installation of Mix has vue-loader already set-up (mentioned here), so as long as all of your Vue templates are defined either in single-file blocks or as raw render functions, the runtime-only build should work just fine.
@DrJonki That's why I can't figure out what's wrong. I get the following error when I use the runtime build:
[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>)
And I don't have any items hanging around for the runtime build to compile.. :confused:
I presume passing data to the component doesn't count as compiling, because I do have some of those
@sausin Can you show how you instantiate your Vue instance and what the mount point looks like in your HTML?
It's a laravel project with the app.js like this:
...
...
Vue.component('MyCookieBanner', require('./components/MyCookieBanner.vue'));
...
...
const app = new Vue({
el: '#app'
});
The main layout file is like this:
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
...
...
<body>
<div id="app">
<my-cookie-banner>
</my-cookie-banner>
...
...
...
</div>
</body>
...
</html>
<my-cookie-banner>
</my-cookie-banner>
There's your problem. You're sending HTML with a custom element, which Vue will pick up on, but being unable to handle rendering it, missing the template compiler and all :P
Try something like this:
const root = require('./components/MyCookieBanner.vue');
const app = new Vue({
el: '#app',
render: createElement => createElement(root) //< The important line
});
EDIT: In addition you shouldn't have anything inside <div id="app">
@DrJonki Thanks for looking into this !
I have several components and several pages which use different components. How would I go about doing this?
Also, not sure what you meant by
EDIT: In addition you shouldn't have anything inside
<div id="app">
How do I define where the vue component should 'come up'?
Sorry for being thick, if this should've been obvious :confused:
What I like to do, is to have a separate 'root' component (as a .vue file). In the template of the root component I would lay out the rest of the page layout.
In other words, take everything you have inside <div id='app'> and move it into it's own component file. Pass this component into createElement.
@DrJonki Thanks for the tip! I think I got it :+1:
@sausin But this doesn't solve the CSP issue with "eval" function used in the compiled app.js
Most helpful comment
There's your problem. You're sending HTML with a custom element, which Vue will pick up on, but being unable to handle rendering it, missing the template compiler and all :P
Try something like this:
EDIT: In addition you shouldn't have anything inside
<div id="app">