I have an application that I developed with Laravel vue2. My app works fine when I run it with npm run prod. Since I want to do SSR, I added inertia and edited the codes below, but styles are not working in my application and I cannot import anything.
My steps to start the project;
npm run prod
npx mix --mix-config=webpack.ssr.mix.js
node public/js/ssr.js
Error in browser -
Error in console
app.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src="{{ asset('js') }}/manifest.js" type="text/javascript"></script>
<script src="{{ asset('js') }}/vendor.js" type="text/javascript"></script>
<script src="{{ asset('js') }}/app.js" type="text/javascript"></script>
#inertiaHead
</head>
<body>
#inertia
</body>
</html>
app.js
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import VueSweetalert2 from 'vue-sweetalert2';
import 'sweetalert2/dist/sweetalert2.min.css';
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import MaterialKit from "./plugins/material-kit";
import VueParticles from 'vue-particles'
Vue.use(VueParticles)
Vue.use(MaterialKit);
Vue.use(VueSweetalert2);
Vue.config.productionTip = false;
import('./assets/css/style.css');
const NavbarStore = {
showNavbar: false
};
Vue.mixin({
data() {
return {
NavbarStore
};
}
});
new Vue({
router,
render: h => h(App)
}).$mount("#app");
ssr.js
import Vue from 'vue'
import { createRenderer } from 'vue-server-renderer'
import { createInertiaApp } from '#inertiajs/inertia-vue'
import createServer from '#inertiajs/server'
createServer((page) => createInertiaApp({
page,
render: createRenderer().renderToString,
resolve: name => require(`./views/${name}`),
setup({ app, props, plugin }) {
console.log(page)
console.log(plugin)
console.log(props)
Vue.use(plugin)
return new Vue({
render: h => h(app, props),
})
},
}))
webpack.mix.js
const mix = require('laravel-mix');
mix.js('resources/js/app.js', 'public/js')
.vue()
.disableSuccessNotifications()
.extract(['vue', 'vue-router', 'axios', 'vue-sweetalert2', 'vue-lazyload', 'vue-carousel', 'vue-material']);
webpack.ssr.mix.js
const path = require('path')
const mix = require('laravel-mix')
const webpackNodeExternals = require('webpack-node-externals')
mix
.options({ manifest: false })
.js('resources/js/ssr.js', 'public/js')
.vue({ version: 2, options: { optimizeSSR: true }, useVueStyleLoader: true},)
.alias({ '#': path.resolve('resources/js') })
.webpackConfig({
target: 'node',
externals: [webpackNodeExternals()],
}).extract(['vue', 'vue-router', 'axios', 'vue-sweetalert2', 'vue-lazyload', 'vue-carousel', 'vue-material']);
Try add to .webpackConfig({... , useVueStyleLoader: true})
Related
I'm new to Vue and Inertia Js, so far I understand that in Inertia, u can call Vue components with layouts, like navbar and sidebar etc.
but what I'm trying to achieve is to create a layout of the whole app, that consists of multiple vue files for example like this,
<template>
<NavbarVue/>
<Home/>
<Kenapa/>
<Cerita/>
<Karir/>
<Lowongan/>
<Media/>
<Gabung/>
<Mitra/>
<Download/>
<Footer/>
</template>
<script setup lang="ts">
import NavbarVue from '../components/Navbar.vue';
import Home from '../pages/Home.vue';
import Media from '../pages/Media.vue';
import Kenapa from '../pages/Kenapa.vue';
import Cerita from '../pages/Cerita.vue';
import Lowongan from '../pages/Lowongan.vue';
import Karir from '../pages/Karir.vue';
import Gabung from '../pages/Gabung.vue';
import Mitra from '../pages/Mitra.vue';
import Download from '../pages/Download.vue';
import Footer from '../components/Footer.vue';
</script>
In vue.js, I can create a layout for the app like that, by creating a template for different vue files like Home page, Kenapa page etc.
But in Inertia Js, this is the app.js file
import './bootstrap';
import '../css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '#inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.m';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, App, props, plugin }) {
return createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue, Ziggy)
.mount(el);
},
progress: {
color: '#4B5563',
},
});
What should I do to achieve that ?
You must use a persistent layout for that.
Layout.vue
<template>
<div>
<Navbar />
<slot /> <!-- Don't forget this -->
<Footer />
</div>
</template>
<script setup lang="ts">
import Navbar from '../components/Navbar.vue';
import Footer from '../components/Footer.vue';
</script>
MyPage.vue
<script>
import Layout from './Layout'
export default {
layout: Layout,
}
</script>
<script setup>
defineProps({ user: Object })
</script>
<template>
<H1>My Page</H1>
<p>Hello {{ user.name }}, welcome to my page!</p>
</template>
I try use stack Laravel + Inertiajs + Vue3. I would like to use the ziggy library to build routes.
And my error in browser console:
Uncaught (in promise) TypeError: _ctx.$route is not a function
Laravel successful
Inertiajs successful
Vue3 successful
Next i install Ziggy
composer require tightenco/ziggy.
my app.js
require('./bootstrap');
import { createApp, h } from 'vue'
import { createInertiaApp } from '#inertiajs/inertia-vue3'
import { InertiaProgress } from '#inertiajs/progress'
import { ZiggyVue } from 'ziggy';
InertiaProgress.init()
createInertiaApp({
resolve: name => require(`./Pages/${name}`),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin, ZiggyVue)
.mount(el)
},
})
console.log(route('test'))
my webpack.mix.js
const mix = require('laravel-mix');
const path = require('path');
mix.alias({
ziggy: path.resolve('vendor/tightenco/ziggy/dist/vue'),
});
mix.js('resources/js/app.js', 'public/js').vue()
.postCss('resources/css/app.css', 'public/css', [
require('tailwindcss'),
]);
my root blade:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<link href="{{ mix('/css/app.css') }}" rel="stylesheet" />
#routes
<script src="{{ mix('/js/app.js') }}" defer></script>
#inertiaHead
</head>
<body>
#inertia
</body>
</html>
my vue page Pages/Home.vue
<template>
<Head title="Welcome" />
<h1 class="text-9xl">Welcome</h1>
<p>Hello, welcome to your first Inertia app!</p>
<br>
<InertiaLink :href="$route('test')">Test</InertiaLink>
</template>
<script>
import { Head } from '#inertiajs/inertia-vue3'
export default {
components: {
Head,
},
}
</script>
Screen my error page
I will be grateful for help
If you're using Laravel with the Ziggy library, you have a global route() function helper available for you automatically.
Using Ziggy with Vue/Inertia, it's helpful to make this function available as a custom $route property so you can use it directly in your templates.
Option 1:
app.config.globalProperties.$route = route
Option 2:
createApp(App)
.use({
install(app) {
// eslint-disable-next-line no-undef
app.config.globalProperties.$route = route;
},
})
Use:
Create User
In app.js-
import route from 'ziggy'
import { ZiggyVue } from './ziggy'
createInertiaApp({
resolve: name => require(`./Pages/${name}`),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin) // Change this
.mixin({ methods: { route } }) // Add this
.mount(el)
},
})
this is my webpack.mix.js
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel applications. By default, we are compiling the CSS
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js').vue()
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
])
.webpackConfig(require('./webpack.config'));
if (mix.inProduction()) {
mix.version();
}
this is my app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&display=swap">
<!-- Styles -->
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
<!-- Scripts -->
#routes
<script src="{{ mix('js/app.js') }}" defer></script>
</head>
<body class="font-sans antialiased">
#inertia
#env('local')
<script src="http://localhost:3000/browser-sync/browser-sync-client.js"></script>
#endenv
</body>
</html>
this is my web.php
<?php
use App\Http\Controllers\GoogleAuthController;
use App\Http\Controllers\KakaoAuthController;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/asdasd', function () {
return Inertia::render('Newpop');
});
Route::get('/', function () {
return view('welcome');
});
Route::post('/', function () {
return view('welcome');
});
Route::middleware(['auth:sanctum', 'verified'])->get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
Route::get('/kakao/login', [KakaoAuthController::class, 'redirect'])->name('kakao.login');
Route::get('/kakao/callback', [KakaoAuthController::class, 'callback']);
Route::get('/github/login', [GithubAuthController::class, 'redirect'])->name('github.login');
Route::get('/github/callback', [GithubAuthController::class, 'callback']);
Route::get('/google/login', [GoogleAuthController::class, 'redirect'])->name('google.login');
Route::get('/google/callback', [GoogleAuthController::class, 'callback']);
this is my Newpop.vue (it is in js/Pages folder)
<template>
<div>asdasddsdadzz</div>
</template>
<script>
export default {};
</script>
this is my app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue').default;
import {
InertiaApp
} from '#inertiajs/inertia-vue'
Vue.use(InertiaApp)
new Vue({
render: h => h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: name => import(`./Pages/${name}`).then(module => module.default),
},
}),
}).$mount(app)
/**
* The following block of code may be used to automatically register your
* Vue components. It will recursively scan this directory for the Vue
* components and automatically register them with their "basename".
*
* Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
*/
// const files = require.context('./', true, /\.vue$/i)
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default))
Vue.component('example-component', require('./components/ExampleComponent.vue').default);
Vue.component('example-two', require('./components/ExampleTwo.vue').default);
Vue.component('hu-hu', require('./components/HuHu.vue').default);
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
const app = new Vue({
el: '#app',
});
// require('./bootstrap');
import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
import "tailwindcss/tailwind.css"
import {
InertiaProgress
} from '#inertiajs/progress'
createInertiaApp({
resolve: name => import(`./Pages/${name}`),
setup({
el,
App,
props
}) {
new Vue({
render: h => h(App, props),
}).$mount(el)
},
})
InertiaProgress.init()
when i starts php artisan serve,
my page shows only #routes.
i had changed app.js or webpack.mix.js like inertia documentation but it doesn't work.
my other vue pages (not using inertia, using js fronend scaffolding) works well.
how can i use inertia component in my project?
I'm trying to install Vuetify on the latest Laravel versione (8) but I cannot do it. Seems it doesn't work even if the console doesn't show me any error.
That's my resource/plugins/vuetify.js
import Vue from 'vue'
// import Vuetify from 'vuetify'
import Vuetify from 'vuetify/lib'
// import 'vuetify/dist/vuetify.min.css'
Vue.use(Vuetify)
const opts = {}
export default new Vuetify(opts)
My webpack.mix.js :
const mix = require('laravel-mix')
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
mix
.js('resources/js/app.js', 'public/js')
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
])
.webpackConfig({
plugins: [
new VuetifyLoaderPlugin()
],
})
.browserSync('tb8.test');
The app.js
import PortalVue from 'portal-vue';
Vue.use(InertiaApp);
Vue.use(InertiaForm);
Vue.use(PortalVue);
Vue.use(vuetify);
const app = document.getElementById('app');
new Vue({
vuetify,
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
and the welcome.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght#400;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Nunito';
}
</style>
</head>
<body class="antialiased">
<div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
#if (Route::has('login'))
<div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
#auth
Dashboard
#else
Login
#if (Route::has('register'))
Register
#endif
#endif
</div>
#endif
<v-app>
<v-main>
Hello World
</v-main>
</v-app>
</div>
</body>
</html>
Can anyone help me to find where is the mistake?
Thank you in advance
Valerio
Fresh Laravel 8.12 + Jetstream + Inertia + VueJs + Vuetify
add to header the string of style in /resources/views/app.blade.php
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
add to /resources/js/app.js
import Vuetify from 'vuetify';
import 'vuetify/dist/vuetify.min.css';
Vue.use(Vuetify)
and
vuetify: new Vuetify(), after 'new Vue({' like this:
require('./bootstrap');
import Vue from 'vue';
import Vuetify from 'vuetify';
import { InertiaApp } from '#inertiajs/inertia-vue';
import { InertiaForm } from 'laravel-jetstream';
import PortalVue from 'portal-vue';
import 'vuetify/dist/vuetify.min.css';
Vue.mixin({ methods: { route } });
Vue.use(InertiaApp);
Vue.use(InertiaForm);
Vue.use(PortalVue);
Vue.use(Vuetify)
const app = document.getElementById('app');
new Vue({
vuetify: new Vuetify(),
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
After that, for example, you can create your vuetify component like this:
/resources/js/Components/NavigationDrawers.vue with code from Vuetify labrory
init this vue-component in /resources/js/Pages/Dashboard.vue like
<navigation-drawers/>
with call
import NavigationDrawers from '#/Components/NavigationDrawers'
and
NavigationDrawers
in <script>
Example:
<template>
<app-layout>
<navigation-drawers/>
....
....
</app-layout>
</template>
<script>
import NavigationDrawers from '#/Components/NavigationDrawers'
import AppLayout from '#/Layouts/AppLayout'
import Welcome from '#/Jetstream/Welcome'
export default {
components: {
AppLayout,
Welcome,
NavigationDrawers,
},
}
</script>
It is help you for setting vuetify to your project.
Sass and other config you can config self.
a screenshot example Navigation Drawer
a screenshot example Navigation Drawer two
Currently Vuetify does not work with vue 3, so to install vuetify you have to go with vue 2. to do so:
we can install jetstream 2.1 which comes with vue 2. I have described installation process below:
Youtube video: https://youtu.be/V8_yLfNhg2I
To install laravel
composer create-project laravel/laravel project_name
Now go to composer.json file and inside require:{} add just one line and rest of composer file should be same.
"laravel/jetstream": "2.1",
after adding that "require" section of composer.json would look something like this:
"require": {
"php": "^7.3|^8.0",
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^8.40",
"laravel/tinker": "^2.5",
"laravel/jetstream": "2.1",
},
Now run composer update
Now run php artisan jetstream:install inertia
Now run npm install
Now run npm install vuetify
Go to resources/css/app.css and add following
#import url('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900');
#import url('https://cdn.jsdelivr.net/npm/#mdi/font#5.x/css/materialdesignicons.min.css');
#import "vuetify/dist/vuetify.min.css";
Now go to resources/js/app.js and add following code:
require('./bootstrap');
// Import modules...
import Vue from 'vue';
import { App as InertiaApp, plugin as InertiaPlugin } from '#inertiajs/inertia-vue';
import PortalVue from 'portal-vue';
//add these two line
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
Vue.mixin({ methods: { route } });
Vue.use(InertiaPlugin);
Vue.use(PortalVue);
//also add this line
Vue.use(Vuetify);
const app = document.getElementById('app');
new Vue({
//finally add this line
vuetify: new Vuetify(),
render: (h) =>
h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: (name) => require(`./Pages/${name}`).default,
},
}),
}).$mount(app);
Now run npm run dev
At this moment your vuetify will work!
To check whether vuetify with inertia js is working or not please follow:
Go to resources/js/Pages and create new file name test.vue
Add following code to test.vue
<template>
<v-app>
<v-container>
<v-btn>Click Me!</v-btn>
</v-container>
</v-app>
</template>
Now run npm run dev
Now go to route/web.php and add
Route::get('/', function () {
return Inertia::render('test');
});
Now php artisan serve to run in browser. and don't forget to add migrate and add database to .env
Vuetify now has a Vue 3 branch (at the time of writing still in beta) The point about the clash with tailwind still stands although the problem is mostly manifests its self in terms of file size (of the css) Anyway to get things working in an install of Laravel (9) and Jetstream with Inertia you need to add vuetify
npm install vuetify#^3.0.7 --save
Then edit resources/js/app.js
by adding:
// Vuetify
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
const vuetify = createVuetify({
components,
directives,
})
and in the same file amending the createInertiaApp function set up so that Vue uses Vuetify
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
setup({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
...
.use(vuetify)
...
},
});
You will then be able to use Vuetify components. You will probably want to set your own colours. There are two options SASS or javascript
here is an example of the Javascript option
const vuetify = createVuetify({
theme: {
themes: {
light: {
dark: false,
colors: {
primary: "#415e96",
secondary: "#b89acc"
}
},
},
},
components,
directives,
}
)
More on this here
Here is an (untested by me) article on removing the collisions between tailwind and Vuetify
When I changed mode to history, the hash from the URL is removed, but components are not loading. This is app.js:
window.Vue = require('vue');
import VueRouter from 'vue-router';
var index = Vue.component('index',
require('./components/frontend/testingIndexComponent.vue'));
var component1 = Vue.component('component1',
require('./components/frontend/testingComponent.vue'));
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: index },
{ path: '/component1', component: component1 }
]
})
const app = new Vue({
router
}).$mount('#app')
this is web.php
Route::get('/{vue_capture?}', function () {
return view('index4');
})->where('vue_capture', '[\/\w\.-]*');
this is index4.blade.php
<body>
<div>
<h1>Header</h1>
<!-- <a><router-link tag="li" to="projects">
sdds
</router-link></a> -->
</div>
<div id="app">
<a><router-link to="component1">
sddsdadadssa
</router-link></a>
<router-view>
</router-view>
</div>
<div>
<h1>Footer</h1>
</div>
<script type="text/javascript" src="{{URL::to('public/js/app.js')}}">
</script>
remove
mode: 'history'
and use
hashbang: false,
history: true
instead