Hello. I'm using Next 13 and lottie
I have an object with a lot of components that are jsons like that:
import animationA from '../animations/animationA.json'
import animationB from '../animations/animationB.json'
import animationC from '../animations/animationC.json'
import animationD from '../animations/animationD.json'
export const animations = {
day: {
animation: animationA,
duration: 1000
},
day: {
animation: animationB,
duration: 2000
},
day: {
animation: animationC,
duration: 3000
},
day: {
animation: animationD,
duration: 4000
}
}
And works perfectly but the page speed test warned me to make smaller bundles.
The problem is I don't know how to do this. I already test as await import
const animationA = await import('../animations/animationA.json')
This solved the bundle problem, but the object animations became weird and does not load properly when I call that specific animation.
I want a way to load those animations in separated bundles, and if possible, my object animations still working as would be with static imports.
Thanks
Related
Env
I have a Vue 3 Application which requires a constant setInterval() to be running in the background (Game Loop).
I put that in store/index.js and call it from views/Playground.vue on mounted().
When leaving Playground i call beforeUnmount(). Making sure that not multiple setInterval() are running.
// store/index.js
startGameLoop({ commit, dispatch, getters }) {
commit(
"setIntervalId",
setInterval(() => {
dispatch("addPower", getters["ship/getFuelPerSecond"]);
}, 1000)
);
},
// Playground.vue
beforeUnmount() {
clearInterval(this.intervalId);
}
In the top section of Playground.vue there is a score displayed and updated within the setInterval(). I use a library called gsap to make the changing numbers a bit pleasant for the eye.
<h2>Points: {{ tweened.toFixed(0) }}</h2>
watch: {
points(n) {
console.log("gsap");
gsap.to(this, { duration: 0.2, tweened: Number(n) || 0 });
},
},
Problem
methods from the Playground.vue are fired differently and i'm struggling to understand why that is the case.
gsap
the watch from the gsap is fired every second like i would expect from the setInterval() but...
Image
In the center of the Playground i display and image where the src part is v-bind to a method called getEnemyShipImage. In the future i would like to change the displayed enemie ship programmatically - but the method is called 34 times per second. Why is that?
<img
:class="{ flashing: flash }"
#click="fightEnemie()"
:src="getEnemyShipImage()"
alt=""
/>
getEnemyShipImage() {
console.log("image");
return require("#/assets/ships/ship-001.png");
}
Log (Browser)
Console Log Output
moved it to a part without using a method and switch changing images to a watch.
data: () => {
return {
...
selectedImages: "",
images: [
require("#/assets/ships/ship-001.png"),
require("#/assets/ships/ship-002.png"),
require("#/assets/ships/ship-003.png"),
],
};
},
// initial value
mounted() {
this.selectedImages =
this.images[Math.floor(Math.random() * this.images.length)];
this.$store.dispatch("startGameLoop");
}
// watch score
watch: {
score() {
this.selectedImages =
this.images[Math.floor(Math.random() * this.images.length)];
},
}
it's not perfect but better as initialy.
I have a very strange problem I can't put my finger on.
I am using Barba.js which makes awesome page transitions and Swiper.js which is a lovely carousel. The problem is that it makes your page a SPA so you have to reinit scripts. Quite a pain to tell you the truth.
In my barba.js file I call a swiper carousel at the top
import barba from "#barba/core";
import { homeCarousel } from './swiper.js'
function initCarousel() {
if (document.querySelector('.swiper-container') != null) {
homeCarousel();
}
}
barba.init({
sync: true,
preventRunning: true,
views: [{
namespace: 'main',
afterEnter() {
setTimeout(() => {
initCarousel();
}, 550);
}
}],
transitions: [{
async leave() {
done();
},
async enter() {
newPage();
},
}]
})
Then in my swiper.js file
import Swiper from 'swiper';
import 'swiper/css/swiper.css';
const homeCarousel = () => {
var hs = new Swiper('.home__carousel', {
init: false,
});
hs.init();
}
homeCarousel();
export { homeCarousel }
This all works o.k. but I have another page that doesn't have a carousel on it so .swiper-container will return null. That's good too, but because am importing at the top of barba.js
import { homeCarousel } from './swiper.js'
It's called when the page is refreshed thus causing a nasty error
Cannot read property 'push' of undefined
When the route is changed, there's no horrible console error.
I guess in an ideal world I would place this import statement inside of the if (document.querySelector('.swiper-container') != null) but imports have to be top level.
Any suggestions, please? I'm about to through the PC out of the window. Probably a good thing.
As you use swiper.js as a library it should contain only API without side effects.
In this case remove homeCarousel(); from swiper.js.
I'm using the following code to show a datetime (using momentjs) that updates every second. I've read discussion about the performance issue's that may or may not be caused by setInterval and setTimeout.
Is this the most efficient way of going about this? What is thé common way to use intervals in single page applications?
export default {
name: 'app',
data () {
return {
dateTime: null
}
},
methods: {
updateTimer () {
this.dateTime = moment().format()
}
},
mounted () {
this.interval = setInterval(this.updateTimer, 1000)
}
}
The discussion can be found here:
https://forum.vuejs.org/t/basic-problem-making-a-clock-update-in-vue/642/14 (it is 3 years old now)
I'm releasing my Vue app into production, but one specific component throws an esoteric error message that I can't trace because all project files are bundled and variable names are changed. This error also is only reproducible in production mode (build), leading me to believe that it's an issue related to the bundling itself.
Steps to reproduce
As I mentioned before, the issue is only present in production mode. Therefore I have done my best to reproduce the issue by simply releasing the app on Netlify for reproduction. Here are the steps:
Visit the app on netlify here: https://grandquest.netlify.com
Scroll down to the "Sign up" form and create a fake account to test the bug
Login using these credentials at the login page
Open the console
Visit the world and click the button that says "Explore Monokai"
Doing this should take you to the faulty route/component (grandquest.netlify.com/map)
The details
The app works perfectly fine in development mode , however (as I will link to), when run in production mode, the app produces an error: Type Error: e is undefined (Mozilla Firefox only, AFAIK) when I mount a specific route.
Secondly, in the vue-cli build logs, I can see various warnings relating to file size limits. Here are the warnings from the build logs:
warning
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
img/gold-frame.536f6ce1.png (415 KiB)
media/combat-fail.f73de150.mp3 (317 KiB)
img/monokai-village.84e00e29.png (1.25 MiB)
img/combat.835c3bee.png (1.04 MiB)
img/combat-shop.138daeea.png (1.56 MiB)
img/potions-shop.dea509b2.png (2.07 MiB)
media/fields-music1.bd10f1d6.mp3 (2.46 MiB)
img/village-gate.f8c4cfd2.png (3.52 MiB)
js/chunk-vendors.6c22f97f.js (1.71 MiB)
warning
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
app (1.95 MiB)
js/chunk-vendors.6c22f97f.js
css/app.fa9c625b.css
js/app.9440af5a.js
warning
webpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/
DONE Build complete. The dist directory is ready to be deployed.
INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
✨ Done in 122.97s.
These two details have led me to believe that the issue is caused by a bundling error
-
I have tried looking for any variables name e inside my code, thinking maybe it was an event, but there are no such variables in my code. It just appears to be a variable that is 'bundled' by vue.
Due to the nature of this error (I am not certain what the variable e is in the code because it's obfuscated), I have done my best to summarize the relevant code for the Map component. I would also not mind sharing the entirety of the files if it could help, however, there is no e variable to be found.
#/views/Map.vue
<template>
<div>
<!-- LOADING SCREEN -->
<div v-if="!gameInterface.gameInitialized" id="loading-screen">
<img src="#/assets/img.png" v-on:click="$router.push(`/world`)">
<div class="tip">Fun fact</div>
<div class="loading-text">Loading assets</div>
</div>
<!-- MAP CONTAINER -->
<div class="map">
<button class="exit-button" v-on:click="() => $router.replace({ name: 'world' })">
EXIT
</button>
<!-- CANVAS PARENT -->
<div
id="canvas-parent"
v-on:mousemove="gameInterface.mouseMonitor"
v-on:mouseleave="gameInterface.pointer.hovering = false"
v-on:resize="resizeMonitor"
/>
<!-- RENDER THE SHOP -->
<Shop v-if="gameInterface.chosenShop"/>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { State, Mutation } from 'vuex-class'
// typescript types
import { User } from '#/types';
// vue components
import Shop from '#/components/Shop.vue';
// the game controller
import gameInterface from '#/game/places/map.ts';
#Component({
components: { Shop }
})
export default class Map extends Vue {
#State public user!: User;
public gameInterface = gameInterface();
public mounted() {
if (!this.user.authenticated) {
return this.$router.replace({ name: 'world' });
}
this.gameInterface.launch();
document.addEventListener('wheel', this.gameInterface.scrollMonitor, true);
}
public destroyed() {
document.removeEventListener('wheel', this.gameInterface.scrollMonitor, true);
this.gameInterface.destroyGame();
}
}
#/game/places/map.ts
export default () => {
let game: any = null;
let global = {
tooltip: {},
chosenShop: null,
gameInitialized: false,
pointer: { x: 0, y: 0, hovering: false },
launch() {
if (!game) {
// here a phaser game is started
game = new Phaser.Game({
// ...config here
created() {
global.gameInitialized = true;
},
});
}
},
destroyGame() {
if (game) {
game.destroy();
}
},
mouseMonitor(event) {
if (!global.gameInitialized) {
return;
}
global.pointer = {
x: event.clientX,
y: event.clientY,
hovering: true,
};
},
scrollMonitor(event) {
if (!game) {
return;
}
if (event.deltaY < 0 && game.scene.scenes[0].cameras.main.zoom < 2) {
game.camera.zoom += 0.1;
}
if (event.deltaY > 0 && game.scene.scenes[0].cameras.main.zoom > 1.15) {
game.camera.zoom -= 0.1;
}
},
exitShop() {
if (!game) {
return;
}
global.chosenShop = null;
game.resume();
}
};
return global;
};
Expected output
You should see a loading screen for some time while the assets load, and then a map should appear on the screen. You should be able to, with your cursor, navigate this map up and down, as well as click on the various shops.
Actual output
The screen appears to be loading indefinitely because an error has ocurred that has stopped the app. The error should now appear in the console, reading Type error: e is undefined(on Firefox)
Any, and all, help is appreciated with this issue :)
Does this function exist?
v-on:resize="resizeMonitor"
I'm not seeing it anywhere. I think you'll get this type of error if the function doesn't exist
Using the same code (see fiddle) and 3 different export URLs I get different export results. The issue is that the left side of the chart is clipping off the category titles but only if the export is JPG, PNG, or PDF - the SVG export is fine.
Current output for JPG, PNG, or PDF:
This the expected output for those types and what SVG does export:
I have set up a jsFiddle - click on the image types at the top to see the issues while changing the exporting.url value.
This is the export code:
window.chartExportLoc = function(chartid, exportType, graphHeader, graphFooter, marginSize) {
var chartToExport = $('#' + chartid).highcharts(),
sourceSpacingBottom = chartToExport.options.chart.spacingBottom;
if (!marginSize) {
marginSize = 15; //HighCharts default
}
chartToExport.exportChart({
type: exportType,
scale: 1,
filename: chartid
}, {
title: {
text: unescape(encodeURI(graphHeader)),
margin: marginSize
},
subtitle: {
y: 10,
text: unescape(encodeURI(graphFooter))
},
chart: {
shadow: false,
width: 800,
spacingBottom: sourceSpacingBottom - 20
}
});
return false;
}
We are running the highchart-export-server nodejs module and it is producing the clipped chart. If we change the exporting.url to use our existsing Java-based exporting application we get the correct/expected output. If we then change to use the export server hosted by highcharts (export.highcharts.com) it also produces the expected output.
I did file a bug on github for this issue but no responses from highcharts and hoping someone here can assist. This is preventing us from moving forward with the nodejs implementation and finally sunsetting the Java-based export app.