There are some that say Haxe is what javascript should have been, a swiftly typed speedy scripting language. Typescript for me has been a life saver as javascript has too many surprises that even if I try to study them and understand them all, I'm still prone to human errors of forgetfulness and clumsiness. Overtly it's honestly just JSLint++ since all javascript code is valid typescript code and the super-set is non-intrusive.
The creator of node, vuejs, vscode, google, etc, advocate it's one of the best ways to manage large scaling javascript projects. If you're on vscode, you can add //@ts-check , and typescript will check your javascript and bug you about potential errors. If you find it saves you from lots of headaches, make the jump to typescript.

it's really hard to say. Looking up games made from phaser 2 vs phaser 3, it'll be able to tackle what most want to throw in a web based game.
But phaser 3 is more preformant, completely re-written from scratch and huge emphasis on modularity.
If you're not satisfied with either, you could build your own with PIXIJS as a backend renderer. Phaser2 uses pixijs v2 iirc but pixi is at v4-5 now.

scene: {
preload: preload,
create: create,
update: update,
scene: [Scene1]
},﻿﻿
it seems that the preload, create, and update, will run first before Scene1's preload, create, and update. If you want to change the order, you create a game scene class, just like you did with scene1(recommended approach) or you can put all your gameplay code in Scene1 and all the menu code in preload, create, and update.
it seems you dont even have a game scene. (thanks for linking my tutorial, hopefully it helps)

@SovietSenpai23
ahhh kk, didn't see the repeat. You can listen to "animationrepeat" instead because repeating animations will never complete.
dragon-fly, since you have the repeat: -1, there's no need to put it in a the update loop or any loop.
You can play the attack animation in the create() and then listen to "animationrepeat" ;
dragon.once("animationrepeat", () => {
dragon.anims.play('dragon-fly');
});
This will return it back to the fly after it repeats attack once.
It will keep running this function when fly is repeating though you can use .once() instead of .on(); and you dont have to remove the listener.
How I would go about doing this is to keep track of if(dragon-atttack){ play(attack)} else{play(fly)} in the update loop.
If you want it in the update function you would need to keep track when the dragon is flying and when it is attacking.

so after dragon-attack finishes, after, you want the dragon-fly animation to play?
dragon.on("animationcomplete", ()=>{ //listen to when an animation completes, then run fly
dragon.anims.play('dragon-fly")
}
//you would need to remove this afterwards though.
If the dragon-fly is the moving/idle state, you can run that on a loop by default and then when you run dragon-attack, it will return back to dragon-fly.