rancher / dashboard

The Rancher UI
https://rancher.com
Apache License 2.0
463 stars 261 forks source link

Vue3: Exceptions thrown in `data` result in blank page #11807

Open richard-cox opened 2 months ago

richard-cox commented 2 months ago

Setup

Describe the bug

To Reproduce

Result

Expected Result

Additional Information

eva-vashkevich commented 1 month ago

We are pushing this issue out because it appears to be more complex than originally thought. A few discoveries:

Some suggestions: https://github.com/rancher/dashboard/pull/12198

rak-phillip commented 1 month ago

We should strongly consider refactoring instances of data that contain complex initialization logic. The project will benefit from writing idiomatic Vue code, and my concern is that we're trying to preserve an anti-pattern instead of correcting and discouraging its usage.

We can eliminate this problem entirely by moving logic and side effects to lifecycle hooks, computed props, or methods and keeping data simple and focused on initializing reactive state.

richard-cox commented 1 month ago

@rak-phillip If the anti-pattern was just tech debt i would agree. This issue though is about ensuring the ui doesn't 'crash' (show a blank page, require refresh), which is about worst thing that can happen, erodes faith in the product and rancher, and is a vue3 UX regression.

Once we identify places where this covers we can address in a better, targeted way (whilst still incrementally converting the complex data fn's over to something better).

rak-phillip commented 1 month ago

In that case, I'd like to advocate for guarding against as many critical failures as possible for 2.10.

A straightforward way to address this is to wrap each offending instance of complex initialization in data in a try..catch block, handle the error ourselves, and allow Vue to return some data object (closer to the Vue2 behavior). It's not elegant, but it limits the scope for potential failures and erosion of trust.

If we consider all components that contain a data prop that does not immediately return an object

data () {
  return {

These can be interpreted as containing complex initialization logic; we would have at least 155 components to cover:

grep -rPzol -C 5 "data\s*\(\)\s*{(?![^{]*return\s*{)" --exclude-dir node_modules --include="*.vue" .

``` ./pkg/aks/components/Taint.vue ./pkg/harvester-manager/machine-config/harvester.vue ./shell/chart/monitoring/grafana/index.vue ./shell/chart/istio.vue ./shell/cloud-credential/generic.vue ./shell/cloud-credential/azure.vue ./shell/components/EmberPageView.vue ./shell/components/Questions/Reference.vue ./shell/components/ResourceList/Masthead.vue ./shell/components/ResourceList/index.vue ./shell/components/SortableTable/index.vue ./shell/components/fleet/FleetIntro.vue ./shell/components/fleet/FleetNoWorkspaces.vue ./shell/components/form/ResourceQuota/Project.vue ./shell/components/form/Command.vue ./shell/components/form/EnvVars.vue ./shell/components/form/HealthCheck.vue ./shell/components/form/HookOption.vue ./shell/components/form/LifecycleHooks.vue ./shell/components/form/MatchExpressions.vue ./shell/components/form/NameNsDescription.vue ./shell/components/form/Networking.vue ./shell/components/form/NodeAffinity.vue ./shell/components/form/NodeScheduling.vue ./shell/components/form/PodAffinity.vue ./shell/components/form/Probe.vue ./shell/components/form/ResourceSelector.vue ./shell/components/form/ShellInput.vue ./shell/components/form/Tolerations.vue ./shell/components/form/ValueFromResource.vue ./shell/components/form/WorkloadPorts.vue ./shell/components/form/ArrayList.vue ./shell/components/form/Security.vue ./shell/components/formatter/ExtensionCache.vue ./shell/components/formatter/Port.vue ./shell/components/formatter/SecretData.vue ./shell/components/formatter/SecretType.vue ./shell/components/formatter/ServiceType.vue ./shell/components/nav/TopLevelMenu.vue ./shell/components/AlertTable.vue ./shell/components/ContainerResourceLimit.vue ./shell/components/HarvesterServiceAddOnConfig.vue ./shell/components/PromptRemove.vue ./shell/components/ResourceYaml.vue ./shell/components/YamlEditor.vue ./shell/detail/management.cattle.io.user.vue ./shell/detail/namespace.vue ./shell/detail/secret.vue ./shell/detail/service.vue ./shell/edit/auth/ldap/config.vue ./shell/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue ./shell/edit/autoscaling.horizontalpodautoscaler/metric-target.vue ./shell/edit/constraints.gatekeeper.sh.constraint/index.vue ./shell/edit/logging-flow/index.vue ./shell/edit/logging.banzaicloud.io.output/providers/elasticsearch.vue ./shell/edit/logging.banzaicloud.io.output/providers/gelf.vue ./shell/edit/logging.banzaicloud.io.output/providers/opensearch.vue ./shell/edit/logging.banzaicloud.io.output/providers/redis.vue ./shell/edit/logging.banzaicloud.io.output/providers/syslog.vue ./shell/edit/logging.banzaicloud.io.output/index.vue ./shell/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue ./shell/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue ./shell/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue ./shell/edit/monitoring.coreos.com.alertmanagerconfig/auth.vue ./shell/edit/monitoring.coreos.com.alertmanagerconfig/index.vue ./shell/edit/monitoring.coreos.com.alertmanagerconfig/tls.vue ./shell/edit/monitoring.coreos.com.receiver/types/opsgenie.vue ./shell/edit/monitoring.coreos.com.receiver/types/pagerduty.vue ./shell/edit/monitoring.coreos.com.receiver/types/slack.vue ./shell/edit/monitoring.coreos.com.receiver/types/webhook.vue ./shell/edit/monitoring.coreos.com.receiver/auth.vue ./shell/edit/monitoring.coreos.com.receiver/index.vue ./shell/edit/monitoring.coreos.com.receiver/tls.vue ./shell/edit/networking.istio.io.destinationrule/LoadBalancer.vue ./shell/edit/networking.k8s.io.ingress/Certificate.vue ./shell/edit/networking.k8s.io.ingress/Rule.vue ./shell/edit/networking.k8s.io.ingress/RulePath.vue ./shell/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue ./shell/edit/networking.k8s.io.networkpolicy/PolicyRules.vue ./shell/edit/networking.k8s.io.networkpolicy/index.vue ./shell/edit/persistentvolume/plugins/awsElasticBlockStore.vue ./shell/edit/persistentvolume/plugins/azureDisk.vue ./shell/edit/persistentvolume/plugins/azureFile.vue ./shell/edit/persistentvolume/plugins/cephfs.vue ./shell/edit/persistentvolume/plugins/cinder.vue ./shell/edit/persistentvolume/plugins/csi.vue ./shell/edit/persistentvolume/plugins/fc.vue ./shell/edit/persistentvolume/plugins/flexVolume.vue ./shell/edit/persistentvolume/plugins/flocker.vue ./shell/edit/persistentvolume/plugins/gcePersistentDisk.vue ./shell/edit/persistentvolume/plugins/glusterfs.vue ./shell/edit/persistentvolume/plugins/hostPath.vue ./shell/edit/persistentvolume/plugins/iscsi.vue ./shell/edit/persistentvolume/plugins/local.vue ./shell/edit/persistentvolume/plugins/longhorn.vue ./shell/edit/persistentvolume/plugins/nfs.vue ./shell/edit/persistentvolume/plugins/photonPersistentDisk.vue ./shell/edit/persistentvolume/plugins/portworxVolume.vue ./shell/edit/persistentvolume/plugins/quobyte.vue ./shell/edit/persistentvolume/plugins/rbd.vue ./shell/edit/persistentvolume/plugins/scaleIO.vue ./shell/edit/persistentvolume/plugins/storageos.vue ./shell/edit/persistentvolume/plugins/vsphereVolume.vue ./shell/edit/persistentvolume/index.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/networking/ACE.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue ./shell/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue ./shell/edit/provisioning.cattle.io.cluster/rke2.vue ./shell/edit/secret/index.vue ./shell/edit/secret/registry.vue ./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/aws-ebs.vue ./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/azure-disk.vue ./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/gce-pd.vue ./shell/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/vsphere-volume.vue ./shell/edit/storage.k8s.io.storageclass/provisioners/driver.longhorn.io.vue ./shell/edit/storage.k8s.io.storageclass/index.vue ./shell/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue ./shell/edit/workload/Job.vue ./shell/edit/workload/Upgrading.vue ./shell/edit/cis.cattle.io.clusterscanbenchmark.vue ./shell/edit/cis.cattle.io.clusterscanprofile.vue ./shell/edit/configmap.vue ./shell/edit/fleet.cattle.io.gitrepo.vue ./shell/edit/helm.cattle.io.projecthelmchart.vue ./shell/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue ./shell/edit/management.cattle.io.fleetworkspace.vue ./shell/edit/management.cattle.io.project.vue ./shell/edit/namespace.vue ./shell/edit/persistentvolumeclaim.vue ./shell/edit/policy.poddisruptionbudget.vue ./shell/edit/resources.cattle.io.restore.vue ./shell/edit/service.vue ./shell/edit/token.vue ./shell/edit/resources.cattle.io.backup.vue ./shell/list/workload.vue ./shell/machine-config/digitalocean.vue ./shell/machine-config/vmwarevsphere.vue ./shell/pages/auth/login.vue ./shell/pages/auth/verify.vue ./shell/pages/c/_cluster/apps/charts/install.vue ./shell/pages/c/_cluster/auth/config/index.vue ./shell/pages/c/_cluster/explorer/EventsTable.vue ./shell/pages/c/_cluster/monitoring/monitor/_namespace/_id.vue ./shell/pages/c/_cluster/monitoring/monitor/create.vue ./shell/pages/c/_cluster/monitoring/route-receiver/_id.vue ./shell/pages/c/_cluster/monitoring/route-receiver/create.vue ./shell/pages/c/_cluster/uiplugins/CatalogList/index.vue ./shell/pages/diagnostic.vue ./shell/pages/fail-whale.vue ./shell/pages/home.vue ```

We can also use this list as potential candidates for refactoring.