I created an example app, blog post, and screencast about how to develop a Photo Gallery PWA with React and JHipster.
Blog: https://developer.okta.com/blog/2018/06/25/react-spring-boot-photo-gallery-pwa
Screencast: https://youtu.be/GlJWUqy1SJM
Source: https://github.com/oktadeveloper/okta-react-photo-gallery-example
Heroku: https://gallery-pwa.herokuapp.com/
You can see from the screencast and Heroku that i18n translations are slow to load and performance is poor. If I run Lighthouse on Heroku (after it wakes from sleeping), it scores a 39 for performance.

I think we can do better.
Create a React app with JHipster 5, deploy it to Heroku, test it with Lighthouse.
[email protected] /Users/mraible/dev/okta/okta-react-photo-gallery-example
โโโ (empty)
##### **JHipster configuration, a `.yo-rc.json` file generated in the root folder**
{
"generator-jhipster": {
"promptValues": {
"packageName": "com.okta.developer",
"nativeLanguage": "en"
},
"jhipsterVersion": "5.0.1",
"applicationType": "monolith",
"baseName": "gallery",
"packageName": "com.okta.developer",
"packageFolder": "com/okta/developer",
"serverPort": "8080",
"authenticationType": "oauth2",
"cacheProvider": "ehcache",
"enableHibernateCache": true,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "postgresql",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "maven",
"enableSwaggerCodegen": false,
"clientFramework": "react",
"useSass": false,
"clientPackageManager": "yarn",
"testFrameworks": [
"protractor"
],
"jhiPrefix": "jhi",
"enableTranslation": true,
"nativeLanguage": "en",
"languages": [
"en",
"fr"
],
"herokuDeployType": "git",
"herokuAppName": "gallery-pwa"
}
}
entityName.json files generated in the .jhipster directory
JDL entity definitions
entity Album (album) {
title String required,
description TextBlob,
created Instant
}
entity Photo (photo) {
title String required,
description TextBlob,
image ImageBlob required,
height Integer,
width Integer,
taken Instant,
uploaded Instant
}
entity Tag (tag) {
name String required minlength(2)
}
relationship ManyToOne {
Album{user(login)} to User,
Photo{album(title)} to Album
}
relationship ManyToMany {
Photo{tag(name)} to Tag{photo}
}
paginate Album with pagination
paginate Photo, Tag with infinite-scroll
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
git version 2.14.1
node: v9.8.0
npm: 6.1.0
yeoman: 2.0.2
yarn: 1.7.0
Docker version 18.03.1-ce, build 9ee9f40
docker-compose version 1.21.1, build 5a3f1a3
Related: jhipster info seems to work for getting the version on Linux, but not on Mac. Notice that it says (empty) for the JHipster version.
Yes definitely,
Dod you use master? can you check if the new lazy loading stuff makes any
difference?
Thanks & Regards,
Deepu
On Tue, Jun 26, 2018 at 2:42 PM Matt Raible notifications@github.com
wrote:
Overview of the issue
I created an example app, blog post, and screencast about how to develop a
Photo Gallery PWA with React and JHipster.Blog:
https://developer.okta.com/blog/2018/06/25/react-spring-boot-photo-gallery-pwa
Screencast: https://youtu.be/GlJWUqy1SJM
Source: https://github.com/oktadeveloper/okta-react-photo-gallery-example
Heroku: https://gallery-pwa.herokuapp.com/You can see from the screencast and Heroku that i18n translations are slow
to load and performance is poor. If I run Lighthouse on Heroku (after it
wakes from sleeping), it scores a 39 for performance.[image: screen shot 2018-06-26 at 6 28 50 am]
https://user-images.githubusercontent.com/17892/41911678-8bd823ce-790a-11e8-8185-6f2431309984.png
Motivation for or Use CaseI think we can do better.
Reproduce the errorCreate a React app with JHipster 5, deploy it to Heroku, test it with
Lighthouse.
JHipster Version(s)[email protected] /Users/mraible/dev/okta/okta-react-photo-gallery-example
โโโ (empty)JHipster configuration, a .yo-rc.json file generated in the root folder .yo-rc.json
file{
"generator-jhipster": {
"promptValues": {
"packageName": "com.okta.developer",
"nativeLanguage": "en"
},
"jhipsterVersion": "5.0.1",
"applicationType": "monolith",
"baseName": "gallery",
"packageName": "com.okta.developer",
"packageFolder": "com/okta/developer",
"serverPort": "8080",
"authenticationType": "oauth2",
"cacheProvider": "ehcache",
"enableHibernateCache": true,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "postgresql",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "maven",
"enableSwaggerCodegen": false,
"clientFramework": "react",
"useSass": false,
"clientPackageManager": "yarn",
"testFrameworks": [
"protractor"
],
"jhiPrefix": "jhi",
"enableTranslation": true,
"nativeLanguage": "en",
"languages": [
"en",
"fr"
],
"herokuDeployType": "git",
"herokuAppName": "gallery-pwa"
}
}JDL for the Entity configuration(s) entityName.json files generated in
the .jhipster directory JDL entity definitionsentity Album (album) {
title String required,
description TextBlob,
created Instant
}
entity Photo (photo) {
title String required,
description TextBlob,
image ImageBlob required,
height Integer,
width Integer,
taken Instant,
uploaded Instant
}
entity Tag (tag) {
name String required minlength(2)
}
relationship ManyToOne {
Album{user(login)} to User,
Photo{album(title)} to Album
}
relationship ManyToMany {
Photo{tag(name)} to Tag{photo}
}paginate Album with pagination
paginate Photo, Tag with infinite-scrollEnvironment and Tools
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)git version 2.14.1
node: v9.8.0
npm: 6.1.0
yeoman: 2.0.2
yarn: 1.7.0
Docker version 18.03.1-ce, build 9ee9f40
docker-compose version 1.21.1, build 5a3f1a3
Related: jhipster info seems to work for getting the version on Linux,
but not on Mac. Notice that it says (empty) for the JHipster version.โ
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864, or mute the
thread
https://github.com/notifications/unsubscribe-auth/ABDlF9PG_3HNIZKpA8anUCaFIW0bpgtnks5uAixFgaJpZM4U33EG
.
I tried with master and it's even slower (22). https://gallery-pwa-master.herokuapp.com/

Here's what changed when I upgraded. https://github.com/oktadeveloper/okta-react-photo-gallery-example/compare/jhipster-master
I upgraded by running rm -rf * in the directory of my app, then running jhipster --with-entities. Then I added back in the customizations that I made for the photo gallery.
FWIW, I created my blog demo with JHipster 5, Angular 6, and JWT. It doesn't score very good on performance either. App is at https://jhipster-5-demo.herokuapp.com, performance score seems to be in 40s or 50s.
That's really strange. lazy loading is supposed to give better
performance(btw note that it works only in prod profile)
So the performance is bad only in the lighthouse score or is it bad
visually when using the app as well? I didn't see any performance issue
visually when I was trying them.
I'll try lighthouse when I find time
Thanks & Regards,
Deepu
On Tue, Jun 26, 2018 at 8:06 PM Matt Raible notifications@github.com
wrote:
FWIW, I created my blog demo with JHipster 5, Angular 6, and JWT. It
doesn't score very good on performance either. App is at
https://jhipster-5-demo.herokuapp.com, performance score seems to be in
40s or 50s.Lighthouse Report.pdf
https://github.com/jhipster/generator-jhipster/files/2138345/Lighthouse.Report.pdfโ
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864#issuecomment-400410035,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABDlF7ljcQ7b8dpRdyT8W5NebTSkZ-7jks5uAngkgaJpZM4U33EG
.
Loading both React versions isn't great visually for me (clean load). I can clearly see the translation placeholder strings on the landing page whilst the loading bar scrolls and it finally catches up and fills in the correct content.
The Angular version isn't excellent, but still noticeably better. At least I don't see any translation placeholders anywhere. (Note that this might be made worse by my connection - seems to take quite a while to resolve the Heroku apps)
Out of interest does anyone have a report for the old Angular 1 version?
I have an older jh 4 app here, deployed via dokku on digital ocean (as far as I know). Can only test the login page as I don't have any credentials to that system at hand. It seems to be much better as that app scores 62 for performance (and I'm pretty sure there is much room for improvement in some custom code).
EDIT: @mraible Your blog app (angular) scores 78 on my machine currently (with mobile emulation, 3g with cpu slow down)
EDIT2: The react app scores 69. But it took forever to load it at first (which is maybe a heroku issue). And I can also see a short flickering of missing translations.
But still 4s for first meaningful paint (without loading any data from a database or so) seems to much imho. I think we should aim for 1 or 2 seconds in lighthouse.
When looking at the network tab I see we load both translations files, that seems not great when we have more supported languages to load everything there. Maybe we can accept a hard page reload when the language changes and only load that file or dump the json in the template maybe (something similar we do in our frontends). Also one og the scripts (I think vendor/3rd party) is still quite large with nearly 500kb gzipped. We aim for at most 200kb gzipped app and vendor bundle together and it feels quite snappy. Maybe we can reduce the amount of imported 3rd party stuff even more somehow?
The angular 1 app for example has 240kb vendor and 50kb app js bundle.

Just a plain bundle analyzer screenshot. I think we should have a look at the font awesome stuff (maybe load it async or so). Also lodash seems pretty large and not sure if we need everything from lodash or lodash at all. Also moment is quite large. Maybe we can check what features we need of moment and maybe replace it with a smaller library.

+1 to upfront load only default translation bundle. I also tried this before, however, noted translation issues on current page. I will see if I can get some time to re-look into that.
Also, we should think about splitting one big bundle to lazy loaded module specific bundles.
Yes we can optimise a lot. For lodash its suppose to treeshake and remove
unused. If its not working then we can just add the methods from lodash
that we are using directly to package instead of full package.
For moment tree shaking doesnt work due to its packaging so ya if there is
a lighter lib, we can consider switching to that.
I'm not happy with the new fontawesome stuff. I would prefer something
thats tree shakeable atleast.
Lets see what we can do.
On Wed, 27 Jun 2018, 9:43 am vishal423, notifications@github.com wrote:
+1 to upfront load only default translation bundle. I also tried this
before, however, noted translation issues on current page. I will see if I
can get some time to re-look into that.Also, we should think about splitting one big bundle to lazy loaded module
specific bundles.โ
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864#issuecomment-400574881,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABDlF3eOrkd8j16o1-wMfcxslzgasIiJks5uAzeIgaJpZM4U33EG
.
Regarding font awesome I will try to update to the latest version later. According to https://github.com/FortAwesome/react-fontawesome/issues/70#issuecomment-399874742 the treeshaking problems should be resolved, which will reduce the bundle size a lo I guess.
When it comes to lodash there is some 3rd party lib that depends on lodash (maybe it is even jhipster-react). I tried lodash-es and that seems to work fine with regards to treeshaking and imports.
For another comparison of v5 vs v4. www.21-points.com is currently running 4.6.2.
Performance score when not logged in is 23.

Performance score when I'm logged in is 17.

It is very confusing. On my machine the score for the login page is 63. But maybe a problem of running chromium?
EDIT: I used the dev tools lighthouse and not the extension. With the extension it is the same
So maybe I have found the problem why fontawesome is not treeshaked. Let me investigate a little bit further. It seems to be a problem of older babel, uglifyjs and fontawesome. https://github.com/FortAwesome/Font-Awesome/issues/13260


Some numbers:
Overall bundle size (gzipped) 300kb, before 470kb
More improvements possible:
Lodash comes from another lib. Not from the app directly. I added lodash-es and treeshaking works like a charm. Will check if react jhipster can use lodash-es instead of lodash maybe it is that. I also noticed in the normal dependecies there are some redux-devtools dependencies. Not sure, but they doesn't sound like deps that should end up in the application bundle. Futhermore, we have popper.js included and react-popper which brings an own (smaller) popper.js. Maybe the separate popper.js is not needed. And I'm pretty sure reactstrap is also not tree shaked properly as it look quite huge.
@mraible @atomfrede @vishal423 guys I'm planning to look into this weekend. If you guys have any updates let me know here so that I don't spent time on things you already did/found out
@deepu105 I will post my findings and what I did yesterday after this evening and maybe propose a PR for the fontawesome treeshaking (which might be easier to see than a comment here).
sure
Thanks & Regards,
Deepu
On Fri, Jun 29, 2018 at 9:59 AM Frederik Hahne notifications@github.com
wrote:
@deepu105 https://github.com/deepu105 I will post my findings and what
I did yesterday after this evening and maybe propose a PR for the
fontawesome treeshaking (which might be easier to see than a comment here).โ
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864#issuecomment-401279477,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABDlF_Cziej93Jv7Icqqy_IPWNq8fESOks5uBd5xgaJpZM4U33EG
.
@deepu105 , I didn't get much chance to look, however, I am sure caching isn't applied on i18n resources. I will move those under content directory. For lazy loading of remaining bundles, I still need to check.
I'll fix lazy loading, i'm already looking into it
Thanks & Regards,
Deepu
On Fri, Jun 29, 2018 at 2:51 PM vishal423 notifications@github.com wrote:
@deepu105 https://github.com/deepu105 , I didn't get much chance to
look, however, I am sure caching isn't applied on i18n resources. I will
move those under content directory. For lazy loading of remaining bundles,
I still need to check.โ
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864#issuecomment-401344817,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABDlF95g7DgWa5j0ur7qyWmwZkXXFxubks5uBiLOgaJpZM4U33EG
.
I can't make a proper PR today, so I try to summarize what I did to make font awesome tree shaked. But unfortunately I just realized the webpack build is not working as it has ts-lint warnings (no-submodule-imports). So without adding @fortawesome to the whitelist it may be better trying to adapt the webpack config, but here is what I did:
1st update fa deps
"@fortawesome/free-solid-svg-icons": "5.1.0",
"@fortawesome/fontawesome-svg-core": "1.2.0",
"@fortawesome/react-fontawesome": "0.1.0",
With this all imports must be changed to import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; (otherwise no package at all could be created).
2nd Update icon loader
import { faSort } from '@fortawesome/free-solid-svg-icons/faSort';
for each icon. --> Fontawesome is correctly tree shaked and the bundle size is decreased a lot.
import { faSort } from '@fortawesome/free-solid-svg-icons/faSort';
import { faEye } from '@fortawesome/free-solid-svg-icons/faEye';
import { faSync } from '@fortawesome/free-solid-svg-icons/faSync';
import { faBan } from '@fortawesome/free-solid-svg-icons/faBan';
import { faTrash } from '@fortawesome/free-solid-svg-icons/faTrash';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons/faArrowLeft';
import { faSave } from '@fortawesome/free-solid-svg-icons/faSave';
import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus';
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt';
import { faUser } from '@fortawesome/free-solid-svg-icons/faUser';
import { faHdd } from '@fortawesome/free-solid-svg-icons/faHdd';
import { faTachometerAlt } from '@fortawesome/free-solid-svg-icons/faTachometerAlt';
import { faHeart } from '@fortawesome/free-solid-svg-icons/faHeart';
import { faList } from '@fortawesome/free-solid-svg-icons/faList';
import { faTasks } from '@fortawesome/free-solid-svg-icons/faTasks';
import { faBook } from '@fortawesome/free-solid-svg-icons/faBook';
import { faClock } from '@fortawesome/free-solid-svg-icons/faClock';
import { faSignInAlt } from '@fortawesome/free-solid-svg-icons/faSignInAlt';
import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons/faSignOutAlt';
import { faThList } from '@fortawesome/free-solid-svg-icons/faThList';
import { faUserPlus } from '@fortawesome/free-solid-svg-icons/faUserPlus';
import { faWrench } from '@fortawesome/free-solid-svg-icons/faWrench';
import { faAsterisk } from '@fortawesome/free-solid-svg-icons/faAsterisk';
import { faFlag } from '@fortawesome/free-solid-svg-icons/faFlag';
import { faBell } from '@fortawesome/free-solid-svg-icons/faBell';
import { faHome } from '@fortawesome/free-solid-svg-icons/faHome';
import { faTimesCircle } from '@fortawesome/free-solid-svg-icons/faTimesCircle';
import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch';
import { library } from '@fortawesome/fontawesome-svg-core';
export const loadIcons = () => {
library.add(
faSort,
faEye,
faSync,
faBan,
faTrash,
faArrowLeft,
faSave,
faPlus,
faPencilAlt,
faUser,
faTachometerAlt,
faHeart,
faList,
faTasks,
faBook,
faHdd,
faClock,
faSignInAlt,
faSignOutAlt,
faWrench,
faThList,
faUserPlus,
faAsterisk,
faFlag,
faBell,
faHome
);
};
@deepu105, I have some changes for lazy loading of i18n bundles. Let me know if you would like those
Yes please
On Sat, 30 Jun 2018, 12:39 pm vishal423, notifications@github.com wrote:
@deepu105 https://github.com/deepu105, I have some changes for lazy
loading of i18n bundles. Let me know if you would like thoseโ
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864#issuecomment-401532942,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABDlF0cj-JGBwQOqgjtqn-5gcUXfLd1pks5uB1VegaJpZM4U33EG
.
It may also be worth looking at this problem with uglify:
https://twitter.com/greweb/status/1013122437884542978
@mraible, can you check with latest master as that contain caching improvements along with lazy loading of locale specific bundles.
I tried the latest code on master and it still doesn't do well when testing with Lighthouse.

Can you try the tree shaking approach for fontawesome? Just curious how
much that helps
Matt Raible notifications@github.com schrieb am Mo., 2. Juli 2018, 17:17:
I tried the latest code on master and it still doesn't do well when
testing with Lighthouse.[image: screen shot 2018-07-02 at 9 16 36 am]
https://user-images.githubusercontent.com/17892/42172258-bbc583ba-7dd8-11e8-963e-227ed16b007f.pngโ
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/jhipster/generator-jhipster/issues/7864#issuecomment-401839972,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAMaidsT98KOMoCO0bd3B1VrBEwLXFqPks5uCjmcgaJpZM4U33EG
.
Guys please check my PR, it should improve things a lot. I'm trying to treeshake lodash now
also RxJS is a huge dependency when enabling websockets.
I dont remember who added it but may be we need to look for a lightweight alternative for that as we dont need all RxJS functionality
Was this truly fixed, because I am getting <30% perf in lighthouse reports.
@EmmanuelMess the lighthouse reports are heavily dependent on your PC config and network so technically its very difficult to achieve great scores always for everyone. If you identify any improvement that can be done, don't hesitate to PR or tell us
I created an application last week with JHipster 5.4.2 and React. To test things out, I modified src/main/webapp/index.html to enable the service worker, then re-deployed to Cloud Foundry. Attached is my score after I logged in and ran Lighthouse.

It seemed strange that I only scored an 81 on PWA since I was able to install the app. So I ran Lighthouse again. The second time it scored 100 for a PWA.

Most helpful comment
Yes we can optimise a lot. For lodash its suppose to treeshake and remove
unused. If its not working then we can just add the methods from lodash
that we are using directly to package instead of full package.
For moment tree shaking doesnt work due to its packaging so ya if there is
a lighter lib, we can consider switching to that.
I'm not happy with the new fontawesome stuff. I would prefer something
thats tree shakeable atleast.
Lets see what we can do.
On Wed, 27 Jun 2018, 9:43 am vishal423, notifications@github.com wrote: