Keep Vue web components small

805 views
Skip to first unread message

Lauren Anderson

unread,
Apr 30, 2019, 8:49:51 PM4/30/19
to uport...@apereo.org

I see that some of the uPortal-contrib web components are including BootstrapVue “components” to add UI elements like dropdown menus. Unfortunately, adding even a single component from BootstrapVue drastically increases the size of the final Javascript file for your component. For example, when I run “npm run build” on the notification-icon project, the minified Javascript file is over 200 KB. This warning from webpack about the component size appears:

 

 warning  

 

asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).

This can impact web performance.

Assets: 

  notification-icon.js (486 KiB)

 

 warning  

 

entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.

Entrypoints:

  notification-icon (486 KiB)

      notification-icon.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/

 

If it’s the only component in your page that may be acceptable but as we build and add more components to uPortal, they impact performance and the user experience. I have experimented with BootstrapVue, Vuetify, and Vue Material and their A la carte system for importing just the component you want, but they all have the same component-bloat problem. These component frameworks are handy for building UI elements for single- or multi-page Vue applications where size isn’t an issue, and we use them for that purpose at our university, but I don’t think they are suitable for building web components intended for use in uPortal (or elsewhere).

 

For the same reason, I think we should divorce ourselves from jQuery and Bootstrap and write Vue components using as much of the native Vue functionality as possible and write the rest in plain old Javascript; well, ES6, ES2015, ECMAScript 2015, or whatever it’s called now. Including these libraries for one piece of functionality results in a massive amount of included code; 99% of which you don’t use. I know webpack does tree-shaking to reduce the amount of code but you still end up with large Javascript files as you can see above.

 

The best alternative I’ve found so far, short of building common UI elements myself—which I don’t want to do—is the Bulma CSS framework. It has all the standard UI elements we’re familiar with, like buttons, tabs, and dropdowns. It adds much less bloat to your final Javascript file because it’s essentially just CSS, separated into smaller SASS files so you include only what you need. In some cases there’s a little more work involved to wire up functionality when you click on things, but it’s not that hard. As an example, I added the Bulma dropdown to a project by importing the dropdown.sass file into my .vue file and it increased the final build by only 1.7K. Which is a lot less than 200K.

 

<style lang="scss" scoped>

    @import "~bulma/sass/utilities/_all.sass"; // required
    @import "~bulma/sass/components/dropdown.sass";

</
style>

 

If anyone is interested in using Bulma and would like some tips to get up to speed quickly, I’d be happy to explain. It’s pretty easy.

 

Lauren

 

lgo...@ed.ac.uk

unread,
May 1, 2019, 5:04:15 AM5/1/19
to uPortal Developers, laur...@byu.edu
Hi Lauren,

I'm not a fan of the web component bundle size either. We have been building a custom React front-end which is highly optimized and we have had to duplicate the notification icon just because of its size. We got around this issue elsewhere within our own project through the use of dynamic imports https://webpack.js.org/guides/code-splitting/. We created a separate webpack project that exported dynamic import methods which is injected into the uPortals header. We can easily within any portlet import what we need as and when we need it, and those libraries are cached and shared by every portlet in the page. This project not only benefits from webpack's tree shaking but it knows to combine common 3rd party libraries together. For example if you have 3 version of Vue, it will create a shared 3rd partly bundle between all three (legacy libraries are smaller!). So this approach avoids giant bundle sizes, is as optimized as any standalone SPA and works well within uPortal as it currently designed.


const
vue = async () => {
 
return import(
   
/* webpackChunkName: "dynamic-Vue" */
    'vue'
    ).then((module) => module.default);
};

const jQuery= async () => {
 
return import(
   
/* webpackChunkName: "dynamic-jQuery" */
    'jquery'
    ).then((module) => module.default);
};

export {
 
vue,
 
jQuery,

};


import {
  jQuery
,
  vue
,
} from 'DynamicImports';

const
[jquery, vue] = await Promise.all([
  jQuery
(),
  vue
(),
]);

// This syntax was from last year, I believe you can import dynamic imports directly now at the top of the class.

I'd need to check with my bosses but we could probably contribute this to the community if the community likes the idea.

Cheers,
Leigh

Julien Gribonvald

unread,
May 2, 2019, 4:37:15 AM5/2/19
to uport...@apereo.org

Hi all,

I'm facing on the same problems ! So any feedback, solutions, and contributions are welcome from now, but in a future it would be great to have a common way.

Leigh, I like your solution, it would be usefull to provide shared components/librairies. Lauren I already hear about the Bulma framework, but didn't watched on, but it seems that it's done on the ligth way ! and so could provide a good help to developpers for UIs in an easy and ligth way with UI components.

After from my point of view, web-components should not includes UI libraries as a web-component should be a really small UI element, but that's not easy everywhere/all the time. Also I try to avoid to use UI libraries as it's easy to reproduce elements in css and sometimes with few js only. My way is to avoid to import fat things for a small need/use, and in most case I gain some times to do manually the things (many peoples add bootstrap for only the "grid" or the dropdown !). Also remember with uPortal about some css framework that where used and how it's/it was complicated to modify/update/remove them.

Also Material provide beautiful tools for UI but is really fat and sometime complex to use it everywhere, so now with my teammates we use Material "patterns" but made only with custom css, it's easy to find the css of different elements and to apply them !

Julien

--
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.
Visit this group at https://groups.google.com/a/apereo.org/group/uportal-dev/.
--
Julien Gribonvald

Christian Murphy

unread,
May 2, 2019, 10:46:22 AM5/2/19
to uPortal Developers
Hey all!

Love the interest  in ensuring bundle size stays optimally small.
Bundle size has definitely been something that has been carefully considered when creating components.
There are a few considerations when it comes to bundle size that haven't been mentioned here.

Not all bytes in the bundle are equal. This post for Addy Osmani gives a good overview of the different performance considerations when it comes to JavaScript bundles.
https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4
Bundle load time is broken down into Download, Parse, Compile, and Execute phases.
Performance is also impacted by scripts loading inline in the main thread vs deferred loading, and cached vs non-cached scripts.

In the case of uPortal web components, some, if not most of the Download, Parse, and Compile cost is a one time cost on first page load.
Future page loads (when served from resource server or CDN) will pull from cache rather than re-downloading, re-parsing, re-compiling the scripts.
Execute is impacted by JavaScript that runs. CSS in JS (scoped Bootstrap) and SVGs in JS (FontAwesome) don't execute, and don't impact execution time in a significant way.
Script loading for web components is uPortal also deferred, so plain HTML can render nearly instantly, and then interactive web components can fill in later.

> I have experimented with BootstrapVue, Vuetify, and Vue Material and their A la carte system for importing just the component you want, but they all have the same component-bloat problem. These component frameworks are handy for building UI elements for single- or multi-page Vue applications where size isn’t an issue, and we use them for that purpose at our university, but I don’t think they are suitable for building web components intended for use in uPortal (or elsewhere).

The reason BootstrapVue, Vuetify, and VueMaterial current add so much weight to the bundle, has less to do with the framework and more to do with browser support.
In a post-IE world, we would be able to pull in the Bootstrap/Material/Bulma stylesheets as an @import in a style tag and bundle size would not be impacted at all. CSS would be delivered separately, as CSS.
IE throws a wrench in that, by not supporting Shadow DOM at all, meaning if we @import those styles apply to the entire page, not just this component, which can.
To work around this, we've scoped the styles and embedded them in the JavaScript bundle.
Dropping the IE work-arounds and polyfills for the dropdown-icon brings the total bundle size to less than 100kb.

> is the Bulma CSS framework

Bulma is good in it's own right, in in-person meetings there have been side conversations about adopting Bulma.
But uPortal has thus far, opted to stick Bootstrap to maintain UI consistency.
If we do choose to leverage Bulma, https://buefy.org is a good option for integrating Bulma and Vue together.

> We got around this issue elsewhere within our own project through the use of dynamic imports https://webpack.js.org/guides/code-splitting/.

Code splitting is another IE-compatible work-around to reducing bundle size through allowing some reuse.
Again, it's an IE work-around, because import is natively supported in ever browser except IE. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Browser_compatibility
Once IE support can be dropped, alternatives, like Pika web used along side HTTP 2, may become a more effective way to handle code reuse and caching.

Best Regards,

Christian Murphy

Lauren Anderson

unread,
May 2, 2019, 2:38:19 PM5/2/19
to Christian Murphy, uPortal Developers

Thank you, Christian for the explanation. Why is anyone still trying to support IE? At 2.6% usage, even Microsoft is dropping support. How about a simple message that says “This application will not run properly in this ancient and decrepit browser. Please try one of these other popular, modern browsers:” and provide links to install Chrome, Firefox, Safari, etc. Kill the beast!

 

Lauren

Jim Helwig

unread,
May 2, 2019, 2:53:19 PM5/2/19
to Lauren Anderson, Christian Murphy, uPortal Developers
We did something like this in uPortal Home because the initial load times in IE were almost unbearable. The first thing we do if you are using IE is display a Material dialog recommending something else. https://github.com/uPortal-Project/uportal-app-framework/pull/877


JimH

— 
Jim Helwig
Web Platforms & Services, UW-Madison

I see that some of the uPortal-contrib web components are including BootstrapVue “components” to add UI elements likedropdown menus. Unfortunately, adding even a single component from BootstrapVue drastically increases the size of the final Javascript file for your component. For example, when I run “npm run build” on the notification-icon project, the minified Javascript file is over 200 KB. This warning from webpack about the component size appears:
 
 warning  
 
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets: 
  notification-icon.js (486 KiB)
 
 warning  
 
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
  notification-icon (486 KiB)
      notification-icon.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.
 
If it’s the only component in your page that may be acceptable but as we build and add more components to uPortal, they impact performance and the user experience. I have experimented with BootstrapVue, Vuetify, and Vue Material and theirA la carte system for importing just the component you want, but they all have the same component-bloat problem. These component frameworks are handy for building UI elements for single- or multi-page Vue applications where size isn’t an issue, and we use them for that purpose at our university, but I don’t think they are suitable for building web components intended for use in uPortal (or elsewhere).
 
For the same reason, I think we should divorce ourselves from jQuery and Bootstrap and write Vue components using as much of the native Vue functionality as possible and write the rest in plain old Javascript; well, ES6, ES2015, ECMAScript 2015, or whatever it’s called now. Including these libraries for one piece of functionality results in a massive amount of included code; 99% of which you don’t use. I know webpack does tree-shaking to reduce the amount of code but you still end up with large Javascript files as you can see above.
 
The best alternative I’ve found so far, short of building common UI elements myself—which I don’t want to do—is theBulma CSS framework. It has all the standard UI elements we’re familiar with, like buttons, tabs, and dropdowns. It adds much less bloat to your final Javascript file because it’s essentially just CSS, separated into smaller SASS files so you include only what you need. In some cases there’s a little more work involved to wire up functionality when you click on things, but it’s not that hard. As an example, I added the Bulma dropdown to a project by importing the dropdown.sass file into my .vue file and it increased the final build by only 1.7K. Which is a lot less than 200K.
 

<style lang="scss" scoped>

    @import "~bulma/sass/utilities/_all.sass"; // required
    @import "~bulma/sass/components/dropdown.sass";

</
style>
 
If anyone is interested in using Bulma and would like some tips to get up to speed quickly, I’d be happy to explain. It’s pretty easy.
 
Lauren
 
-- 
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.
Visit this group at https://groups.google.com/a/apereo.org/group/uportal-dev/.
-- 
Julien Gribonvald
-- 
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.
Visit this group at https://groups.google.com/a/apereo.org/group/uportal-dev/.
-- 
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.
Visit this group at https://groups.google.com/a/apereo.org/group/uportal-dev/.

Message has been deleted

Julien Gribonvald

unread,
May 3, 2019, 4:16:54 AM5/3/19
to uport...@apereo.org

On my side (from France) we should not eliminate supported/upgraded browsers to avoid to exclude peoples without good computer acknowledge ! That's an accessibility rule if I'm not wrong.

After in middle and high schools we have more peoples with lower computer acknowledge than in universities. So we kept at least a compatibility for IE 11 but after some month we have now only 0,3% of use with this browser and 2,6 % with Edge. The main part use google chrome or safari (~40% each), and the remaining part use mainly firefox (7,3%).

Also we provide a message that tell to users to download and install a supported browser with the links to official documentations. After Christian Murphy already made a PR that purpose a such solution see here : https://github.com/Jasig/uPortal-start/pull/264, the problem with this solution is it use an external website...

@Christian Murphy: thanks for your explanations but there is a point of view that is really important for me, we should keep a really small bundle size for mobiles, now our users use mainly a mobile (71% of mobiles, 2% of tablet, and 26% of desktop) and from everywhere so we should optimize the download size. Also that's why we should go more on progressive web apps !

Julien

Le 02/05/2019 à 21:00, ther...@gmail.com a écrit :
Just echo'ing that sentiment. HAXcms will treat IE11 as effectively having no javascript. We're treating Edge (of today) w/ a watered down version of what we give people. I dug into the data as part of a recent talk if looking for additional data to back this opinion -- https://youtu.be/Akn6keIYZ3k?t=823

To unsubscribe from this group and stop receiving emails from it, send an email to uport...@apereo.org.

--
Julien Gribonvald

--
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to uport...@apereo.org.

--
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.

To unsubscribe from this group and stop receiving emails from it, send an email to uport...@apereo.org.

--
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.
Visit this group at https://groups.google.com/a/apereo.org/group/uportal-dev/.
--
Julien Gribonvald

lgo...@ed.ac.uk

unread,
May 3, 2019, 8:22:45 AM5/3/19
to uPortal Developers
Hi Christian,

I'm not a fan of describing Webpack as an IE workaround, that is a very misleading statement. Calling it a legacy browser workaround would probably be more appropriate and you will still have to support those for a while. I mean older versions of Firefox, older Chrome and I am sure Edge is missing a few things.

I totally 100% agree that Webpack will be replaced by esmodules but that will take some time. You can easily fix the fat bundle problem with Webpack (or RollUp, etc) now and replace that in time. I don't know if you realize this but a lot of the uPortal Vue web components are already using Webpack by using the vue-cli-service https://github.com/vuejs/vue-cli/blob/e376c00b2647ad6ce5b9d2c8750cb95f0263d49d/packages/%40vue/cli-service/package.json#L75. Ironically its Webpack that is creating the fat bundles so why not optimize those with code splitting. This would not impact on your current design, it just adds to it. I don't understand why this is problem or why living with fat bundles is the only solution for now. Our notification icon duplicate is about 50k in size using this method. 

You can also avoid dynamic imports by marking common libraries as external and pull them in that way https://forum.vuejs.org/t/vue-cli-adding-external-js-and-css-libraries/38946.

I'm surprised to hear that you are bundling pollyfills btw. You will always need pollyfills to satisfy bleeding edge features so why not have that as a separate project. 

Cheers,
Leigh

To unsubscribe from this group and stop receiving emails from it, send an email to uport...@apereo.org.
--
Julien Gribonvald

--
You received this message because you are subscribed to the Google Groups "uPortal Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uport...@apereo.org.

Christian Murphy

unread,
May 3, 2019, 12:58:14 PM5/3/19
to uPortal Developers
> we should keep a really small bundle size for mobiles
> everywhere so we should optimize the download size

We're all in agreement on this.
The question is what technique and technologies to use to do this.

> Also that's why we should go more on progressive web apps !

I agree, progressive web app technology in particular Service Workers can help to improve the user experience.

> I'm not a fan of describing Webpack as an IE workaround, that is a very misleading statement. I mean older versions of Firefox, older Chrome and I am sure Edge is missing a few things.

It is accurate, Webpack, used to bundle browser code, is an IE work around.
Bundlers exist get around single threaded request blocking and the lack of of effective module system.
HTTP 2 multiplexing and ES Modules resolved these issues at the standards and browser level.
All major browser, including long term support versions of Chrome and Firefox, support these standards, except IE and older versions of Edge.

> Ironically its Webpack that is creating the fat bundles so why not optimize those with code splitting. This would not impact on your current design, it just adds to it. I don't understand why this is problem or why living with fat bundles is the only solution for now

Code splitting a few imports in the component will result in the same amount of bytes being sent to the browser (slightly more due to webpack overhead).
It just shifts the bytes around so the webpack file size checker doesn't complain, hiding the problem, but not solving it.

> I'm surprised to hear that you are bundling pollyfills btw.

It doesn't bundle polyfills.
Polyfills are delivered separate.

Out of curiosity, what is the status on Edinburgh open sourcing the automatic polyfilling service that was developed on campus?

---

There are a few ways we can get client side performance wins, without sacrificing browser support.

One would be to pre-render pages on the server, then progressively add JavaScript in the background.
This would mean the first page render would always be static HTML, and a service worker would load take over for future page loads.
This would require running a Node server along side the Tomcat server to handle pre-rendering.

Another would be to make "modern" mode in vue cli work with web components.
Allowing one version for modern browsers and another version for IE to be generated, and allowing the browser to automatically decide which to load.
This approach is currently on hold because Vue's web component wrapper does not and will not support IE.

Best Regards,

Christian Murphy


To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.

lgo...@ed.ac.uk

unread,
May 6, 2019, 4:40:21 AM5/6/19
to uPortal Developers
Hi Christian,

Webpack is not an IE workaround it is a bundler and we both agree ES Modules will replace that technology. I said so in my last post. 

Code splitting a few imports in the component will result in the same amount of bytes being sent to the browser (slightly more due to webpack overhead).
It just shifts the bytes around so the webpack file size checker doesn't complain, hiding the problem, but not solving it.

I'm very confused now, our wires must be getting crossed. So you are not bundling third party libraries into your bundles? If you are then I don't understand how this statement is true. 3 web components with the same dependencies which are bundled are substantially larger as big as 3 web components that pull in third party libraries as globals. The browser can't tell whats in the bundle, so it will pull them down anyway. Yes you are moving bytes around but you are only downloading third party libraries once.

It doesn't bundle polyfills.
Polyfills are delivered separate.

I made that statement because you originally stated "Dropping the IE work-arounds and polyfills for the dropdown-icon brings the total bundle size to less than 100kb."

Out of curiosity, what is the status on Edinburgh open sourcing the automatic polyfilling service that was developed on campus?

Originally we were held back because of licensing issues. I believe those are resolved. Right now we simply don't have the resources to contribute to the community as we have a pressing deadline. We did have a discussion with Drew last week regarding making all of our projects open source. I believe there is a lot of interest in doing that. I'm a bit out of the loop on that. I doubt that will be done before I go, I leave at the end of May.

Cheers,
Leigh

Christian Murphy

unread,
May 6, 2019, 2:43:24 PM5/6/19
to uPortal Developers
> Webpack is not an IE workaround it is a bundler

And a major reason bundlers continue to be used is to work around IE restrictions.
Hence WebPack is an IE work around in this use-case. :)
Most of extended syntax, static analysis, and useful feature work is being handled by compilers, like babel, typescript, postcss, and vue-template-compiler. Not bundlers.

> So you are not bundling third party libraries into your bundles?

Some, Vue is extracted out by Vue CLI and provided in global script on the page.
The rest of the libraries are bundled.

WebPack could be use to achieve some additional reuse, but to do that, all components would need to be run through a single webpack bundler, and the config would need to be able to handle multiple languages, multiple frameworks, and needs to know how to pack each of those as web component.
While it's do-able, I question the ROI of writing and maintaining a massive webpack config to save ~200kb, vs leveraging ES Modules and letting browsers handle that for us.

> I made that statement because you originally stated "Dropping the IE work-arounds and polyfills for the dropdown-icon brings the total bundle size to less than 100kb."

Polyfills are applied directly to the page, not bundled.
Using Scoped CSS to work around the lack of Shadow DOM in IE, is the main contributor to bundle size that could be easily be removed.

> Why is anyone still trying to support IE?

Usually to support legacy campus systems.
E.G. Banner version 8 and below require IE, and a few universities are still migrating to a newer version that works cross browser.

In a very opportune announcement from Microsoft, the new Chromium based Edge browser will include an IE compatibility mode to ease the transition to modern browsers for educators and enterprises.
https://www.theverge.com/2019/5/6/18527875/microsoft-chromium-edge-new-features-build-2019
So this may not be a problem in a few months.

> How about a simple message that says “This application will not run properly in this ancient and decrepit browser. Please try one of these other popular, modern browsers:” and provide links to install Chrome, Firefox, Safari

I agree, dropping IE support is an easy approach to cleaning out legacy polyfills and work arounds, speeding up the portal.
And having a message alerting people to upgrade would be a good add to uPortal 5 to help ease the transition, and a requirement for the major release that will drop IE support (uPortal 6 or 7)
PRs are welcome!

---

Another thing to note, while bundle size is important, it is only one part of web performance.
Performance auditing tools like the Lighthouse https://developers.google.com/web/tools/lighthouse and WebHint https://webhint.io.
Highlight non-blocking script loading, compression (see this PR for ongoing discussion), and adding cache headers, as excellent opportunities to improve page load time.

Best Regards,

Christian Murphy

To unsubscribe from this group and stop receiving emails from it, send an email to uportal-dev...@apereo.org.
Reply all
Reply to author
Forward
0 new messages