generator-jhipster: React slow to load in production

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.

screen shot 2018-06-26 at 6 28 50 am
Motivation for or Use Case

I think we can do better.

Reproduce the error

Create a React app with JHipster 5, deploy it to Heroku, test it with Lighthouse.

JHipster Version(s)
gallery@0.0.0 /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 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

Environment and Tools

java version “1.8.0_144” Java™ SE Runtime Environment (build 1.8.0_144-b01) Java HotSpot™ 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.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 30 (29 by maintainers)

Most upvoted comments

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 .

@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 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
  );
};