Compile Laravel Vue components into different js files - laravel

I have a big project in Laravel, which have several front-ends, depending on logged user.
I also have a shared directory, where common components (like table, modal, etc.) can be used by the different front-end.
I want to compile each front-end to a different js file, so I can include only the relevant file for each user.
What I have till now:
webpack.mix.js:
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/frontendUser.js', 'public/js')
.js('resources/js/frontendAdmin.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
Under resources/js I have a separate file for each front-end, for example frontendAdmin.js:
require('./bootstrap');
window.Vue = require('vue');
Vue.component(
'frontend-admin-component',
require('./components/FrontendAdminComponent.vue').default
);
const app = new Vue({
el: '#app',
});
When I run npm run dev fiels are compiled correctly, and I can include them from the blade file:
<script src="{{ asset('js/frontendAdmin.js') }}" defer></script>
However, I get in console this error:
[Vue warn]: Unknown custom element: <frontend-admin-component>
- did you register the component correctly? For recursive components,
make sure to provide the "name" option.
Looks like the component behaves well, however I assume the warning exists for some reason and would like to fix it.
Is what I try to do have sense? What is wrong?

This warning generally occurs if you do not specify any name your component
For example, if you have a component called User.vue then your component should be as follows:
<template>
</template>
<script>
export default {
name: 'User'
}
</script>
<style>
</style>
This name option is not mandatory but it is convention to use a name for each component for all components.

Related

Laravel + vue.js : vue devtools only showing <Root> compenent

I have a little problem with vue.js recently and wondering if anyone could help please?
I have a new install of laravel 7.3.3 and vue.js 2.6.12 can not get the vue devtools extension to show me my components, variables etc.
This is what the devtools look like :
Here is the repo : https://github.com/yex777/pa-hub
Thanks for any help!
I had a similar issue with my repo. I don't actually register components globally, I instead make components and just register them on the page they are needed. My issue with this was caused because I was binding Vue to the page twice. Once in app.js and then again in my custom JS file for my component. As such, I think the dev tools was picking up the wrong Vue instance.
I resolved my issue by removing the references to vue in my app.js file and then only binding elements using my new JS file. So my app.js file only contains
require('./bootstrap');
and then I have a separate file which I include on the relevant page which looks a little like this:
import Vue from 'vue';
import Axios from 'axios';
import StudentManagement from './StudentManagement.vue';
window.axios = Axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
new Vue({ // eslint-disable-line no-undef, no-new
el: '#student-management',
render: h => h(StudentManagement),
});
I suspect you may have a similar issue where the Vue instance is being setup twice.
The easiest way to check is in the console, it will output a message saying that Vue is in development mode:
As you can see, it's got a 2 next to the message, saying the message has been output twice. If this is the case, you just need to make sure you only include or set up your Vue instance once and the dev tools should pickup your components.

How do I put Vue chunk files in public/js with Laravel Mix?

I have a Laravel and Vue project in which I'm using dynamic import function calls in the Vue to chunk my components into separate files.
Everything's working fine, but the Vue chunk files (e.g., 0.js, 1.js, etc.) are being placed directly under the public directory, instead of under public/js, which is where app.js is.
Here is my Laravel Mix file:
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js/')
.sass('resources/sass/vendor.scss', 'public/css/')
.sass('resources/sass/app.scss', 'public/css/')
.version();
What do I need to change/add to get the Vue chunk files to be automatically placed within public/js when I build every time, instead of directly under the public directory? Thanks.
You can add the path in webpack like following
mix.webpackConfig({
output: {
chunkFilename: 'js/chunks/[name].js',//replace with your path
},
});
See this GitHub issue for more information

Why does Laravel Mix's extract method cause Sass to not compile in this case?

I have a Laravel project using Laravel Mix, Vue.js and Sass.
The following is the content of the webpack.mix.js file in the project:
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.extract(['vue'])
.sass('resources/sass/vendor.scss', 'public/css/')
.sass('resources/sass/app.scss', 'public/css/');
This Mix file is properly compiling all the CSS and JS assets for me when I import all of my Vue components into a master Vue component called App as follows:
// Layout
import SiteFooter from './layout/SiteFooter';
import SiteHeader from './layout/SiteHeader';
// Pages
import Home from './pages/Home';
// And many more here...
export default {
components: {
SiteFooter,
SiteHeader,
// Pages
Home,
// etc...
}
However, as I started to create a lot of components. app.js started to get too big, so then I switched to loading the components in App asynchronously as follows:
// Layout
import SiteFooter from './layout/SiteFooter';
import SiteHeader from './layout/SiteHeader';
export default {
components: {
SiteFooter,
SiteHeader,
// Pages
Home: () => import('./pages/Home'),
// And many more here...
This perfectly achieved the goal of reducing the size of app.js and breaking the components up into separate files, which is great, but as soon as I did this, the Sass stopped compiling into app.css and vendor.css files, and I had no styles on the site.
I played around for a bit and realized that if I removed the extract(['vue']) line from webpack.mix.js, then the Sass would correctly compile again and the styles would display correctly, but then app.js would increase in size by about 330k because of the inclusion of the Vue code.
What I'm wondering is: Why does having the extract(['vue']) method call in the Mix file along with using asynchronous components in Vue cause the Sass to not be compiled, and more importantly, is there a way to pull the Vue code out into a separate vendor.js file as well as get the Sass to properly compile when Vue components are asynchronously loaded? Thank you.

How to add a Vue component to the file app.js in laravel?

I was watching a tutorial that uses laravel and vue and on the tutorial he add a vue component in the components folder and then register that component in app.js file using this code
Vue.component('articles',require('./components/articles.vue');
And it works fine and in my case when I use this code it says require is not defined.
In the app.js file theres already an example component registered using this code
Vue.component('example-component',__webpack_require__(37));
My question is how does the number 37 define the ExampleComponent.vue file? And how can I get the number of the file i want to include? And I don't have the webpack CLI
Thanks
Its looks like i have been using the wrong app.js file which was in the public directory i should be adding these codes to the app.js which sits in the components directory
You should try
import YourComponent from 'path';
new Vue({
components: {
"your-component": YourComponent
});

Laravel mix .extract method

Hi I am using laravel mix with my Laravel 5.5
I have my mix file like this:
/* Production settings */
if (mix.inProduction()) {
mix.version();
mix.disableNotifications();
}
/* Sass Processing */
mix.sass('resources/assets/sass/_bootstrap.scss', 'public/css/bootstrap.css');
mix.sass('resources/assets/sass/navigation.scss', 'public/css/navigation.css');
mix.sass('resources/assets/sass/global.scss', 'public/css/global.css').options({
processCssUrls: false
});
mix.sass('resources/assets/sass/cards.scss', 'public/css/cards.css')
.sass('resources/assets/sass/forms.scss', 'public/css/forms.css')
.sass('resources/assets/sass/search.scss', 'public/css/search.css')
.sass('resources/assets/sass/profile.scss', 'public/css/profile.css')
.sass('resources/assets/sass/event.scss', 'public/css/event.css')
.sass('resources/assets/sass/entity.scss', 'public/css/entity.css')
.sass('resources/assets/sass/travel.scss', 'public/css/travel.css')
.sass('resources/assets/sass/sliders.scss', 'public/css/sliders.css')
.sass('resources/assets/sass/login.scss', 'public/css/login.css');
mix.styles([
'resources/assets/css/bootstrap-social.css',
'resources/assets/css/dropzone.css',
'resources/assets/css/jquery-ui.css',
'resources/assets/css/jquery-ui.structure.css',
'resources/assets/css/jquery-ui.theme.css',
'resources/assets/css/font-awesome.css',
'resources/assets/css/animate.css',
], 'public/css/style.css');
/* Global JS */
mix.scripts([
'resources/assets/js/pace.js',
'resources/assets/js/jquery.js',
'resources/assets/js/page-load.js',
'resources/assets/js/bootstrap.js',
'resources/assets/js/jquery-ui.js',
'resources/assets/js/favourites.js',
], 'public/js/global.js');
mix.js('resources/assets/js/dropzone.js', 'public/js/dropzone.js');
mix.js('resources/assets/js/image-upload.js', 'public/js/image-upload.js');
mix.js('resources/assets/js/googlemap.js', 'public/js/googlemap.js');
mix.js('resources/assets/js/entity.js', 'public/js/entity.js');
mix.js('resources/assets/js/validation.js', 'public/js/validation.js');
mix.js('resources/assets/js/search.js');
mix.js('resources/assets/js/homesearch.js', 'public/js/homesearch.js');
mix.js('resources/assets/js/instantsearch.js', 'public/js/instantsearch.js');
mix.js('resources/assets/js/featured.js', 'public/js/featured.js');
mix.js('resources/assets/js/tram.js', 'public/js/tram.js');
mix.js('resources/assets/js/counter.js', 'public/js/counter.js');
What I wanted to do is use the extract method as mentioned in documentation:
Vendor Extraction - One potential downside to bundling all application-specific JavaScript with your vendor libraries is that it
makes long-term caching more difficult. For example, a single update
to your application code will force the browser to re-download all of
your vendor libraries even if they haven't changed.
If you intend to make frequent updates to your application's
JavaScript, you should consider extracting all of your vendor
libraries into their own file. This way, a change to your application
code will not affect the caching of your large vendor.js file. Mix's
extract method makes this a breeze:
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['vue'])
The extract method accepts an array of all libraries or modules that
you wish to extract into a vendor.js file. Using the above snippet as
an example, Mix will generate the following files:
public/js/manifest.js: The Webpack manifest runtime
public/js/vendor.js: Your vendor libraries
public/js/app.js: Your application code To avoid JavaScript errors, be sure to load these files in the proper order:
<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/app.js"></script>
So I have created an empty file in: resources/assets/js/app.js and in my webpack:
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['jquery', 'bootstrap', 'pace'])
Everything is being processed successfully, I attached all the files. app.js seems to have required content however when I get to the page apparently jquery is not being defined.
What could be the cause? I have installed bootstrap, jquery, and pace throught npm.
With vue, jquery plugins have certain conflict
https://vuejsdevelopers.com/2017/05/20/vue-js-safely-jquery-plugin/

Resources