Express.js рдкрд░ рд░рд┐рдПрдХреНрдЯ рдРрдк рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рд░реЗрдВрдбрд░рд┐рдВрдЧ

рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рд░реЗрдВрдбрд░рд┐рдВрдЧ рдмрдирд╛рдиреЗ рдХреЗ рддрд░реАрдХреЗ рдкрд░ рдХрд┐рд╕реА рднреА рдЕрдзрд┐рдХ рдпрд╛ рдХрдо рдкреВрд░реНрдг рдореИрдиреБрдЕрд▓ рдХреА рдХрдореА рд╕реЗ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЬрдм рдореИрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рднрд╛рдЧ рдЧрдпрд╛, рддреЛ рдореЗрд░реЗ рдкрд╛рд╕ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП 2 рд╡рд┐рдХрд▓реНрдк рдереЗ, рдпрд╛ рддреЛ Next.js рдврд╛рдВрдЪреЗ рдХреЗ рд╕рд╛рде, рдпрд╛ Express.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗред

рд╣рдорд╛рд░реЗ рддреИрдпрд╛рд░ рдмрдбрд╝реЗ OTT рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП Next.js рдХреА рдЬрд╛рдБрдЪ рдореЗрдВ рд▓рдЧрднрдЧ 100 рдШрдВрдЯреЗ рдХрд╛ рд╕рдордп рд╡реНрдпрддреАрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рдХрдИ рд╕рдорд╕реНрдпрд╛рдПрдВ рдереАрдВ, рдЬрд┐рд╕рд╕реЗ рд╣рдордиреЗ рдЗрд╕реЗ рдордирд╛ рдХрд░ рджрд┐рдпрд╛ (рдореИрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦреВрдБрдЧрд╛), рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдПрдХ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдХрд▓реНрдк рдерд╛, Express .js , рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореИрдВ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдБред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдбреЗрдореЛ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рдХреЛрдб рдпрд╣рд╛рдБ рд╣реИ ред

рдЖрдЗрдП рдЖрд░рдВрднрд┐рдХ рдХрд╛рд░реНрдп рдФрд░ рдЬреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдерд╛, рдЙрд╕рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВред

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЙрд╕ рд╕рдордп рдерд╛:

  • рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рддреИрдпрд╛рд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ, рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдерд╛, рдЗрд╕рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдФрд░ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдиреАрдЪреЗ рд╕реВрдЪреАрдмрджреНрдз рд╣реИред
  • рд╕реНрдЯреЛрд░ рдХреЗ рд▓рд┐рдП Immutable.js рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
  • Redux sagas рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛
  • рдЧрддрд┐рд╢реАрд▓ рдЖрдпрд╛рдд рдХреЗ рд▓рд┐рдП React.lazy рдФрд░ React.suspense
  • рд░рд╛рдЙрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд░рд┐рдПрдХреНрдЯ-рд░рд╛рдЙрдЯрд░ 4
  • рдЖрдЗрдХрди рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо рдлрд╝реЙрдиреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЙрджреНрджреЗрд╢реНрдпреЛрдВ:

  • рд╕рдорд╛рдзрд╛рди рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП HTML рдХреЛ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
  • рдпрд╣ рд╕рдорд╛рдзрд╛рди рдореМрдЬреВрджрд╛ рдХреЛрдб рдХреЛ рдиреНрдпреВрдирддрдо рд░реВрдк рд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рдд рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЛ рдиреНрдпреВрдирддрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд╕рд╛рде рд░рд╣рдирд╛ рдЪрд╛рд╣рд┐рдПред
  • рдЙрди рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд╣реИрдВ
  • рдкреЗрдЬ рд╕реЗ рдПрд╕рдИрдУ рдореЗрдЯрд╛ рдбреЗрдЯрд╛ рд╕рд░реНрд╡рд░ рд╕реЗ рдЖрдирд╛ рдЪрд╛рд╣рд┐рдП
  • рдЫрд╡рд┐рдпреЛрдВ, рд╢реИрд▓рд┐рдпреЛрдВ рдФрд░ рдлреЛрдВрдЯ рдХреЛ рд╕рд░реНрд╡рд░ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдмрд╛рдж рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдП рдмрд┐рдирд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рднреЗрдЬрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
  • рдЧреНрд░рд╛рд╣рдХ рдкрдХреНрд╖ рдЧрддрд┐рд╢реАрд▓ рдЖрдпрд╛рдд рд╕рдорд░реНрдерди
  • рд╕рд░реНрд╡рд░ рдкрд░ рдкреНрд░реАрд▓реЛрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХреЗ рджреЛрд╣рд░рд╛рд╡ рд╕реЗ рдмрдЪреЗрдВ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдкрд░ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рддреЗ рд╕рдордп

рд╣рдордиреЗ рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рд╣реИ, рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИред

рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рдкреНрд░рд▓реЗрдЦрди рд╕реЗ, рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ SSR рдХреЗ рд▓рд┐рдП рдЖрдк рд░реЗрдВрдбрд░рдЯрд╛рдЙрд░рд┐рдВрдЧ () рдФрд░ рд╣рд╛рдЗрдбреНрд░реЗрдЯ () рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЖрдЧреЗ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ?

renderToString - рд╣рдорд╛рд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд░реНрд╡рд░ рдкрд░ HTML рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╣рд╛рдЗрдбреНрд░реЗрдЯ - рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдкрд░ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рдкреНрд░рддрд┐рдкрд╛рджрди рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдбреЗрдЯрд╛ рд▓реЛрдб рд╣реЛ рд░рд╣рд╛ рд╣реИ


рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд░реЗрдбрдХреНрд╕-рдХрдиреЗрдХреНрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рд░реЗрдВрдбрд░ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рд╣рдореЗрдВ рдЪрд╛рд╣рд┐рдПред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, hoc asyncConnect рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░, рдпрд╣ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд░рд╛рдЙрдЯрд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп рдпрд╣ рдХрдВрдкреЛрдиреЗрдВрдЯрдорд╛рдЙрдВрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

@asyncConnect([ { key: 'usersFromServer', promise: async ({ store: { dispatch } }) => { await dispatch(getUsersData()); return Promise.resolve(); }, }, ]) 

рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░ рдПрдХ Redux рд╕реНрдЯреЛрд░ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдм рдХреБрдЫ рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рд╣реИ, рдмрд╕ server.js рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдмрдирд╛рдПрдБред

рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рдкрд░, рд░реЗрдбрдСрдХреНрд╕ -рдХрдиреЗрдХреНрдЯ рд╕реЗ рд▓реЛрдбрдСрдирд╕реНрд╡рд░ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ , рд╣рдо рдбреЗрдЯрд╛ рдкреНрд░реАрд▓реЛрдб рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВред

рд░реЗрдВрдбрд░рдЯреЙрдЗрд░рд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рдо рдЕрдкрдиреЗ рдбреЗрдЯрд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдПрдЪрдЯреАрдПрдордПрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВред

рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдЬрд╝рд┐рдЯ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛ рдХреЛ getState () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ <script /> рдЯреИрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реИрд╢реНрд╡рд┐рдХ рд╡рд┐рдВрдбреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬрд┐рд╕рд╕реЗ рдлрд┐рд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рд╣рдо рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рдЧреЗрдЯ рдореЗрдВ рд╕реЗрдЯ рдХрд░реЗрдВрдЧреЗред

рдпрд╣ рд╕рдм рдХреБрдЫ рдРрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ

 app.get('*', (req, res) => { const url = req.originalUrl || req.url; const history = createMemoryHistory({ initialEntries: [url], }); const store = configureStore(initialState, history); const location = parseUrl(url); const helpers = {}; const indexFile = path.resolve('./build/main.html'); store.runSaga(sagas).toPromise().then(() => { return loadOnServer({ store, location, routes, helpers }) .then(() => { const context = {}; if (context.url) { req.header('Location', context.url); return res.send(302) } const css = new Set(); // CSS for all rendered React components const insertCss = (...styles) => styles.forEach(style => css.add(style._getCss())); const dynamicRoutes = [...routes]; dynamicRoutes[0].routes = [...dynamicRoutes[0].routes, ...StaticRoutesConfig]; const appContent = ReactDOMServer.renderToString( <StyleContext.Provider value={{ insertCss }}> <Provider store={store} key="provider"> <StaticRouter location={location} context={context}> <ReduxAsyncConnect routes={dynamicRoutes} helpers={helpers}/> </StaticRouter> </Provider> </StyleContext.Provider> ); const helmet = Helmet.renderStatic(); fs.readFile(indexFile, 'utf8', (err, data) => { if (err) { console.log('Something went wrong:', err); return res.status(500).send('Oops, better luck next time!'); } data = data.replace('__STYLES__', [...css].join('')); data = data.replace('__LOADER__', ''); data = data.replace('<div id=app></div>', `<div id=app>${appContent}</div>`); data = data.replace('<div id="app"></div>', `<div id="app">${appContent}</div>`); data = data.replace('<title></title>', helmet.title.toString()); data = data.replace('<meta name="description" content=""/>', helmet.meta.toString()); data = data.replace('<script>__INITIAL_DATA__</script>', `<script>window.__INITIAL_DATA__ = ${JSON.stringify(store.getState())};</script>`); return res.send(data); }); }); store.close(); }); }); 

ReduxAsyncConnect рдШрдЯрдХ рдореЗрдВ 2 рдкреНрд░реЙрдкреНрд╕ рдкрд╛рд╕ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:

рдкрд╣рд▓рд╛ рд╣рдорд╛рд░рд╛ рдорд╛рд░реНрдЧ рд╣реИ, рджреВрд╕рд░рд╛ рд╣реЗрд▓реНрдкрд░ (рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдп), рдЬрд┐рд╕реЗ рд╣рдо рдкреВрд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рддрдХ рдкрд╣реБрдВрдЪрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдПрдХ рддрд░рд╣ рдХрд╛ рд╕рдВрджрд░реНрднред

рд╕рд░реНрд╡рд░ рд░реВрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, StaticRouter рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рд╣реЗрд▓рдореЗрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ seo рдореЗрдЯрд╛ рдЯреИрдЧ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдШрдЯрдХ рдореЗрдВ рдЯреИрдЧ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд┐рд╡рд░рдг рд╣реИред

рдЯреИрдЧ рдХреЛ рд╕рд░реНрд╡рд░ рд╕реЗ рддреБрд░рдВрдд рдЖрдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ

 const helmet = Helmet.renderStatic(); helmet.title.toString() helmet.meta.toString() 

рд░реВрдЯрд┐рдВрдЧ рдХреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА рдПрдХ рд╕рд░рдгреА рдореЗрдВ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ рдкрдбрд╝рд╛, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИред

 export const StaticRoutesConfig = [ { key: 'usersGender', component: UsersGender, exact: true, path: '/users-gender/:gender', }, { key: 'USERS', component: Users, exact: true, path: '/users', }, { key: 'main', component: Users, exact: true, path: '/', }, { key: 'not-found', component: NotFound, }, ]; 

рд╕рд░реНрд╡рд░ рдкрд░ рдЖрдиреЗ рд╡рд╛рд▓реЗ url рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд░рд╛рдЙрдЯрд░ рдиреЗ рд╡рд╛рдВрдЫрд┐рдд рдбреЗрдЯрд╛ рдкреГрд╖реНрда рд╡рд╛рдкрд╕ рдХрд░ рджрд┐рдпрд╛ред

рдЧреНрд░рд╛рд╣рдХ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ?

рдпрд╣рд╛рдБ рдореБрдЦреНрдп рдЧреНрд░рд╛рд╣рдХ рдлрд╝рд╛рдЗрд▓ рд╣реИред рдЖрдк рдЦреЛрдЬ рдЗрдВрдЬрди рдФрд░ рдХреЛрдб рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реНрд▓реЗрд╖рд┐рдХреА рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдкреЗрдЬ рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдмреНрд░рд╛рдЙрдЬрд╝рд░ / index.js

 import 'babel-polyfill'; import { browserRender } from '../app/app'; browserRender(); 

App.js рдлрд╝рд╛рдЗрд▓

 const initialState = !process.env.IS_SERVER ? window.__INITIAL_DATA__ : {}; const history = process.env.IS_SERVER ? createMemoryHistory({ initialEntries: ['/'], }) : createBrowserHistory(); const store = configureStore(initialState, history); if (!process.env.IS_SERVER) { window.store = store; } const insertCss = (...styles) => { // eslint-disable-next-line no-underscore-dangle const removeCss = styles.map(style => style._insertCss()); return () => removeCss.forEach(dispose => dispose()); }; export const browserRender = () => { const dynamicRoutes = [...routes]; dynamicRoutes[0].routes = [...dynamicRoutes[0].routes, ...StaticRoutesConfig]; hydrate( <StyleContext.Provider value={{ insertCss }}> <Provider key="provider" store={store} > <ConnectedRouter history={history}> <ReduxAsyncConnect helpers={{}} routes={dynamicRoutes} /> </ConnectedRouter> </Provider> </StyleContext.Provider>, document.getElementById('app'), ); }; 

рд░реВрдЯрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рдХрдиреЗрдХреНрдЯреЗрдб -рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рд░рд╛рдЙрдЯрд░ / рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╕реЗ рдХрдиреЗрдХреНрдЯреЗрдб рд░рд╛рдЙрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ред

рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд░реЗрдВрдбрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП, рд╣рдо r eact-рд░реВрдЯрд░-рдбреЛрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╕реНрд╡рд┐рдЪ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдорд╛рд░реА рд░реВрдЯрд┐рдВрдЧ рдХрд╛ рдареАрдХ рд╕реЗ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 <Switch> <Route path="/about"> <About /> </Route> <Route path="/users"> <Users /> </Route> <Route path="/"> <Home /> </Route> </Switch> 

рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рд╣реА рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд░реНрдгрд┐рдд рдорд╛рд░реНрдЧреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд░рдгреА рд╣реИ, рдФрд░ рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рд░рд╛рдЙрдЯрд░-рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

App / index.js

 import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Helmet } from 'react-helmet'; import { renderRoutes } from 'react-router-config'; import { getRouterLocation } from './selectors/router'; @connect(state => ({ location: getRouterLocation(state), }), null) export default class App extends Component { static propTypes = { location: PropTypes.shape().isRequired, route: PropTypes.shape().isRequired, }; render() { const { route } = this.props; return ( <div> {renderRoutes(route.routes)} </div> ); } } 

рд╕рд░реНрд╡рд░ рдкрд░ рдХрд╛рд░реНрдиреЗрдЯреНрд╕, рд╕реНрдЯрд╛рдЗрд▓ рдФрд░ рдлреЛрдВрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ


рд╢реИрд▓рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП, рдЖрдЗрд╕реЛрдореЙрд░реНрдлрд┐рдХ-рд╢реИрд▓реА-рд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ , рдХреНрдпреЛрдВрдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рд╕реНрд▓реАрдкрд░-рд▓реЛрдбрд░ рд╡реЗрдмрдкреИрдХ рдореЗрдВ рд▓рдХреНрд╖реНрдп рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ: "рдиреЛрдб";

рд╡рд╣ рд╕рднреА рд╢реИрд▓рд┐рдпреЛрдВ рдХреЛ DOM рдореЗрдВ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╕рд░реНрд╡рд░ рд╕реЗ рддреИрдпрд╛рд░, рд╕реБрдВрджрд░ рдкреГрд╖реНрда рдЖрддрд╛ рд╣реИред рдЖрдк рд╢реИрд▓рд┐рдпреЛрдВ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рджреНрд╡рд╛рд░рд╛ рдХреИрд╢ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд╕рд░реНрд╡рд░ рдкрд░ рдЫрд╡рд┐рдпреЛрдВ рдФрд░ рдбрд╛рдЙрдирд▓реЛрдб рдлреЛрдВрдЯ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡реЗрдмрдкреИрдХ рд▓реЛрдбрд░ рдмреЗрд╕ 64-рдЗрдирд▓рд╛рдЗрди-рд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред

 { test: /\.(jpe?g|png|ttf|eot|otf|svg|woff(2)?)(\?[a-z0-9=&.]+)?$/, use: 'base64-inline-loader?limit=1000&name=[name].[ext]', }, 

рдпрд╣ рдЫрд╡рд┐рдпреЛрдВ рдФрд░ рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдлреЛрдВрдЯ рдХреЗ рд▓рд┐рдП рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдирддреАрдЬрддрди, рд╣рдореЗрдВ рдмреЗрд╕ 64 рд╕рд░реНрд╡рд░ рд╕реЗ рдПрдХ рдХреЛрдб рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ, рдЬреЛ рдмрд╛рдж рдореЗрдВ рд▓реЛрдб рдХрд┐рдП рдмрд┐рдирд╛ рдлреЛрдВрдЯ рдФрд░ рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдкреГрд╖реНрда рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред

рдХреНрд▓рд╛рдЗрдВрдЯ рдмрд┐рд▓реНрдб рдХреЗ рд▓рд┐рдП, рд╕рд╛рдорд╛рдиреНрдп url-loader рдФрд░ рдлрд╝рд╛рдЗрд▓-рд▓реЛрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ ред

 { test: /\.(eot|svg|otf|ttf|woff|woff2)$/, use: 'file-loader', }, { test: /\.(mp4|webm|png|gif)$/, use: { loader: 'url-loader', options: { limit: 10000, }, }, }, 

рд╣рд╛рдВ, рдЗрд╕рд╕реЗ рд▓реЛрдб рдХрд┐рдП рдЧрдП рдкреГрд╖реНрда рдХрд╛ рдЖрдХрд╛рд░ рдмрдврд╝ рдЧрдпрд╛, рд▓реЗрдХрд┐рди рдбрд╛рдЙрдирд▓реЛрдб рдЧрддрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рдерд╛ред

рд╕рд░реНрд╡рд░ рдкрд░ рдЧрддрд┐рд╢реАрд▓ рдЖрдпрд╛рдд


React.js рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдЖрдпрд╛рдд рдХрд░рдиреЗ рдФрд░ рд▓реЛрдбрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП React.lazy рдФрд░ React.suspense рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡реЗ SSR рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

рд╣рдордиреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛-рд▓реЛрдб рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛, рдЬреЛ рдПрдХ рд╣реА рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

 import Loadable from 'react-loadable'; import Loader from './Loader'; const LoadableComponent = Loadable({ loader: () => import('./my-component'), loading: Loader, }); export default class App extends React.Component { render() { return <LoadableComponent/>; } } 

рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░, рдпрд╣ рдХреЛрдб рд▓реЛрдбрд░ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ, рд╕рд░реНрд╡рд░ рдкрд░, рд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЙрдбреНрдпреВрд▓ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдирд┐рдореНрди рдХреЛрдб рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

 Loadable.preloadAll().then(() => { app.listen(PORT, () => { console.log(` Server is listening on port ${PORT}`); }); }); 

Loadable.preloadAll () - рдПрдХ рд╡рд╛рджрд╛ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдХрд╣рддрд╛ рд╣реИ рдХрд┐ рдореЙрдбреНрдпреВрд▓ рд▓реЛрдб рдХрд┐рдП рдЧрдП рд╣реИрдВред

рд╕рднреА рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рд╣рд▓ рд╣реЛ рдЧрдП рд╣реИрдВред

рдореИрдВрдиреЗ рд▓реЗрдЦ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣рд░ рдЪреАрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдорд┐рдиреА рдбреЗрдореЛ рдмрдирд╛рдпрд╛ред

Source: https://habr.com/ru/post/hi473210/


All Articles