How can I prerender a subset of my laravel+vue application? - laravel

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.

Related

Weird "#/" at the end of URL locally

I am messing around locally with a laravel and vue project, I also have vue-router setup but my URL look like this: <virtual-host>.loc/#/.
Whenever I access my v-host it loads but I get this weird #/ thing appended to the end of the URL. Does anybody know where it comes from? Is it a JS thing?
by default vue js use hash mode. that's why you see that type of url. to change this behavior you need to set mode property to history like this,
const router = new VueRouter({
mode: 'history',
routes: [...]
})

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 to properly connect Nuxt.js with a laravel backend?

I am starting a new project, Nuxt.js for the frontend and Laravel for the backend.
How can I connect the two?
I have installed a new Nuxt project using create-nuxt-app, and a new laravel project.
As far as I have searched, I figured I need some kind of environment variables.
In my nuxt project, I have added the dotenv package and placed a new .env file in the root of the nuxt project.
And added CORS to my laravel project, as I have been getting an error.
The variables inside are indeed accessible from the project, and im using them
like this:
APP_NAME=TestProjectName
API_URL=http://127.0.0.1:8000
And accessing it like this:
process.env.APP_NAME etc'
To make HTTP calls, I am using the official Axios module of nuxt.js, and to test it i used it in one of the components that came by default.
The backend:
Route::get('/', function () {
return "Hello from Laravel API";
});
and from inside the component:
console.log(process.env.API_URL)//Gives 127.0.0.1:8000
//But this gives undefined
this.$axios.$get(process.env.API_URL).then((response) => {
console.log(response);
});
}
What am I doing wrong here?
I have tried to describe my setup and problem as best as I can. If I overlooked something, please tell me and I will update my question. Thanks.
Taking for granted that visiting https://127.0.0.1:8000/ in your browser you get the expected response, lets see what might be wrong in the front end:
First you should make sure that axios module is initialized correctly. Your nuxt.config.js file should include the following
//inclusion of module
modules: [
'#nuxtjs/axios',
<other modules>,
],
//configuration of module
axios: {
baseURL: process.env.API_URL,
},
Keep in mind that depending on the component's lifecycle, your axios request may be occurring in the client side (after server side rendering), where the address 127.0.0.1 might be invalid. I would suggest that you avoid using 127.0.0.1 or localhost when defining api_uris, and prefer using your local network ip for local testing.
After configuring the axios module as above, you can make requests in your components using just relative api uris:
this.$axios.$get('/').then(response => {
console.log(response)
}).catch(err => {
console.error(err)
})
While testing if this works it is very helpful to open your browser's dev tools > network tab and check the state of the request. If you still don't get the response, the odds are that you'll have more info either from the catch section, or the request status from the dev tools.
Keep us updated!
Nuxt has a routing file stucture to make it easy to set up server side rendering but also to help with maintainability too. This can cause Laravel and Nuxt to fight over the routing, you will need to configure this to get it working correctly.
I'd suggest you use Laravel-Nuxt as a lot of these small problems are solved for you.
https://github.com/cretueusebiu/laravel-nuxt

How to add Vue-donut-chart library to Vuepress?

I'm trying to add a chart using this Vue library. I added the dependencies into the Config file. The library asks us to use Vue.use(). But I get Vue is undefined. Any ideas?
https://vuejsexamples.com/lightweight-vue-component-for-drawing-pure-css-donut-charts/
Please use the App Level Enhancments
https://vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements
Belowe text is copied from Vuepress documentation:
App Level Enhancements
Since the VuePress app is a standard Vue app, you can apply app-level enhancements by creating a file .vuepress/enhanceApp.js, which will be imported into the app if it is present. The file should export default a hook function which will receive an object containing some app level values. You can use this hook to install additional Vue plugins, register global components, or add additional router hooks:
export default ({
Vue, // the version of Vue being used in the VuePress app
options, // the options for the root Vue instance
router, // the router instance for the app
siteData // site metadata
}) => {
// ...apply enhancements to the app
}

Removing # from url is showing me 404 after page refresh, I am using Vue Js in Laravel Application

I am developing a laravel(5.4) application in which i am using vue js(2.0) for SPA, my problem is i want to remove #(hash) from URL.
please suggest me any solution?
This is my HTML
<ul class="category-list">
<li><router-link to="/testlink.html">Tets Link</router-link></li>
<li><router-link to="/demotestlink.html">Demo Test LInk</router-link></li>
</ul>
This is my vue js code
export default new VueRouter({
[
{
path: '/testlink.html',
component:require('./components/demo/Testlink')
}
],
mode: 'history',
});
and i have made a Testlink.vue file inside components/demo folder in Assets
Note: FYI, I am using vue.js(2.0) in Laravel(5.4) Application
From Vue-Router documentation, I found this.
The default mode for vue-router is hash mode - it uses the URL hash to simulate a full URL so that the page won't be reloaded when the URL changes.
To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload:
const router = new VueRouter({
mode: 'history',
routes: [...]
})
I tried the above and it worked fine for me. For more information read here

Resources