Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(vue): apply vue component name to wrapper #257

Merged
merged 1 commit into from
Apr 12, 2023

Conversation

sean-perkins
Copy link
Collaborator

@sean-perkins sean-perkins commented Apr 26, 2022

Pull request checklist

Please check if your PR fulfills the following requirements:

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)
  • Build (npm run build) was run locally for affected output targets
  • Tests (npm test) were run locally and passed

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Generated Vue component wrappers display as AnonymousComponent in Vue dev tools.

Issue URL: resolves #143

What is the new behavior?

Generated Vue component wrappers will correctly display as their pascal case component name in dev tools.

Does this introduce a breaking change?

  • Yes
  • No

Other information

Before After

This PR is in favor of #162.

@sean-perkins sean-perkins requested a review from a team April 26, 2022 19:08
@sean-perkins sean-perkins requested a review from a team as a code owner April 26, 2022 19:08
Copy link
Contributor

@liamdebeasi liamdebeasi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason why I opted not to make this change before was that it broke treeshaking with Webpack. Can you make a dev/prerelease build and I can help verify this with you?

@sean-perkins
Copy link
Collaborator Author

Can do 👍 we are taking advantage of this pattern in some if the manual wrappers in Ionic Vue (but not all).

Dev build: 0.6.1-dev.11651000551.1f528d2f

Framework branch using dev-build + fixes manual wrappers: FW-1403

@liamdebeasi
Copy link
Contributor

liamdebeasi commented Apr 26, 2022

This is the results in Ionic Vue 6.1.2:

  File                                 Size                            Gzipped

  dist/js/chunk-vendors.0403cd9d.js    155.62 KiB                      52.58 KiB
  dist/js/338.36682778.js              9.61 KiB                        2.62 KiB
  dist/js/980.a017a848.js              8.52 KiB                        3.36 KiB
  dist/js/605.e6a58a23.js              6.72 KiB                        2.71 KiB
  dist/js/576.fda3a897.js              4.97 KiB                        2.27 KiB
  dist/js/880.54275d29.js              4.97 KiB                        2.27 KiB
  dist/js/app.ab5fd87e.js              3.87 KiB                        1.83 KiB
  dist/js/753.96a8f7af.js              1.10 KiB                        0.60 KiB

This is the results using a dev build from your FW-1403 branch:

  File                                 Size                            Gzipped

  dist/js/chunk-vendors.1e534e0f.js    171.35 KiB                      55.63 KiB
  dist/js/338.448f3f86.js              9.61 KiB                        2.62 KiB
  dist/js/980.e5d479b7.js              8.52 KiB                        3.36 KiB
  dist/js/605.2c08ef3a.js              6.72 KiB                        2.71 KiB
  dist/js/576.fda3a897.js              4.97 KiB                        2.27 KiB
  dist/js/880.54275d29.js              4.97 KiB                        2.27 KiB
  dist/js/app.c47936d0.js              3.87 KiB                        1.83 KiB
  dist/js/753.41ccc004.js              1.10 KiB                        0.60 KiB

It looks like either webpack/Vue CLI fixed a lot of issues with treeshaking, but I do notice an increase in size with chunk-vendors.

I am testing on https://github.com/liamdebeasi/ionic-vue-treeshaking which only imports a single <ion-badge> component, so I imagine the difference will be a bit larger when testing a real world app.

Dev build with your changes: 6.1.3-dev.11651002603.1969dbdc

Are you able to identify what's been added/changed between the two builds?

@sean-perkins
Copy link
Collaborator Author

sean-perkins commented Apr 26, 2022

Ok digging into the output a couple things stand-out; one I ran npm ci for the initial snapshot and that seems to not include the aria attribute changes or the recent modal changes, which will account for some size.

The only other diff that is noticeable is this portion (putting inside a collapsible section):

Feature:

const kt = (e) => e.__isTeleport,
        St = (e) => e && (e.disabled || "" === e.disabled),
        Ct = (e) =>
          "undefined" !== typeof SVGElement && e instanceof SVGElement,
        _t = (e, t) => {
          const n = e && e.to;
          if ((0, r.HD)(n)) {
            if (t) {
              const e = t(n);
              return e;
            }
            return null;
          }
          return n;
        },
        Rt = {
          __isTeleport: !0,
          process(e, t, n, o, r, i, a, s, l, c) {
            const {
                mc: d,
                pc: u,
                pbc: p,
                o: {
                  insert: h,
                  querySelector: f,
                  createText: m,
                  createComment: g,
                },
              } = c,
              $ = St(t.props);
            let { shapeFlag: b, children: v, dynamicChildren: y } = t;
            if (null == e) {
              const e = (t.el = m("")),
                c = (t.anchor = m(""));
              h(e, n, o), h(c, n, o);
              const u = (t.target = _t(t.props, f)),
                p = (t.targetAnchor = m(""));
              u && (h(p, u), (a = a || Ct(u)));
              const g = (e, t) => {
                16 & b && d(v, e, t, r, i, a, s, l);
              };
              $ ? g(n, c) : u && g(u, p);
            } else {
              t.el = e.el;
              const o = (t.anchor = e.anchor),
                d = (t.target = e.target),
                h = (t.targetAnchor = e.targetAnchor),
                m = St(e.props),
                g = m ? n : d,
                b = m ? o : h;
              if (
                ((a = a || Ct(d)),
                y
                  ? (p(e.dynamicChildren, y, g, r, i, a, s), wt(e, t, !0))
                  : l || u(e, t, g, b, r, i, a, s, !1),
                $)
              )
                m || Lt(t, n, o, c, 1);
              else if ((t.props && t.props.to) !== (e.props && e.props.to)) {
                const e = (t.target = _t(t.props, f));
                e && Lt(t, e, null, c, 0);
              } else m && Lt(t, d, h, c, 1);
            }
          },
          remove(e, t, n, o, { um: r, o: { remove: i } }, a) {
            const {
              shapeFlag: s,
              children: l,
              anchor: c,
              targetAnchor: d,
              target: u,
              props: p,
            } = e;
            if ((u && i(d), (a || !St(p)) && (i(c), 16 & s)))
              for (let h = 0; h < l.length; h++) {
                const e = l[h];
                r(e, t, n, !0, !!e.dynamicChildren);
              }
          },
          move: Lt,
          hydrate: Tt,
        };
      function Lt(e, t, n, { o: { insert: o }, m: r }, i = 2) {
        0 === i && o(e.targetAnchor, t, n);
        const { el: a, anchor: s, shapeFlag: l, children: c, props: d } = e,
          u = 2 === i;
        if ((u && o(a, t, n), (!u || St(d)) && 16 & l))
          for (let p = 0; p < c.length; p++) r(c[p], t, n, 2);
        u && o(s, t, n);
      }
      function Tt(
        e,
        t,
        n,
        o,
        r,
        i,
        { o: { nextSibling: a, parentNode: s, querySelector: l } },
        c
      ) {
        const d = (t.target = _t(t.props, l));
        if (d) {
          const l = d._lpa || d.firstChild;
          16 & t.shapeFlag &&
            (St(t.props)
              ? ((t.anchor = c(a(e), t, s(e), n, o, r, i)),
                (t.targetAnchor = l))
              : ((t.anchor = a(e)), (t.targetAnchor = c(l, t, d, n, o, r, i))),
            (d._lpa = t.targetAnchor && a(t.targetAnchor)));
        }
        return t.anchor && a(t.anchor);
      }
      const Nt = Rt,
        At = "components";
      function Et(e, t) {
        return Mt(At, e, !0, t) || e;
      }

Main:

const kt = (e) => e.__isTeleport;
      const St = "components";
      function Ct(e, t) {
        return Rt(St, e, !0, t) || e;
      }

☝️ this seems tied to possibly inline overlays and the way they are proxied. I will test with not naming those and see if that chunk disappears tomorrow.

@sean-perkins
Copy link
Collaborator Author

Ok, figured it out 🎉

The problem was not from this repo or this PR, but from the changes to the manual wrappers. Many of the manual wrappers had /*@__PURE__*/ applied to the defineComponent call, which is executed when the file is imported to create the constant value. This causes treeshaking to bail. Swapping those to wrapped function calls actually leads to a decrease in the bundle size:

 File                                 Size            Gzipped

  dist/js/chunk-vendors.18a3abfb.js    132.39 KiB     41.80 KiB
  dist/js/338.94328270.js              9.61 KiB       2.62 KiB
  dist/js/649.5b4cfc79.js              8.71 KiB       3.39 KiB
  dist/js/576.fda3a897.js              4.97 KiB       2.27 KiB
  dist/js/880.54275d29.js              4.97 KiB       2.27 KiB
  dist/js/app.2ad93169.js              3.86 KiB       1.82 KiB
  dist/js/753.16fe4f3e.js              1.10 KiB       0.60 KiB

This wasn't probably caught, as most of the manual wrappers are essential components for any Ionic application and are commonly imported into the bundle anyways.

Here is the updated dev-build of the branch to test with in the treeshaking repo: 6.1.3-dev.11651028387.10392a75

Copy link
Contributor

@liamdebeasi liamdebeasi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting some compilation errors with the latest dev build in Vite only:

src/views/About.vue:17:8 - error TS2322: Type '{}' is not assignable to type 'IntrinsicAttributes & Partial<{}> & Omit<Readonly<{ toString?: string | undefined; valueOf?: unknown; toLocaleString?: string | undefined; disabled?: boolean | undefined; ... 21 more ...; shape?: "round" | undefined; }> & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>'.
  Type '{}' is not assignable to type 'Omit<Readonly<{ toString?: string | undefined; valueOf?: unknown; toLocaleString?: string | undefined; disabled?: boolean | undefined; strong?: boolean | undefined; fill?: "default" | "clear" | "outline" | "solid" | undefined; ... 19 more ...; shape?: "round" | undefined; }> & VNodeProps & AllowedComponentProps & Co...'.
    Types of property 'toString' are incompatible.
      Type '() => string' is not assignable to type 'string & (() => string)'.

17       <ion-button @click="showModal">Open Modal</ion-button>
          ~~~~~~~~~~

I added a "vite" branch to https://github.com/liamdebeasi/ionic-vue-treeshaking. That example shows a Vite + Ionic Vue starter app with v6.1.3. It should build successfully -- then install your dev build and try and run npm run build again. You should get the above error.

@liamdebeasi
Copy link
Contributor

liamdebeasi commented Apr 11, 2023

Did a bit more digging. This issue can be fixed by setting Container.name instead of Container.displayName.

When Vue gets the component name, it will use displayName if it is a functional component: https://github.com/vuejs/core/blob/ae5a9323b7eaf3dfa11b2a442a02faa992f88225/packages/runtime-core/src/component.ts#L1033-L1040

However, it will also fall back to name. If the component is not a functional component, it will also use name. It seems safer to always set name instead.


Vue Dev Tools appears to only consider name:

https://github.com/vuejs/devtools/blob/74eccb02fb57d9f12acc3d890a09ac291d843fff/packages/app-frontend/src/features/components/ComponentTreeNode.vue#L30
https://github.com/vuejs/devtools/blob/74eccb02fb57d9f12acc3d890a09ac291d843fff/packages/app-frontend/src/features/components/SelectedComponentPane.vue#L20

@rwaskiewicz
Copy link
Member

@liamdebeasi I think I'm missing a little context. I'm not sure what the state of this PR was before 1549fe0 was pushed. Were there additional/different changes in the prior commit(s) that were causing your tree shaking concerns and build issues? Is https://github.com/liamdebeasi/ionic-vue-treeshaking up to date/could I use that with a dev build of this branch to test this out?

@liamdebeasi
Copy link
Contributor

Actually! It looks like this PR is no longer needed. I think I had an old version of the Vue Dev Tools installed.

Vue Dev Tools does indeed support displayName: https://github.com/vuejs/devtools/blob/74eccb02fb57d9f12acc3d890a09ac291d843fff/packages/shared-utils/src/util.ts#L342 (Issue: vuejs/devtools-v6#1494)

Updating to the latest Vue Dev Tools reveals that the components generated by stencil-ds-output-target show the component name correctly. Going to close this.

@rwaskiewicz
Copy link
Member

Does this mean we can also close #143 as well?

@liamdebeasi
Copy link
Contributor

Yep, I can close that.

@liamdebeasi
Copy link
Contributor

liamdebeasi commented Apr 12, 2023

Not sure what happened, but this is indeed still a bug.

Steps to repro

  1. Install Vue Dev Tools: https://devtools.vuejs.org/
  2. Clone https://github.com/liamdebeasi/vue-test
  3. Run npm install && npm run dev
  4. Open Vue Dev Tools with the "Components" tab active.
  5. Observe that there is an Anonymous Component.

Dev Build

Stencil Output Target Dev Build: 0.6.1-dev.11681238809.11549fe0
Ionic Dev Build with Stencil Dev Build: 7.0.2-dev.11681306962.1af4897a

You can install the Ionic Dev Build and follow the same steps above. Observe that in step 5 the component displayed is using its component name.

Install Example: npm install @ionic/vue@7.0.2-dev.11681306962.1af4897a @ionic/vue-router@7.0.2-dev.11681306962.1af4897a

@liamdebeasi liamdebeasi reopened this Apr 12, 2023
@liamdebeasi
Copy link
Contributor

liamdebeasi commented Apr 12, 2023

Here is the old code before I pushed my new fix: f528d2f

This code changed from using a functional component to a component with a setup call. I'm not sure if the treeshaking issues are still present with the previous/unused fix.

@rwaskiewicz
Copy link
Member

Screenshot 2023-04-12 at 9 58 50 AM

LGTM! Tested specifically on Firefox v112, Vue Dev Tools v6.5.0

liamdebeasi added a commit to ionic-team/ionic-framework that referenced this pull request Apr 12, 2023
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->


<!-- Issues are required for both bug fixes and features. -->
Issue URL: resolves #25199

Vue components show up as "Anonymous Component" in Vue Dev Tools. This
is caused by our use of `displayName` instead of `name`. This required a
fix in the Vue Output Target package. See
ionic-team/stencil-ds-output-targets#257 for
more info.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updates the Vue Output Target dependency
- Functional components created manually in Ionic Vue now set `name`
instead of `displayName`. Note: Non-functional components were never
impacted by this bug.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


Dev build: `7.0.2-dev.11681308435.141a05de`
liamdebeasi added a commit to ionic-team/ionic-framework that referenced this pull request Apr 17, 2023
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->


<!-- Issues are required for both bug fixes and features. -->
Issue URL: resolves #25199

Vue components show up as "Anonymous Component" in Vue Dev Tools. This
is caused by our use of `displayName` instead of `name`. This required a
fix in the Vue Output Target package. See
ionic-team/stencil-ds-output-targets#257 for
more info.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updates the Vue Output Target dependency
- Functional components created manually in Ionic Vue now set `name`
instead of `displayName`. Note: Non-functional components were never
impacted by this bug.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


Dev build: `7.0.2-dev.11681308435.141a05de`
liamdebeasi added a commit to ionic-team/ionic-framework that referenced this pull request Apr 19, 2023
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->


<!-- Issues are required for both bug fixes and features. -->
Issue URL: resolves #25199

Vue components show up as "Anonymous Component" in Vue Dev Tools. This
is caused by our use of `displayName` instead of `name`. This required a
fix in the Vue Output Target package. See
ionic-team/stencil-ds-output-targets#257 for
more info.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Updates the Vue Output Target dependency
- Functional components created manually in Ionic Vue now set `name`
instead of `displayName`. Note: Non-functional components were never
impacted by this bug.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->


Dev build: `7.0.2-dev.11681308435.141a05de`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: @ionic/vue components displayed as "<AnonymousComponent>" in vue3-devtools
4 participants