Nuxt.js custom loader not loading instantly - vue.js

So my custom loader is not loading instantly only like a split second then it loads here is my site, my goals is to my custom components load. PS when i change ssr to false it works
here is my site: https://micahkwaka.dev
export default {
loading: '~/components/LoadingBar.vue',
loadingIndicator: false,
ssr: true,
pageTransition: {
name: 'my-page',
mode: 'out-in'
},
// Target (https://go.nuxtjs.dev/config-target)
target: 'static',
}

EDIT: This loader is when you have an SPA, to wait for it to load before showing the content. Since you're using Nuxt as an universal app (ssr + client), you will have the static content first (before the JS kicks in, and therefore your animation). So, you could make one with static SVG/CSS but the backed-in JS loader is not the solution here.
The best way would be to disable the JS to test the final result. Still, I'm pretty sure that Google will give you a better rating if you do not have any loader. You could maybe add it to your page transitions tho.
For the animation itself, start with it, then setTimeout the removal of it after 500ms or alike. Plenty ways of doing it. But you will need to have it on the initial render of your page (before the JS hydration).
Why do you set the loadingIndicator to false if you want it ?
If you want a custom one, provide a path to key as explained in the documentation: https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-loading-indicator/

Related

How to properly load Bootstrap5's Masonry into Nuxt?

I am trying to use the Masonry plugin with Bootstrap5 and NuxtJS. When I follow the example here
https://getbootstrap.com/docs/5.0/examples/masonry/ and incorporate it into my own codesandbox, I notice that my demo is not in the correct masonry format. See the gaps? My sandbox
My example:
Bootstrap's example:
What do I need to do to get my demo into format shown on the Bootstrap Masonry example page?
I checked how to load the script from a CDN either globally or locally. It was working but at one condition: you needed to NOT start on the masonry page.
Meaning that if you loaded the app on a specific page, then moved to the one with the masonry it was working. But not if you started on this specific page. So, a pretty subpar solution.
This article was really helpful to understand how to wait until the CDN script is fully loaded: https://vueschool.io/articles/vuejs-tutorials/how-to-load-third-party-scripts-in-nuxt-js/
Then I realized that we are far better installing it directly as an NPM dependency. Therefore, I proceeded to the masonry repo. Found a great message on how to setup the whole thing in Nuxt.
And after a removal of some useless stuff and some modern dynamic import, here we are
<template>
<main>
<h1>Bootstrap and Masonry</h1>
<div class="row" id="masonry">
<!-- ... -->
</main>
</template>
<script>
export default {
async mounted() {
if (process.browser) {
let { default: Masonry } = await import('masonry-layout')
new Masonry('#masonry', { percentPosition: true })
}
},
}
</script>
The final solution is looking pretty well and there is not a lot of code. On top of that, the code is properly loaded. And you can load it on a click or any other event.

Image require() in nuxt with hot reload by HRM webpack

I use the dynamic source for vue-webpack images in nuxt :src="require('path/to/image' + dynamic.variable)" in my project navbar. If the users substitute their image through a form which refetches their information and deletes their previous image I get a webpack error module (img) not found (it does not find the new one): is there a way to solve this, like wait for webpack HRM to finish?
I tried setting up a setTimeout() of one second before user re-fetch and it works, but I don't like a random waiting, I'd use a promise or a sync dynamic, the point is webpack hot reload is not controlled by my functions.. I also tried with setting the dynamic path as a computed: but it doesn't fix.
My image tag:
<img v-if="this.$auth.user.image" class="userlogo m-2 rounded-circle" :src="require('#assets/images/users/' + this.$auth.user.image)" alt="usrimg">
My Useredit page methods:
...
methods: {
userEdit() {
//uploads the image
if (this.formImageFilename.name) {
let formImageData = new FormData()
formImageData.append('file', this.formImageFilename)
axios.post('/db/userimage', formImageData, { headers: { 'Content-Type': 'multipart/form-data' } })
// once it has uploaded the new image, it deletes the old one
.then(res=>{this.deleteOldImage()})
.catch(err=>{console.log(err)})
}else{
this.userUpdate() //if no new image has to be inserted, it proceeds to update the user information
}
},
deleteOldImage(){
if(this.$auth.user.image){axios.delete('/db/userimage', {data: {delimage: this.$auth.user.image}} )}
console.log(this.$auth.user.image + ' deleted')
this.userUpdate() // it has deleted the old image so it proceeds to update the user information
},
userUpdate(){
axios.put(
'/db/user', {
id: this.id,
name: this.formName,
surname: this.formSurname,
email: this.formEmail,
password: this.formPassword,
image: this.formImageFilename.name,
})
.then(() => { console.log('User updated'); this.userReload()}) // reloads the updated user information
.catch(err => {console.log(err)} )
},
userReload(){
console.log('User reloading..')
this.$auth.fetchUser()
.then(() => { console.log('User reloaded')})
.catch(err => {console.log(err)} )
},
}
...
the problem happens after "console.log('User reloading..')" and before "console.log('User reloaded');", it is not related to the file upload nor the server response. I broke a single function in many little ones just to check the function progression and its asynchronous dynamics but the only one that is not manageable is the webpack hot reload :/
I'd like the users to upload their images and see their logo in the Navbar appear updated after submitting the form.
First of all, as somebody told you in the comments, webpack hmr shouldn't be used for production.
In Nuxt, everything that you reference from the assets folder will be optimized and bundled into the project package. So the ideal use case for this folder is all assets that can be packaged and optimized, and most likely won't change like fonts, css, background images, icons, etc.
Then, require is called only once by webpack when it is either building the site for local development or building the site for generating a production package. The problem in your case is that you delete the original file while you're in development and webpack tries to read it and fails.
In the case of these images that the user uploads, I think you should use the static folder instead and instead of using require you'll have to change the :src with
:src="'/images/users/' + this.$auth.user.image"
Let me know if this helps.
Okay, I probably solved it.
HMR: you are of course right. Thank you for pointing out, I am sorry, I am a beginner and I try to understand stuff along the way.
Aldarund, thank you, your idea of not changing the path and cache it client side.. I am too noob to understand how I could implement it ( :) ) but it gave me a good hint: the solution was to keep the image name as the user id + the '.png' extension and to manage the image with jimp so that the image name, extension and file type are always the same, and with or without webpack compiling the new path, I always have the correct require().
Jair, thank you for the help, I didn't follow that road, but I will keep it as a second chance if my way creates errors. Just to be specific: the error comes when it does not find -and asks for the name of- the NEW image, not the OLD one, as I wrote in my question: it happens because the fetchUser() functions reloads the user information including the new image name.
Do you guys see any future problems in my methodology?
Really thank you for your answers. I am learning alone and it's great to receive support.

Multiple Aurelia Instances - Aurelia Webpack Plugin - aureliaApp option - "module not found"

I am composing my web app as a number of Aurelia "feature" apps - although I'm not using Aurelia features as such. Consequently in my html markup I have two entry points pointing to different apps:
<!-- Top Navigation Bar -->
<div aurelia-app="topnav"></div>
<!-- Main App-->
<div aurelia-app="main"></div>
I am using webpack and everything works perfectly using the single "main" app. Webpack generates a JS file "main.bundle.js" which I include in the src tag.
Things are not so straightforward when I added the "topnav" app. In webpack I tell the plugin to use a different aureliaApp name:
new AureliaPlugin({ aureliaApp: "topnav"}),
and, as you can see my HTML entrypoint also calls "topnav". Webpack generates a JS file "topnav.bundle.js" which I also include. I have a file called "topnav.ts" which contains the aurelia Cionfigure function which ends:
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName("nav")));
And a pair of files "nav.ts", "nav.html" which constitute my viewmodel and view.
When I run the app aurelia loads and the "nav" module code executes. But I then get an error - see below.
The module which it reports that it cannot find is the one entered into the HTML markup.
Should this work? Have I missed something?
I should add, everything seems to work. I can create and update properties in the viewmodel and these are bound to the view. It's just that this error is thrown.
You are doing nothing wrong, just unsupported scenario. Per official doc-wiki: https://github.com/aurelia/webpack-plugin/wiki/AureliaPlugin-options#aureliaapp
You can have only 1 auto entry module with aureliaApp configuration. To solve this, you just need to add PLATFORM.moduleName('topnav') to your main.ts (and put it on root level)
Another way to do is to bootstrap manually:
// in your index.ts
import { bootstrap } from 'aurelia-bootstrapper';
// bootstrap top nav application, with one instance of Aurelia
bootstrap(aurelia => {
// do your configuration
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('topnav'),
document.querySelector('#topnav')
);
});
// bootstrap main application, with another instance of Aurelia
bootstrap(aurelia => {
// aurelia.use.standardConfiguration();
// ...
aurelia
.start()
.then(() => aurelia.setRoot(
PLATFORM.moduleName('app'),
document.querySelector('app')
)
});

Dynamic data not rendering in prerender-spa-plugin

I use prerender-spa-plugin in vue.js app for rendering html
but it can't render dynamic data.
when prerender-spa-plugin complete rendering
created html file only contains some html code not showing any dynamic data
Method
Mounted
prerender-spa-plugin Configuration
Adding the headless option solve the problem for me:
renderer: new Renderer({
injectProperty: '__PRERENDER_INJECTED',
renderAfterTime: 5000,
// Other puppeteer options.
// (See here: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)
headless: false // Display the browser window when rendering. Useful for debugging.
})

ArcGIS Api (Esri) triggering multipleDefine error

I have this weird issue while using ArcGIS API for JavaScript v4.4 in my code. I am trying to build an Excel Web Add-in in which I would like to load an ArcGIS map but when I load ArcGIS I get a multipleDefine error.
ArcGIS is getting bundled with Dojo which is used as the loader for all the ArcGIS/esri packages. I have no other choices to load my own custom JS bundles with Dojo because of the way ArcGIS has built their API. So I can't decide to not use Dojo and thus not getting the multipleDefine error.
I load my own JS files like this:
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js" type="text/javascript"></script>
<script>
var dojoConfig = {
parseOnLoad: false,
async: false,
// we make aliases for our js file
aliases:  [
['index',  './Bundles/index.js'],
],
};
</script>
<script src="https://js.arcgis.com/4.4/init.js"></script>
<script>
require(['index'], function (index) {
//...do something
});
</script>
When I restart the page I get a multipleDefine error once in every two/three trials. After a lot of investigation I understood that the error lies with the Office.js API but I had a hard time to find a good solution.
After a while I found the cause of the problem; we cannot start office-js and Dojo together because they both want to add scripts in the head tag of our page and somehow they end up in conflict with one another, thus we get the dreaded multipleDefined Dojo error and some of our files do not get loaded.
Once this cause was identified I decided to solve it by making sure Dojo, Argis and my custom js files got loaded once Office and dependencies were fully loaded.
I implemented it like this in my js code:
// This Dojo config variable has to be defined before Dojo is loaded in our scripts
var dojoConfig = {
// we make aliases for our custom js file
aliases: [
['index', './Bundles/index.js'],
],
// We require our dependencies (our own code bundles) with Dojo.
// Notice that it is mandatory to bundle our js files
// as AMD Modules for Dojo to be able to load them as dependencies.
deps: ['index'],
};
// Once office has fully initialized we can add our arcgis file and let
// him load our own required javascript files.
// We cannot start Office-js and Dojo/Arcgis together because they both
// want to add scripts in the head tag of the HTML page and
// somehow they end up in conflict, thus we get the dreaded
// multipleDefined Dojo error and some of our files
// do not get loaded.
Office.initialize = function (reason) {
// we manually add the Arcgis script to the header of our page
// once we are sure Office and dependencies has fully loaded.
var tag = document.createElement('script');
tag.src = 'https://js.arcgis.com/4.4/init.js';
document.getElementsByTagName('head')[0].appendChild(tag);
};
Once this was added the code started working like a charm.