Laravel mix .extract method - laravel

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/

Related

Laravel Vue Non SPA - How to split the files for every page for its vue js components?

My application is using laravel vue but not SPA,.. so im still using laravel blades to separate the pages. Every page are importing app.js. My App.js is compiled by webpack and all my vue components are compiled on that file. so the problem is the app.js getting MB size and the every page will slow to load that file. Is their way to split the code of vuejs or separate the file for every pages using webpack?
this is my webpack.js in my web application.
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.setPublicPath('public')
.setResourceRoot('../') // Turns assets paths in css relative to css file
// .options({
// processCssUrls: false,
// })
.sass('resources/sass/frontend/app.scss', 'css/frontend.css')
.sass('resources/sass/backend/app.scss', 'css/backend.css')
.js('resources/js/frontend/app.js', 'js/app.js')
.js([
'resources/js/backend/before.js',
'resources/js/backend/app.js',
'resources/js/backend/after.js'
], 'js/backend.js')
.extract([
// Extract packages from node_modules to vendor.js
'jquery',
'bootstrap',
'popper.js',
'axios',
'sweetalert2',
'lodash'
])
.sourceMaps();
if (mix.inProduction()) {
mix.version()
.options({
// Optimize JS minification process
terser: {
cache: true,
parallel: true,
sourceMap: true
}
});
} else {
// Uses inline source-maps on development
mix.webpackConfig({
devtool: 'inline-source-map'
});
}
My laravel is using laravel boiler plate template and he separated the other files into vender.js. And my problem is the app.js getting biggger size and it will hard to load for the users have slower connection.
As far as I know, the best you can do is that using Dynamic Imports, laravel-mix internally uses webpack code-splitting and it's included out of the box by the latest version of laravel-mix.
Add this to your webpack.mix.js file
mix.babelConfig({
plugins: ['#babel/plugin-syntax-dynamic-import'],
});
And also you need to change how you import your components.
// Standard import
import StandardComponent from './components/ExampleComponent.vue';
// Dynamic import
const DynamicallyImportedComponent =
() => import('./components/ExampleComponent.vue');
By doing this way laravel-mix will compile the component in a separate file. And dynamically insert the file in your html head section. So will only insert the file if it is needed.
Webpack will split the dynamically imported files into chunks and name them 0.js, 1.js, etc. If you want to configure the chunk name for a file, you need to add a “magic” comment to the import statement to tell Webpack the name you want to use. Just like how you would do it in a webpack setup. Like:
const DynamicallyImportedComponent =
() => import(/* webpackChunkName: "dynamically-imported-component" */ './components/ExampleComponent.vue');

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 can I prerender a subset of my laravel+vue application?

I have a laravel application with my front-end written in Vuejs. I want to prerender the public pages only. What is the correct configuration for the prerender-spa-plugin to do this?
Most tutorials on the web show how to do it for the whole website, but I need only few pages pre-rendered. I must be missing something but I get only a blank page and my javascript is not loaded during the prerendering. I am not using vue router.
const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin')
// In the mix webpack config -
plugins: [
...
new PrerenderSPAPlugin({
// Required - The path to the webpack-outputted app to prerender.
staticDir: path.join(__dirname, 'static'),
// Required - Routes to render.
routes: [ '/' ],
})
]
Error message: Unable to prerender all routes!
The javascript/vue files etc for the static part should all be in the static directory. It won't work if they are in the folder you normally use for organizing the rest of your application.
You need to use HTMLwebpackPlugin to copy over the html to the output directory (say, in public). Mix's copy happens too late. Chunks will help get only the js files you want.

Compile Laravel Vue components into different js files

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.

Resources