nativescript-vue / nativescript-vue

Native mobile applications using Vue and NativeScript.
https://nativescript-vue.org/
MIT License
5.32k stars 241 forks source link

Lazy Loading components #852

Open 4f3x opened 3 years ago

4f3x commented 3 years ago

Version

2.9.0

Reproduction link

https://play.nativescript.org/?template=play-vue&id=ByiImE

Platform and OS info

NS 8.0

Steps to reproduce

this.$navigateTo does not accept lazily loaded components. In an example of the deprecated NS adaptation of vue-router this appears to be possible. NS-NG also appears to provide lazy loading components for routing. The components appears to load properly, yet the Frame is not updated accordingly.

What is expected?

The component is loaded dynamically and routed to properly.

What is actually happening?

The component may load and appears to be instantiated using Vue-Devtools, yet the frame is not updated.


Thank you for your help and work on NS-Vue!

zaSmilingIdiot commented 2 years ago

I seem to be working around this by doing something similar to the following in the relevant tap event handler:

await import('path/to/component/here.vue')
  .then(module => module.default)
  .catch(() => null)
  .then(mod => mod && this.$navigateTo(mod, {/*options, etc here */ } ));

I'm not 100% certain what the performance impact is, if any, but its working (at least on Android... haven't done any check on this for iOS).

MrSnoozles commented 2 years ago

@rigor789 Could you verify that this is bad practice and if there is a better approach:

We want to register the routes globablly. Because of the behaviour in this issue we're doing:

// app/routes.js

import Home from '~/pages/Home';
import Profile from '~pages/Profile';
import TodoList from '~/pags/TodoList'

export default {
  Home,
  Profile,
  TodoList
};

We then register the routes doing

// app/app.js
import Vue from 'nativescript-vue';
import routes from './routes.js'

Vue.prototype.$routes = routes;

This is super convenient for navigating through the app. But I guess because the components are not lazy loaded all the pages are loaded on startup, impacting app startup performance. Is that correct?

rigor789 commented 2 years ago

They are in the initial webpack chunk yes, though they are not "loaded" as-in the contents/components.

The bundle contains something like this:

// bundle.js - pseudo version, omitting webpack related stuff
// app.js code
// ...
// Home.vue code
... export { /* stuff */ }
// Profile.vue code
... export { /* stuff */ }
// TodoList code
... export { /* stuff */ }

Where if you do lazy-loading, it would be like

// bundle.js - pseudo version, omitting webpack related stuff
// app.js code
// ...
// webpack runtime code for loading other chunks
// Home.vue code in Home.vue.webpack-chunk.js
... export { /* stuff */ }
// Profile.vue code in Profile.vue.webpack-chunk.js
... export { /* stuff */ }
// TodoList code in TodoList .vue.webpack-chunk.js
... export { /* stuff */ }

Whether it makes a speed difference or not, I'm not sure, would require some benchmarking.

  1. Probably loads slower initially because the initial file is bigger
  2. Probably loads slower when trying to navigate because it has to resolve an external module

Would definitely be interesting to measure the difference between the two.