#reactjs #material-ui #next.js #styled-components #i18next
#reactjs #material-ui #next.js #styled-компоненты #i18next
Вопрос:
У меня был проект с Next 8 и пользовательским узлом server.js файл, который обрабатывает маршрутизацию, был хорошим и быстрым, но у него не было material ui. Я добавил material ui и обновил проект до Next 9.4.4 и удалил пользовательский сервер. но поскольку я добавил material UI даже на старом сервере, это происходит очень медленно! Я перепробовал много решений, но ни одно из них не сработало. изменение маршрутов занимает до 30 секунд! добавление текста и сохранение занимает 10-15 секунд! режим разработки выполняется очень медленно. можете ли вы предложить мне решения?
_app.js
import React from 'react';
import App from 'next/app';
import * as Sentry from '@sentry/browser';
import cookies from 'next-cookies';
import Router from 'next/router';
import NProgress from 'nprogress';
import NextSeo from 'next-seo';
import { Provider } from 'react-redux';
import { ThemeProvider as StyledThemeProvider } from 'styled-components';
import { ThemeProvider } from '@material-ui/core/styles';
import { ToastContainer } from 'react-toastify';
import withRedux from 'next-redux-wrapper';
import withReduxSaga from 'next-redux-saga';
import { FlexContainer, theme as styledTheme } from '../config/globalStyles';
import materialTheme from '../config/theme';
import defaultSEOConfig from '../next-seo.config';
import createStore from '../config/store';
import { isCompatibleBrowser } from '../config/helpers';
import { appWithTranslation } from '../config/i18n';
import withGA from '../services/common/withGA';
import { getGAKey } from '../config/ga';
import Text from '../components/atoms/Text';
import { confirm } from '../config/confirm';
import { setCommonState } from '../redux/actions';
import InfoBar from '../components/molecules/InfoBar';
import 'rc-time-picker/assets/index.css';
import 'react-responsive-carousel/lib/styles/carousel.min.css';
import '../static/css/general.css';
Sentry.init({ dsn:"KEY" });
Router.onRouteChangeStart = () => {
NProgress.start();
};
Router.onRouteChangeComplete = () => NProgress.done();
Router.onRouteChangeError = () => NProgress.done();
const legalInformation = (
<StyledThemeProvider theme={styledTheme}>
legalInformation
</StyledThemeProvider>
);
const acceptLegal = () => {
document.cookie = `acceptedLegal=1; path=/; max-age=${86400 * 365}`;
};
class MyApp extends App {
static async getInitialProps(appContext) {
const appProps = await App.getInitialProps(appContext);
const { acceptedLegal, isAdminNavigation } = cookies(appContext.ctx);
const userAgent = appContext.ctx.req
? appContext.ctx.req.headers['user-agent']
: navigator.userAgent;
const oldBrowser = !isCompatibleBrowser(userAgent);
return { ...appProps, acceptedLegal, isAdminNavigation, oldBrowser };
}
componentWillMount() {
const { store, isAdminNavigation } = this.props;
const isOpen = isAdminNavigation === 'true';
store.dispatch(setCommonState('adminNavigation', isOpen, 'header'));
}
componentDidCatch(error, errorInfo) {
Sentry.withScope(scope => {
Object.keys(errorInfo).forEach(key => {
scope.setExtra(key, errorInfo[key]);
});
Sentry.captureException(error);
});
super.componentDidCatch(error, errorInfo);
}
renderCookieModal() {
const { acceptedLegal } = this.props;
if (!acceptedLegal amp;amp; typeof document !== 'undefined')
confirm({
title: 'Cookies Policy',
message: legalInformation,
confirmLabel: 'I accept',
cancelLabel: "I don't accept",
onConfirm: acceptLegal,
reactConfirmAlertOptions: {
closeOnEscape: false,
closeOnClickOutside: false,
},
closeOnCancel: false,
});
}
render() {
const { Component, pageProps, store, oldBrowser } = this.props;
if (typeof window !== 'undefined' amp;amp; window.HubSpotConversations) {
if (Router.router.route !== '/home') {
if (window.HubSpotConversations.widget.status().loaded) {
window.HubSpotConversations.widget.remove();
}
}
}
return (
<StyledThemeProvider theme={styledTheme}>
<ThemeProvider theme={materialTheme}>
<NextSeo config={defaultSEOConfig} />
<Provider store={store}>
<FlexContainer>
<div>
{oldBrowser amp;amp; (
<InfoBar
content="You’re using an old or incompatible browser. Please use the latest version of Google Chrome or Firefox for an issue-free experience."
palette="warning"
/>
)}
</div>
<div>
<Component {...pageProps} />
</div>
</FlexContainer>
<ToastContainer style={{ zIndex: 10001 }} />
{this.renderCookieModal()}
</Provider>
</ThemeProvider>
</StyledThemeProvider>
);
}
}
const gaApp = appWithTranslation(withGA(getGAKey(), false, Router)(MyApp));
export default withRedux(createStore)(withReduxSaga(gaApp))
_document.js
import React from 'react';
import getConfig from 'next/config';
import Document, { Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet as StyledComponentSheets } from 'styled-components';
import { ServerStyleSheets as MaterialUiServerStyleSheets } from '@material-ui/styles';
const { publicRuntimeConfig } = getConfig();
class MyDocument extends Document {
render() {
return (
<html lang="en">
<Head>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<meta httpEquiv="Content-Security-Policy" content="upgrade-insecure-requests" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
{this.props.styleTags}
<link
rel="apple-touch-icon"
sizes="57x57"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-57x57.png`}
/>
<link
rel="apple-touch-icon"
sizes="60x60"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-60x60.png`}
/>
<link
rel="apple-touch-icon"
sizes="72x72"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-72x72.png`}
/>
<link
rel="apple-touch-icon"
sizes="76x76"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-76x76.png`}
/>
<link
rel="apple-touch-icon"
sizes="114x114"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-114x114.png`}
/>
<link
rel="apple-touch-icon"
sizes="120x120"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-120x120.png`}
/>
<link
rel="apple-touch-icon"
sizes="144x144"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-144x144.png`}
/>
<link
rel="apple-touch-icon"
sizes="152x152"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-152x152.png`}
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href={`${publicRuntimeConfig.staticFolder}/favicons/apple-icon-180x180.png`}
/>
<link
rel="icon"
type="image/png"
sizes="192x192"
href={`${publicRuntimeConfig.staticFolder}/favicons/android-icon-192x192.png`}
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href={`${publicRuntimeConfig.staticFolder}/favicons/favicon-32x32.png`}
/>
<link
rel="icon"
type="image/png"
sizes="96x96"
href={`${publicRuntimeConfig.staticFolder}/favicons/favicon-96x96.png`}
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href={`${publicRuntimeConfig.staticFolder}/favicons/favicon-16x16.png`}
/>
<link
rel="manifest"
href={`${publicRuntimeConfig.staticFolder}/favicons/manifest.json`}
/>
{/* <link href="https://fonts.googleapis.com/css?family=Noto Sansamp;display=swap" rel="stylesheet" /> */}
<link
href="https://fonts.googleapis.com/css2?family=Noto Sans:wght@400;700amp;display=swap"
rel="stylesheet"
/>
{/* <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto Sans:300,400,500,700amp;display=swap" /> */}
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700amp;display=swap"
/>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material Icons" />
<meta name="msapplication-TileColor" content="#009ce1" />
<meta
name="msapplication-TileImage"
content={`${publicRuntimeConfig.staticFolder}/favicons/ms-icon-144x144.png`}
/>
<meta name="theme-color" content="#009ce1" />
<script
type="text/javascript"
id="hs-script-loader"
async
defer
src="//js.hs-scripts.com/5669472.js"
/>
{/* <script type="text/javascript" src="https://js.stripe.com/v3/" /> */}
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
);
}
}
MyDocument.getInitialProps = async ctx => {
const materialUiSheets = new MaterialUiServerStyleSheets();
const styledComponentSheet = new StyledComponentSheets();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
// enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
enhanceApp: App => props =>
styledComponentSheet.collectStyles(materialUiSheets.collect(<App {...props} />)),
enhanceComponent: Component => Component,
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<React.Fragment>
{initialProps.styles}
{materialUiSheets.getStyleElement()}
{styledComponentSheet.getStyleElement()}
</React.Fragment>
),
};
} finally {
styledComponentSheet.seal();
}
};
export default MyDocument;
package.json
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@aspnet/signalr": "^1.1.4",
"@babel/core": "^7.3.4",
"@date-io/moment": "1.x",
"@material-ui/core": "^4.9.7",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.47",
"@material-ui/pickers": "^3.2.10",
"@material-ui/styles": "^4.9.6",
"@sambego/storybook-state": "^1.3.4",
"@sentry/browser": "^5.15.4",
"@storybook/addon-actions": "^5.2.1",
"@storybook/addon-knobs": "^5.2.1",
"@storybook/addon-storysource": "^5.2.1",
"@storybook/addon-viewport": "^5.2.1",
"@storybook/react": "^5.2.1",
"@stripe/react-stripe-js": "^1.1.2",
"@stripe/stripe-js": "^1.3.2",
"@zeit/next-css": "^1.0.1",
"airbnb-browser-shims": "^3.2.0",
"axios": "^0.18.0",
"babel-loader": "^8.0.5",
"babel-plugin-inline-react-svg": "^1.1.1",
"babel-plugin-react-css-modules": "^4.0.0",
"babel-plugin-transform-es2017-object-entries": "^0.0.5",
"core-js": "^2.6.5",
"dotenv-load": "^1.1.0",
"emoji-js": "^3.4.1",
"emoji-mart": "^2.11.1",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.9.1",
"es6-promise": "^4.2.6",
"express": "^4.17.1",
"fast-deep-equal": "^2.0.1",
"formik": "^2.1.4",
"fuse.js": "^3.4.4",
"google-map-react": "^1.1.4",
"google-maps-react": "^2.0.2",
"highcharts": "^7.1.2",
"highcharts-react-official": "^2.2.2",
"isomorphic-unfetch": "^3.0.0",
"js-cookie": "^2.2.0",
"lodash": "^4.17.11",
"material-table": "^1.57.2",
"moment": "^2.24.0",
"moment-countdown": "^0.0.3",
"next": "9.4.4",
"next-compose-plugins": "^2.2.0",
"next-cookies": "^1.1.2",
"next-env": "^1.1.0",
"next-i18n-rewrites": "^0.0.7",
"next-i18next": "6.0.2",
"next-images": "^1.2.0",
"next-redux-saga": "^4.0.1",
"next-redux-wrapper": "^3.0.0-alpha.2",
"next-routes": "^1.4.2",
"next-seo": "^1.2.0",
"next-transpile-modules": "^3.0.0",
"nprogress": "^0.2.0",
"polished": "^3.0.3",
"prop-types": "^15.7.2",
"qs": "^6.9.0",
"rc-slider": "^8.6.11",
"rc-time-picker": "^3.7.2",
"react": "16.13.1",
"react-confirm-alert": "^2.4.1",
"react-copy-to-clipboard": "^5.0.1",
"react-dates": "^20.1.0",
"react-dom": "16.13.1",
"react-ga": "^2.6.0",
"react-grid-system": "^4.4.3",
"react-height": "^3.0.1",
"react-inlinesvg": "^0.8.4",
"react-items-carousel": "^2.8.0",
"react-lazyload": "^2.5.0",
"react-places-autocomplete": "^7.2.1",
"react-redux": "^6.0.1",
"react-responsive-carousel": "^3.1.50",
"react-sortable-hoc": "^1.9.1",
"react-star-rating-component": "^1.4.1",
"react-stripe-elements": "^4.0.1",
"react-swipeable": "^5.2.2",
"react-toastify": "^5.1.0",
"react-tooltip": "^3.11.2",
"react-with-direction": "^1.3.0",
"redux": "^4.0.1",
"redux-devtools-extension": "^2.13.8",
"redux-immutable": "^4.0.0",
"redux-saga": "^1.0.2",
"reduxsauce": "^1.0.1",
"reselect": "^4.0.0",
"styled-components": "4.1.3",
"webpack": "^4.0.1"
},
"devDependencies": {
"@babel/runtime-corejs2": "^7.8.7",
"@svgr/webpack": "^5.3.0",
"autoprefixer": "^9.3.1",
"babel-eslint": "^10.0.1",
"babel-jest": "^24.1.0",
"babel-loader": "^8.0.5",
"babel-plugin-inline-react-svg": "^1.1.1",
"babel-plugin-react-css-modules": "^4.0.0",
"babel-plugin-styled-components": "^1.10.7",
"babel-plugin-transform-es2017-object-entries": "^0.0.5",
"babel-plugin-transform-object-rest-spread": "^7.0.0-beta.3",
"babel-preset-airbnb": "^4.0.1",
"concurrently": "^4.1.0",
"eslint": "^5.16.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-prettier": "^4.0.0",
"eslint-plugin-import": "2.14.0",
"eslint-plugin-jsx-a11y": "6.1.1",
"eslint-plugin-prettier": "^3.0.1",
"eslint-plugin-react": "7.11.0",
"jest": "^24.1.0",
"postcss-initial": "^3.0.0",
"postcss-preset-env": "^6.4.0",
"prettier": "1.16.4"
}
Комментарии:
1. Это сумасшедшее количество зависимостей. Вам все это нужно? Похоже, что, скорее всего, именно это делает ваш сайт таким медленным. Размер вашего пакета должен быть огромным. Можете ли вы проверить, насколько он велик?