Commit 0ac3a015 authored by Oleksii Savran's avatar Oleksii Savran

Migrate to loadable-components

parent 37101d0d
......@@ -19,11 +19,7 @@
"plugins": [
"transform-object-rest-spread",
"babel-plugin-syntax-dynamic-import",
[
"./react-loadable-custom/babel.js",
{
"importName": "utilities/CustomReactLoadable"
}
]
"@loadable/babel-plugin"
]
}
......@@ -11,6 +11,8 @@
"test": "jest"
},
"dependencies": {
"@loadable/component": "^5.12.0",
"@loadable/server": "^5.12.0",
"axios": "^0.19.2",
"connected-react-router": "^6.8.0",
"express": "^4.17.1",
......@@ -45,6 +47,8 @@
"@babel/cli": "^7.10.1",
"@babel/core": "^7.10.2",
"@gringlobal/i18n": "*",
"@loadable/babel-plugin": "^5.12.0",
"@loadable/webpack-plugin": "^5.12.0",
"@types/enzyme": "^3.10.5",
"@types/jest": "^25.2.3",
"@types/node": "14.0.11",
......
......@@ -17,13 +17,8 @@
"inputSourceMap": false,
"sourceMaps": false,
"plugins": [
"@loadable/babel-plugin",
"transform-object-rest-spread",
"babel-plugin-syntax-dynamic-import",
[
"./react-loadable-custom/babel.js",
{
"importName": "utilities/CustomReactLoadable"
}
]
"babel-plugin-syntax-dynamic-import"
]
}
......@@ -9,7 +9,7 @@ const ManifestPlugin = require('webpack-manifest-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
const ReactLoadable = require('react-loadable/webpack');
const LoadablePlugin = require('@loadable/webpack-plugin');
const fs = require('fs');
// devserver configuration
......@@ -290,9 +290,10 @@ module.exports = {
],
}),
new ReactLoadable.ReactLoadablePlugin({
filename: 'react-loadable.json',
}),
// new ReactLoadable.ReactLoadablePlugin({
// filename: 'react-loadable.json',
// }),
new LoadablePlugin({ writeToDisk: true }),
],
optimization: {
......
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Loadable from 'react-loadable';
// import Loadable from 'react-loadable';
import { loadableReady } from '@loadable/component'
import { applyMiddleware, compose, createStore } from 'redux';
import thunk from 'redux-thunk';
import { I18nextProvider, withSSR } from 'react-i18next';
......@@ -93,7 +94,7 @@ if (__PRELOADED_STATE__ === undefined) {
});
} else {
// SSR
Loadable.preloadReady().then(() => {
loadableReady(() => {
reconfigureServiceAxios({ accessToken: store.getState().login.access_token });
ReactDOM.hydrate(
<Provider store={ store }>
......
......@@ -17,6 +17,8 @@
},
"dependencies": {
"@gringlobal/client": "*",
"@loadable/component": "^5.12.0",
"@loadable/server": "^5.12.0",
"@material-ui/core": "^4.10.1",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.44",
......@@ -61,6 +63,8 @@
"@babel/cli": "^7.10.1",
"@babel/core": "^7.10.2",
"@gringlobal/i18n": "*",
"@loadable/babel-plugin": "^5.12.0",
"@loadable/webpack-plugin": "^5.12.0",
"@types/enzyme": "^3.10.5",
"@types/jest": "^25.2.3",
"@types/node": "14.0.11",
......
import * as React from 'react';
import { renderToString } from 'react-dom/server';
import Loadable from 'react-loadable';
import { getBundles } from 'react-loadable/webpack';
import { ChunkExtractor } from '@loadable/server';
import { createMemoryHistory } from 'history';
import { StaticRouter } from 'react-router-dom';
......@@ -35,14 +34,10 @@ import ApiError from '@gringlobal/client/model/common/ApiError';
import sagas from 'core/action/saga';
// react-loadable webpack stats
import * as path from 'path';
import { readFileSync } from 'fs';
import { receiveSsrError } from 'core/action/serverInfo';
const reactLoadableStats = JSON.parse(readFileSync(path.join('./', 'react-loadable.json'), { encoding: 'utf8' }));
// console.log(`react-loadable stats: `, reactLoadableStats);
const webStats = path.resolve('../assets/loadable-stats.json',);
const prerenderer = (html, errHtml) => (req, res) => {
console.log('Init prerenderer, request url:', req.url);
......@@ -62,6 +57,11 @@ const prerenderer = (html, errHtml) => (req, res) => {
const search = req._parsedOriginalUrl.search;
const context = {};
const extractor = new ChunkExtractor({ statsFile: webStats, outputPath: path.resolve('target/app/assets'), entrypoints: ['gringlobal']});
// const nodeExtractor = new ChunkExtractor({ statsFile: nodeStats, outputPath: path.resolve('target/app/server') });
// const webExtractor = new ChunkExtractor({ statsFile: webStats, outputPath: path.resolve('target/app/assets') });
function setLocale() {
const locale = detectLocaleFromPath(config.frontendPath, pathname, 0);
// console.log('Detected locale for SSR is', locale);
......@@ -90,10 +90,9 @@ const prerenderer = (html, errHtml) => (req, res) => {
const pathWithoutLang = req.url.substr(initialLanguage !== defaultLanguage ? 3 : 0, req.url.length);
console.log(`<StaticRouter location="${pathWithoutLang}" basename="${basename}"`);
const direction = getDir(initialLanguage);
const modules = [];
const InitialView = (
<Loadable.Capture report={ (moduleName) => modules.push(moduleName) }>
extractor.collectChunks(
<ReduxProvider store={ store }>
<StylesProvider generateClassName={ generateClassName } sheetsRegistry={ sheets }>
<MuiThemeProvider theme={ theme(direction) }>
......@@ -105,20 +104,19 @@ const prerenderer = (html, errHtml) => (req, res) => {
</MuiThemeProvider>
</StylesProvider>
</ReduxProvider>
</Loadable.Capture>
)
);
const componentHTML = renderToString(InitialView);
const initialState = store.getState();
const titleState = store.getState().pageTitle.title;
// console.log('react-loadable modules', modules);
const bundles = getBundles(reactLoadableStats, modules);
// console.log(`react-loadable bundles`, bundles);
const bundleStyles = bundles.filter((bundle) => bundle.file.endsWith('.css'));
// console.log(`react-loadable bundleStyles`, bundleStyles);
const bundleScripts = bundles.filter((bundle) => bundle.file.endsWith('.js'));
// console.log(`react-loadable bundleScripts`, bundleScripts);
// You can now collect your script tags
const scriptTags = extractor.getScriptTags(); // or extractor.getScriptElements();
// You can also collect your "preload/prefetch" links
const linkTags = extractor.getLinkTags(); // or extractor.getLinkElements();
// And you can even collect your style tags (if you use "mini-css-extract-plugin")
const styleTags = extractor.getStyleTags(); // or extractor.getStyleElements();
if (process.env.DEBUG) {
console.log('componentHTML:', componentHTML);
......@@ -138,15 +136,11 @@ const prerenderer = (html, errHtml) => (req, res) => {
return html.replace(/SERVER_RENDERED_(CSS|STATE|HTML|TITLE|I18NSTORE|DIR|LANG|HEADLINKS|BUNDLECSS|BUNDLESCRIPTS)/g, (match, x) => {
// console.log(`Injecting ${match}`);
switch (match) {
case 'SERVER_RENDERED_BUNDLECSS': return bundleStyles.map((style) => {
return `<link href="${style.file}" rel="stylesheet"/>`;
}).join('\n');
case 'SERVER_RENDERED_BUNDLESCRIPTS': return bundleScripts.map((bundle) => {
return `<script src="${bundle.file}"></script>`;
case 'SERVER_RENDERED_BUNDLECSS': return styleTags;
case 'SERVER_RENDERED_BUNDLESCRIPTS': return scriptTags;
// alternatively if you are using publicPath option in webpack config
// you can use the publicPath value from bundle, e.g:
// return `<script src="${bundle.publicPath}"></script>`
}).join('\n');
case 'SERVER_RENDERED_CSS': return sheets.toString();
case 'SERVER_RENDERED_STATE': return serialize(initialState, { isJSON: true });
case 'SERVER_RENDERED_HTML': return componentHTML;
......@@ -154,7 +148,7 @@ const prerenderer = (html, errHtml) => (req, res) => {
case 'SERVER_RENDERED_I18NSTORE': return serialize(initialI18nStore, { isJSON: true });
case 'SERVER_RENDERED_DIR': return serialize(getDir(initialLanguage), { isJSON: false });
case 'SERVER_RENDERED_LANG': return serialize(initialLanguage, { isJSON: false });
case 'SERVER_RENDERED_HEADLINKS': return languageLinks.join('');
case 'SERVER_RENDERED_HEADLINKS': return `${linkTags}${languageLinks.join('')}`;
default: console.log(`Unrecognized variable in ssr-template.html: ${match}`); return '';
}
});
......
import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
// import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
import loadable from '@loadable/component';
// model
import IRoute from '@gringlobal/client/model/common/IRoute';
const loadBrowsePage = /* #__LOADABLE__ */ () => import('accession/ui/AccessionBrowsePage');
const loadDisplayPage = /* #__LOADABLE__ */ () => import('accession/ui/AccessionDetailsPage');
const publicRoutes: IRoute[] = [
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "accession" */ 'accession/ui/AccessionBrowsePage'),
}),
component: loadable(loadBrowsePage),
path: '/a',
},
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "accession" */'accession/ui/AccessionDetailsPage'),
}),
component: loadable(loadDisplayPage),
path: '/a/:id',
},
];
......
import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
// import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
import loadable from '@loadable/component';
// model
import IRoute from '@gringlobal/client/model/common/IRoute';
......@@ -6,16 +7,12 @@ import IRoute from '@gringlobal/client/model/common/IRoute';
const publicRoutes: IRoute[] = [
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "cooperator" */ 'cooperator/ui/BrowsePage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "cooperator" */ 'cooperator/ui/BrowsePage')),
path: '/cooperator',
},
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "cooperator" */'cooperator/ui/DetailsPage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "cooperator" */'cooperator/ui/DetailsPage')),
path: '/cooperator/:id',
},
];
......
import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
// import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
import loadable from '@loadable/component';
// model
import IRoute from '@gringlobal/client/model/common/IRoute';
......@@ -6,9 +7,7 @@ import IRoute from '@gringlobal/client/model/common/IRoute';
const publicRoutes: IRoute[] = [
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "cooperator" */ 'inventory/ui/InventoryBrowsePage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "cooperator" */ 'inventory/ui/InventoryBrowsePage')),
path: '/inventory',
},
// {
......
import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
// import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
import loadable from '@loadable/component';
import { UserRole } from '@gringlobal/client/model/user/User';
// model
......@@ -7,31 +8,23 @@ import IRoute from '@gringlobal/client/model/common/IRoute';
const publicRoutes: IRoute[] = [
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "request" */ 'request/ui/RequestBrowsePage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "request" */ 'request/ui/RequestBrowsePage')),
path: '/request',
},
{
exact: true,
auth: [ UserRole.USER ],
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "request" */ 'request/ui/RequestAddPage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "request" */ 'request/ui/RequestAddPage')),
path: '/request/new',
},
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "request" */'request/ui/CheckList'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "request" */'request/ui/CheckList')),
path: '/request/checklist/:requestId(\\d+)?',
},
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "request" */'request/ui/RequestDetailsPage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "request" */'request/ui/RequestDetailsPage')),
path: '/request/:id(\\d+)',
},
];
......
import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
import loadable from '@loadable/component';
// model
import IRoute from '@gringlobal/client/model/common/IRoute';
......@@ -6,15 +6,11 @@ import IRoute from '@gringlobal/client/model/common/IRoute';
const publicRoutes: IRoute[] = [
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "taxonomy" */ 'taxonomy/ui/TaxonomySpeciesBrowsePage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "taxonomy" */ 'taxonomy/ui/TaxonomySpeciesBrowsePage')),
path: '/t/species',
}, {
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "taxonomy" */ 'taxonomy/ui/TaxonomyGenusBrowsePage'),
}),
component: loadable(() => import(/* webpackMode:"lazy", webpackChunkName: "taxonomy" */ 'taxonomy/ui/TaxonomyGenusBrowsePage')),
path: '/t/genus',
},
// {
......
import Loadable from '@gringlobal/client/utilities/CustomReactLoadable';
import loadable from '@loadable/component';
// model
import IRoute from '@gringlobal/client/model/common/IRoute';
......@@ -6,22 +6,16 @@ import IRoute from '@gringlobal/client/model/common/IRoute';
const publicRoutes: IRoute[] = [
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "user" */'user/ui/LoginPage'),
}),
component: loadable(/* #__LOADABLE__ */ () => import(/* webpackMode:"lazy", webpackChunkName: "user" */'user/ui/LoginPage')),
path: '/login',
},
{
exact: true,
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "user" */ 'user/ui/admin/BrowsePage'),
}),
component: loadable(/* #__LOADABLE__ */ () => import(/* webpackMode:"lazy", webpackChunkName: "user" */ 'user/ui/admin/BrowsePage')),
path: '/user',
},
{
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "user" */'user/ui/admin/DetailsPage'),
}),
component: loadable(/* #__LOADABLE__ */ () => import(/* webpackMode:"lazy", webpackChunkName: "user" */'user/ui/admin/DetailsPage')),
path: '/user/:uuid',
},
];
......
......@@ -186,6 +186,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.10.1"
"@babel/plugin-syntax-dynamic-import@^7.7.4":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
"@babel/plugin-syntax-json-strings@^7.8.3":
version "7.8.3"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
......@@ -243,7 +250,7 @@
core-js-pure "^3.0.0"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.7", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.10.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839"
integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==
......@@ -1274,6 +1281,35 @@
npmlog "^4.1.2"
write-file-atomic "^2.3.0"
"@loadable/babel-plugin@^5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@loadable/babel-plugin/-/babel-plugin-5.12.0.tgz#de18d4637eb8f4bdecd694a6737880b3e2094d4c"
integrity sha512-hb4TDUalaGogsCASEi0fD9Jn0Y2nQybupGgJQAxmx2KrLKxRoWfg78bJMabvownonsq3MEWgUWqb0c3m0uX9vQ==
dependencies:
"@babel/plugin-syntax-dynamic-import" "^7.7.4"
"@loadable/component@^5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@loadable/component/-/component-5.12.0.tgz#34d056d15f53dc08d04e9203cad6867cf4f7306c"
integrity sha512-eDG7FPZ8tCFA/mqu2IrYV6eS+UxGBo21PwtEV9QpkpYrx25xKRXzJUm36yfQPK3o7jXu43xpPkwiU4mLWcjJlw==
dependencies:
"@babel/runtime" "^7.7.7"
hoist-non-react-statics "^3.3.1"
"@loadable/server@^5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@loadable/server/-/server-5.12.0.tgz#61069d9cf6151e7d22c25f54264165556a101634"
integrity sha512-Sb4hPz3vPf2z8GMPlW2kSiDwy3Lv38LhVFEW/Uy3BJqHxNlollJDD3rXQ6zmCZY5S/x/m1tPox8UyIBhcr8SZg==
dependencies:
lodash "^4.17.15"
"@loadable/webpack-plugin@^5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@loadable/webpack-plugin/-/webpack-plugin-5.12.0.tgz#b28c6e7a979e9c2f8d8b743a634de0ede124c76f"
integrity sha512-9G/DOSvR0BZHF8DCd7jWTVEjfLnyLKB+S5KhBOSCK8pTMwDcTKeb0oVd4iwPyeAfPAN4ibqN90r9qnSKnJ+WEQ==
dependencies:
mkdirp "^0.5.1"
"@material-ui/core@^4.10.1":
version "4.10.1"
resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.10.1.tgz#e3db4ca55d2af6cc23a1159ef5c32ad97c43c39c"
......@@ -7034,7 +7070,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.2.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment