I am trying to make PWA of my Vue/Laravel app. The problem I am facing is my manifest.json file is not linked to my production build head. On my development it's working fine, browser is detecting the manifest.json but not on server.
I have linked the manifest.json to my app.blade.php file but on production server when I see the source code there is no manifest.json attached.
Here 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">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
<link rel="manifest" href="manifest.json" />
<title>{{env('APP_NAME')}}</title>
</head>
<body class="antialiased">
<div id="app"></div>
<script src="{{ asset('js/main.js') }}"></script>
</body>
</html>
My webpack.mix.js configs are
const mix = require('laravel-mix');
const path = require('path');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
/*
|--------------------------------------------------------------------------
| 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.ts('resources/js/main.ts', 'public/js')
.vue({ version: 3 })
.postCss('resources/css/app.css', 'public/css', [
//
])
.sourceMaps();
mix.browserSync('http://localhost/');
mix.webpackConfig(module.exports = {
resolve: {
alias: {
'#/pages': path.resolve(__dirname, './resources/js/pages'),
'#/assets': path.resolve(__dirname, './resources/js/assets'),
},
},
});
mix.webpackConfig({
plugins: [
new WebpackManifestPlugin(),
new WebpackPwaManifest({
name: "DC",
short_name: "DC",
start_url: "/",
display: "standalone",
theme_color: "#004c97",
background_color: "#fff",
icons: [
{
"src": path.resolve(__dirname, './resources/js/assets/images/logo-pwa.png'),
"sizes": "256x256",
"type": "image/png"
}
],
id: "/#/login",
filename: 'manifest.json',
publicPath: '/',
basePath: '/public',
}),
],
});
mix.options({
hmrOptions: {
host: 'localhost',
port: 8000
}
})
Remember, it's working fine on development but not working on production.
Here is my production output
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="irPGXqkRHKDYOBD1G0rPYsNp0Iwu881BIeCbmBfo"/>
<title>Abc</title>
</head>
<body class="antialiased">
<div id="app"></div>
<script src="https://xxxx/js/main.js"></script>
</body>
</html>
As you can see, there is no manifest file attached here
After spending hours i finally able to resolve this issue by replacing assets with mix in app.blade.php here is my latest file
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}"/>
<link rel="manifest" href="{{ mix('/pwa/manifest.json') }}" />
<title>{{env('APP_NAME')}}</title>
</head>
<body class="antialiased">
<div id="app"></div>
<script src="{{ mix('/js/main.js') }}"></script>
</body>
</html>
Related
To be honest, I'm having trouble understanding the concept of Laravel how to build in and use its assets (css, js). I guess I'm using a wrong but still working way even for production.
My approach for Production
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
],
});
Step 1: npm run build
Step 2: Manually copy the newly generated js and css files into my public folder.
Step 3: Change the file names in my bladetemplate. So app.11111.js to app.js
Note: This doesn't feel right but it worked for Production. I would be very grateful for any hints on this.
Here is my layout.blade.php file
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="stylesheet" href="https://fonts.bunny.net/css2?family=Nunito:wght#400;600;700&display=swap">
<link rel="stylesheet" href="{{ asset('assets/css/main.css') }}">
<!-- Scripts -->
#vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100" style="min-height: 100vh; display:flex; flex-direction:column;">
#include('layouts.navigation')
<!-- Page Content -->
<main>
#yield('content')
</main>
#include('templateparts.footer')
</div>
<script src="{{ asset('assets/js/app.js') }}"></script>
</body>
</html>
I am trying to run my application via a tunnel service (https://localtunnel.github.io/www/), but it sets the relative path to local which makes it so that my assets can't get loaded.
What I have tried:
changing the mix helper to the assets helper -> works, but makes me unable to use the npm hot reload function. I would like to make use of this.
My blade file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{csrf_token()}}">
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
<title>Laravel Vue Ecommerce</title>
<link href=" {{ mix('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<app></app>
</div>
<script src="{{ mix('js/bootstrap.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>
</body>
</html>
webpack.mix.js:
mix.js('resources/js/app.js', 'public/js').vue()
.sass('resources/sass/app.scss', 'public/css')
.sourceMaps()
The errors:
GET https://localhost:8080/css/app.css net::ERR_BLOCKED_BY_CLIENT
tame-dog-60.loca.lt/:16
GET https://localhost:8080/js/bootstrap.js net::ERR_BLOCKED_BY_CLIENT
tame-dog-60.loca.lt/:17
GET https://localhost:8080/js/app.js net::ERR_BLOCKED_BY_CLIENT
I have just done a fresh install of inertia on an app with vuejs (v2) and am getting this error:
[Vue warn]: Do not mount Vue to <html> or <body> - mount to normal elements instead.
But I don't see why it's trying to mount on those elements? As far as I can tell I've followed the inertia installation guide....
web.php
Route::get('test', function(){return \Inertia\Inertia::render('master');});
app-ihf.js
import { App, plugin } from '#inertiajs/inertia-vue'
import Vue from 'vue'
import { InertiaProgress } from '#inertiajs/progress'
Vue.use(plugin)
const el = document.getElementById('app')
new Vue({
render: h => h(App, {
props: {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: name => require(`./Pages/${name}`).default,
},
}),
}).$mount(el)
InertiaProgress.init()
master.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app-ihf.css">
<script src="{{ mix('/js/app-ihf.js') }}"></script>
</head>
<body>
#inertia
</body>
</html>
Can anyone see what's going wrong here? This is the html when you visit that route
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app-ihf.css?id=fc17ae1fae0b57440a59">
<script src="/js/app-ihf.js?id=fa7eba2a2c660c498a3e"></script>
</head>
<body>
<div id="app" data-page="{"component":"master","props":{"errors":{}},"url":"\/test","version":"3993c0d73e25e92aa0e15607a6c438ef"}"></div>
</body></html>
I had the exact same issue and it's because I didn't put defer into the script tag so the JavaScript in app.js was running before the id="app" element existed on the page.
So in your case you need:
<script src="{{ mix('/js/app-ihf.js') }}" defer></script>
I have laravel/VueJs app which is supporting multiple language but there is one issue, when I change language on VueJs html Lang tag will not change.
Code
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="csrf-token" content="{{ csrf_token() }}" />
<title>{{ config('app.name', 'Laravel') }}</title>
<link href="{{ asset('css/app.css') }}" rel="stylesheet" />
<style>body{ margin-bottom: 60px !important;}</style>
</head>
<body style="overflow:hidden;">
<noscript>
<strong>We're sorry but Xtreme Vuesax doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="{{ asset('js/app.js') }}"></script>
<script>
window.default_locale = "{{ config('app.locale') }}";
window.fallback_locale = "{{ config('app.fallback_locale') }}";
</script>
</body>
</html>
app.js
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
import localesData from './components/Layouts/localesData'
Vue.component('locale-dropdown', require('./components/Layouts/locales').default);
const i18n = new VueI18n({
locale: 'en',
messages: localesData,
})
const app = new Vue({
el: '#app',
router,
store,
i18n,
render: h => h(App)
});
Explanation
I need this line <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> to be change to selected language in VueJs.
any idea how to change that?
From within your Vue component 'locale-dropdown', when the user selects a locale, you can
//say the data property on your component which holds the selected locale is called locale
let h = document.querySelector('html');
h.setAttribute('lang', this.locale);
I'm trying to setup Inertia to use in my Laravel project but it gives me errors? Where is my mistake?
I installed Inertia with this command
composer require inertiajs/inertia-laravel
followed the instructions on the github page and added #inertia to my app.blade.php like this:
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<link rel="icon" type="image/jpg" href="{{asset("/image/logo2.png")}}">
<!-- Fonts -->
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
#inertia
</body>
</html>
in my Login Controller
public function showLoginForm()
{
return Inertia::render('Auth/Login');
}
in my routes/web.php
Auth::routes();
Route::get('login', 'Auth\LoginController#showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController#login');
This is the error I get:
the lines that is highlighted is the #inertia which show up as this
<div id="app" data-page="<?php echo e(json_encode($page)); ?>"></div>
What am i doing wrong?
#inertia blade directive is working but not rendered because you need to install the frontend adapter
npm install #inertiajs/inertia #inertiajs/inertia-vue
Set it up in webpack.mix.jsĀ
const mix = require('laravel-mix')
const path = require('path')
mix.js('resources/js/app.js', 'public/js')
.webpackConfig({
output: { chunkFilename: 'js/[name].js?id=[chunkhash]' },
resolve: {
alias: {
vue$: 'vue/dist/vue.runtime.esm.js',
'#': path.resolve('resources/js'),
},
},
})
And initialize it in Vue resources/js/app.js
import { InertiaApp } from '#inertiajs/inertia-vue'
import Vue from 'vue'
Vue.use(InertiaApp)
const app = document.getElementById('app')
const pages = {
'Auth/Login': require('./Pages/Auth/Login.vue').default,
}
new Vue({
render: h => h(InertiaApp, {
props: {
initialPage: JSON.parse(app.dataset.page),
resolveComponent: name => pages[name],
},
}),
}).$mount(app)