CSR & SSR
Рендеринг на стороне клиента
Рендеринг на стороне сервера
- относится к размещению одностраничного приложения (SPA) вСервис-терминалПроцесс рендеринга фрагментов HTML, отправки их в браузер, а затем передачи их в браузер для связывания состояний и событий, чтобы стать полностью интерактивной страницей. (PS: содержимое SSR в этой статье касается изоморфных приложений.)
- Процесс рендеринга SSR:
- Сервер отвечает только за первый «рендеринг» (в прямом смысле только браузер может отображать страницу, сервер фактически генерирует HTML-контент), а затем возвращает его клиенту, клиентперениматьВзаимодействие со страницей (логика, такая как привязка событий), а затем при переключении маршрутизации на стороне клиента соответствующий контент отображается непосредственно через код JS, и рендеринг на стороне сервера больше не требуется (требуется только при обновлении страницы).
Зачем использовать ССР
преимущество:
- Более высокая скорость загрузки в верхней части страницы: не нужно ждать, пока JavaScript завершит загрузку и выполнение, прежде чем отобразить содержимое, быстрее увидеть полностью отрендеренную страницу и улучшить взаимодействие с пользователем.
-
более дружественный к SEO:
- Сканер может напрямую захватить отображаемую страницу. HTML-документ, возвращенный CSR в первый раз, представляет собой пустой узел (корень) и не содержит контента. Сканер не может проанализировать, какой контент содержится на вашем веб-сайте, поэтому он не может дать вам хороший рейтинг . SSR возвращает обработанный HTML-фрагмент с полным содержимым, чтобы поисковые роботы могли лучше анализировать и индексировать его.
- На основе старой версии поисковой системы: мы добавим заголовок и описание в html, чтобы сделать простую сео-оптимизацию, эти два не улучшат поисковый рейтинг по сути, но улучшат коэффициент конверсии сайта. Предоставьте веб-сайту больше описаний, чтобы у пользователей было желание кликнуть, тем самым улучшив рейтинг.
<title>首页标题</title>
<meta name="description" content="首页描述"></meta>
- На основании новой версии поисковой системы (полнотекстовый поиск): Недостаточно полагаться на два вышеупомянутых, чтобы дать веб-сайту хороший рейтинг, поэтому SSR необходим для предоставления большего количества контента веб-сайта.
недостаток:
- Высокое потребление производительности сервера
- Сложность проекта становится выше, и проблемы нужно искать между фронтендом, нодой и бэкендом
- Необходимо учитывать эксплуатацию и техническое обслуживание, применение и расширение машины SSR, что увеличивает стоимость эксплуатации и обслуживания (можно решить с помощью Serverless).
Что такое изоморфное применение
- Набор кода, который может выполняться как на сервере, так и на клиенте, называется изоморфным приложением.
- Создавайте визуализированный контент на сервере, чтобы пользователи могли видеть информативные страницы как можно раньше. В дополнение к чисто статическому контенту полное приложение также включает в себя различные реакции на события, взаимодействие с пользователем и многое другое. Это означает, что сценарии JavaScript должны выполняться на стороне браузера для завершения событий привязки, обработки асинхронных взаимодействий и т. д.
- С точки зрения производительности и взаимодействия с пользователем, рендеринг на стороне сервера должен отображать самую важную, основную и самую основную информацию о странице, в то время как на стороне браузера необходимо выполнять дополнительные расширенные функции, такие как рендеринг страницы и привязка событий для взаимодействия. Так называемый изоморфизм означает, что передняя и задняя части имеют общий набор кода или логики, и в этом наборе кода или логики идеальная ситуация состоит в том, чтобы судить о существующей структуре DOM и структуре, которая должна быть отображена в процессе дальнейшей обработки. рендеринг на стороне браузера.То же самое, если это то же самое, структура DOM не будет перерисовываться, и требуется только привязка событий.
- С этой точки зрения изоморфизм и рендеринг на стороне сервера различны. Изоморфизм больше похож на пересечение рендеринга на стороне сервера и рендеринга на стороне браузера. кода или Логика работает в унисон. Ядром изоморфизма является «тот же набор кодов», который представляет собой другое измерение с точки зрения двух концов.
Вручную создайте структуру SSR
- адрес проекта:https://github.com/yjdjiayou/react-ssr-demo
- В исходном коде проекта уже есть много комментариев, поэтому я не буду вводить здесь слишком много.
использоватьNext.js(Зрелая структура SSR)
- Вот лишь некоторые заслуживающие внимания знания и мой собственный опыт.официальная документация китайский документ
Установить
npx create-next-app project-name
Посмотреть package.json
{
"name": "next-demo-one",
"version": "0.1.0",
"private": true,
"scripts": {
// 默认端口 3000,想要修改端口用 -p
"dev": "next dev -p 4000",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "9.1.4",
"react": "16.12.0",
"react-dom": "16.12.0"
}
}
Head
- Следующая / главная роль - дать каждому набору страницы
<head>
Содержимое тега эквивалентно react-helmet
import Head from 'next/head'
export default () =>
<div>
<Head>
<title>My page title</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
<p>Hello world!</p>
</div>
getInitialProps
- Next.js имеет собственный набор спецификаций для получения данных, и запросы данных нужно размещать в
getInitialProps
Внутри, вместо того, чтобы быть помещенным в жизненный цикл компонента, он должен следовать его спецификациям. -
getInitialProps
Свойства входного объекта следующие:-
pathname
- часть пути URL -
query
- Запросная часть URL, которая преобразуется в объект. -
asPath
- фактический путь (включая часть запроса), отображаемый в браузере, какString
Типы -
req
- Объект HTTP-запроса (только на стороне сервера) -
res
- Объект возврата HTTP (только на стороне сервера) -
jsonPageRes
- Получить объект ответа данных(только на стороне клиента) -
err
- любые ошибки при рендеринге
-
- Когда страница загружается изначально,
getInitialProps
будет вызываться только на стороне сервера. Только когда трасса прыгает(Link
Переход к компоненту или переход к методу API), клиент выполнитgetInitialProps
.онлайн демо -
Только компоненты, размещенные в каталоге pages, его
getInitialProps
будет вызываться, подкомпоненты используютgetInitialProps
это недействительно- Поскольку все компоненты в каталоге pages по умолчанию являются перенаправленными компонентами, будут обрабатываться только перенаправленные компоненты. Next.js сначала вызовет компонент маршрутизации на
getInitialProps
метод, получить возвращенные данные какprops
Передайте его компоненту маршрутизации и, наконец, визуализируйте компонент маршрутизации.онлайн демо - Самый прямой способ получения данных дочерними компонентами выглядит следующим образом:
- Поскольку все компоненты в каталоге pages по умолчанию являются перенаправленными компонентами, будут обрабатываться только перенаправленные компоненты. Next.js сначала вызовет компонент маршрутизации на
function PageA(props){
const {childOneData,childTwoData} = props;
return <div>
<ChildOne childOneData/>
<ChildTwo childTwoData/>
</div>;
}
PageA.getInitialProps = async ()=>{
// 在父组件中的 getInitialProps 方法里,调用接口获取子组件所需要的数据
const childOneData = await getPageAChildOneData();
const childTwoData = await getPageAChildTwoData();
return {childOneData, childTwoData}
};
- Когда структура страницы сложна, несколько подкомпонентов должны одновременно запрашивать данные или подкомпоненты должны загружаться динамически, приведенное выше решение может не подойти. Не думайте о запросе данных в жизненном цикле дочерних компонентов, следуйте спецификациям Next.js. Лучший способ — разбить эти подкомпоненты на подмаршруты и назвать их компонентами маршрутизации.
getInitialProps
метод получения данных
маршрутизация
-
конвенционная маршрутизация
- По умолчанию в
pages
в каталоге.js
Все файлы являются маршрутами первого уровня. - Если вы хотите использовать вторичную маршрутизацию, просто в
pages
каталог создать новую папку
- По умолчанию в
-
в Next.js
Link
компонент, который ничего не отображает по умолчанию (например,a
тег), необходимо указать содержимое рендеринга, и внутри должен быть элемент верхнего уровня, а два родственных элемента не могут появляться одновременно. Он просто слушает то, что мы указываемclick
событие, затем перейти к указанному пути
import Link from 'next/link'
const Index = () => {
return (
<>
<Link href="/a?id=1">
<div>
<Button>AAA</Button>
<Button>BBB</Button>
</div>
</Link>
</>
)
};
- Маршруты в Next.js генерируются путем согласования структуры каталогов файлов, поэтому их нельзя определить
params
,Динамическая маршрутизация может быть выполнена только черезquery
выполнить
import Router from 'next/router'
import Link from 'next/link'
const Index = () => {
// 通过 API 跳转
function gotoTestB() {
Router.push(
{
pathname: '/test/b',
query: {
id: 2,
},
}
)
}
return (
<>
<Link href="/test/b?id=1" >
<Button>BBB</Button>
</Link>
</>
)
};
- Если вы хотите, чтобы маршрут выглядел лучше в браузере (например:
/test/id
, вместо/test?id=123456
),Можно использоватьКарта маршрута
import Router from 'next/router'
import Link from 'next/link'
const Index = () => {
// 通过 API 跳转
function gotoTestB() {
Router.push(
{
pathname: '/test/b',
query: {
id: 2,
},
},
'/test/b/2',
)
}
return (
<>
<Link href="/test/b?id=1" as="/test/b/1" >
<div>
<Button>BBB</Button>
</div>
</Link>
</>
)
};
- Однако, когда вышеуказанная страница обновляется, страница будет 404. Поскольку это приложение SPA, интерфейс может изменить маршрут браузера без обновления страницы, но когда страница обновляется и файл, соответствующий маршруту, повторный запрос, сервер не может найти файл, соответствующий пути. Поэтому вам нужно использовать инфраструктуру Node (например, Koa2), чтобы заменить сервер по умолчанию, который поставляется с Next.js.
const Koa = require('koa');
const Router = require('koa-router');
const next = require('next');
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
router.get('/a/:id', async ctx => {
const id = ctx.params.id;
await handle(ctx.req, ctx.res, {
pathname: '/a',
query: { id },
});
});
server.listen(3000, () => {
console.log('koa server listening on 3000')
});
}
- Перехватчик маршрутизации
import Router from 'next/router'
Router.beforePopState(({ url, as, options }) => {
// I only want to allow these two routes!
if (as !== "/" || as !== "/other") {
// Have SSR render bad routes as a 404.
window.location.href = as
// 返回 false,Router 将不会执行 popstate 事件
return false
}
return true
});
-
перенаправленные события
-
routeChangeStart(url)
- Срабатывает, когда маршрут начинает переключаться -
routeChangeComplete(url)
- Запускается, когда переключение маршрута завершено -
routeChangeError(err, url)
- Запускается, когда переключатель маршрута сообщает об ошибке -
beforeHistoryChange(url)
- браузерhistory
Срабатывает, когда режим начинает переключаться -
hashChangeStart(url)
- начать переключениеhash
Запускается, когда значение не переключается на маршрут страницы -
hashChangeComplete(url)
- завершить переключениеhash
Запускается, когда значение не переключается на маршрут страницы - здесь
url
значит отображается в браузереurl
. если вы использовалиКарта маршрута, что в браузереurl
покажетas
значение
-
import React from 'react';
import Router from 'next/router'
class User extends React.Component {
handleRouteChange = url => {
console.log('url=> ', url);
};
componentDidMount() {
Router.events.on('routeChangeStart', (res) => {
console.log(res);
});
Router.events.on('routeChangeComplete', (res) => {
console.log(res);
});
Router.events.on('routeChangeError', (res) => {
console.log(res);
});
}
componentWillUnmount() {
Router.events.off('routeChangeStart', (res) => {
console.log(res);
});
Router.events.off('routeChangeComplete', (res) => {
console.log(res);
});
Router.events.off('routeChangeError', (res) => {
console.log(res);
});
}
render() {
return <div>User </div>;
}
}
style jsx
- В Next.js есть различные CSS-решения, интегрированные по умолчанию.styled-jsx
const A = ({ router, name}) => {
return (
<>
<Link href="#aaa">
<a className="link">
A {router.query.id} {name}
</a>
</Link>
<style jsx>{`
a {
color: blue;
}
.link {
color: ${color};
}
`}</style>
</>
)
};
Динамическая загрузка ресурсов и компонентов
import { withRouter } from 'next/router'
import dynamic from 'next/dynamic'
import Link from 'next/link'
const LazyComp = dynamic(import('../components/lazy-comp'));
const A = ({time }) => {
return (
<>
<div>Time:{time}</div>
<LazyComp />
</>
)
};
A.getInitialProps = async ctx => {
// 动态加载 moment,只有到了当前页面的时候才去加载它,而不是在页面初始化的时候去加载
const moment = await import('moment');
const promise = new Promise(resolve => {
setTimeout(() => {
resolve({
name: 'jokcy',
// 默认加载的是 ES6 模块
time: moment.default(Date.now() - 60 * 1000).fromNow(),
})
}, 1000)
});
return await promise
};
export default A;
_app.js
- новый
./pages/_app.js
файл, пользовательский модуль приложения - Настройка в Next.js может иметь следующие преимущества:
- Реализовать общий макет для каждой страницы - Макет
- Сохраняйте некоторое публичное состояние (используя избыточность) при изменении маршрутов
- Передайте некоторые пользовательские данные на страницу
- использовать
componentDidCatch
пользовательская обработка ошибок
// lib/my-context
import React from 'react'
export default React.createContext('')
// components/Layout
// 固定布局
xxx
xxx
xxx
// _app.js
import 'antd/dist/antd.css';
import App, { Container } from 'next/app';
import Layout from '../components/Layout'
import MyContext from '../lib/my-context'
import {Provider} from 'react-redux'
class MyApp extends App {
state = {
context: 'value',
};
/**
* 重写 getInitialProps 方法
*/
static async getInitialProps(ctx) {
const {Component} = ctx;
// 每次页面切换的时候,这个方法都会被执行!!!
console.log('app init');
let pageProps = {};
// 因为如果不加 _app.js,默认情况下,Next.js 会执行 App.getInitialProps
// 所以重写 getInitialProps 方法时,路由组件的 getInitialProps 必须要执行
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return {
pageProps
}
}
render() {
const { Component, pageProps, reduxStore } = this.props;
return (
// 在最新的 Next.js 版本中,Container 被移除了,不再需要 Container 包裹组件
// https://github.com/zeit/next.js/blob/master/errors/app-container-deprecated.md
<Container>
<Layout>
<MyContext.Provider value={this.state.context}>
<Component {...pageProps} />
</MyContext.Provider>
</Layout>
</Container>
)
}
}
export default MyApp;
_document.js
- Он будет вызываться только при рендеринге сервера, клиент не будет выполняться.
- Используется для изменения содержимого документа, отображаемого на сервере.
- Обычно используется со сторонними решениями css-in-js, такими какstyled-components
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
// 重写 getInitialProps 方法
static async getInitialProps(ctx) {
// 因为如果不加 _document.js,默认情况下,Next.js 会执行 Document.getInitialProps
// 所以自定义的时候,必须执行 Document.getInitialProps
const props = await Document.getInitialProps(ctx);
return {
...props
}
}
// render 要么不重写,重写的话,以下的内容都必须加上
// render() {
// return (
// <Html>
// <Head>
// <style>{`body { background:red;} /* custom! */`}</style>
// </Head>
// <body className="custom_class">
// <Main />
// <NextScript />
// </body>
// </Html>
// )
// }
}
export default MyDocument
Внутренняя интеграция с Webpack
- Next.js интегрирует Webpack внутри, прямо из коробки
- Разделение кода и встряхивание дерева по умолчанию в среде сборки
Интегрировать Редукс
процесс рендеринга
Порядок выполнения сервера
- _app getInitialProps()
- page getInitialProps()
- _document getInitialProps()
- _app constructor()
- _app render()
- page constructor()
- page render()
- _document constructor()
- _document render()
страница представляет компонент маршрутизации
Порядок выполнения клиента (первая открытая страница)
- _app constructor()
- _app render()
- page constructor()
- page render()
Уведомление:Когда страница загружается изначально,getInitialProps
будет вызываться только на стороне сервера. Только когда маршрут прыгает(Link
Переход к компоненту или переход к методу API), клиент выполнитgetInitialProps
.
Порядок выполнения прыжка по маршруту
- _app getInitialProps()
- page getInitialProps()
- _app render()
- page constructor()
- page render()
Плюсы и минусы использования Next.js
преимущество:
- Легкий и простой в использовании, низкая стоимость обучения, готовые решения (например, внутренняя интеграция Webpack, обычная маршрутизация и т. д.), нет необходимости создавать проекты самостоятельно. Личное мнение: это фреймворк, который обменивает степени свободы на простоту использования.
- Благодаря собственной стратегии синхронизации данных он решает самую большую проблему рендеринга на стороне сервера. Очень проблематично получать данные, отображаемые сервером, и повторно использовать их на стороне клиента, когда нет фреймворка.
- Благодаря множеству плагинов мы можем использовать его по запросу, когда мы его используем.
- Гибкая конфигурация: его можно быстро и гибко настроить в соответствии с различными требованиями проекта.
недостаток:должны соответствовать его спецификациям (например: должны бытьgetInitialProps
Получение данных из ), способ записи фиксированный, что не способствует расширению.
Outlook без сервера
- Бессерверная архитектура — бессерверная архитектура.
- Бессерверность не означает, что серверы больше не нужны, но означает, что разработчикам больше не нужно слишком много думать о серверах, и появляется концепция вычислительных ресурсов как сервисов вместо серверов.
- Serverless определенно станет популярным, Front-end может напрямую писать функции для реализации back-end логики без учета развертывания, эксплуатации и обслуживания, среды и других сценариев, что значительно повысит производительность.
- При использовании Serverless последующая SSR может называться Serverless Side Rendering.
- Поскольку я мало что знаю о Serverless, я знаю только его концепцию и влияние, поэтому я не осмеливаюсь говорить слишком много Заинтересованные студенты могут понять это сами.
Поймите Serverless, этой статьи достаточно
Понять принцип бессерверной архитектуры без сервера (1)
Что такое бессерверная бессерверная архитектура?
Общая проблема
Клиенты должны использовать ReactDOM.hydra вместо ReactDOM.render, чтобы делать то, чего не делает SSR (например, привязка событий).
- В Реакции v15,
ReactDOM.render
метод будет основан наdata-react-checksum
тег, повторное использованиеReactDOMServer
Результат рендеринга не повторяет рендеринг. согласно сdata-reactid
атрибут, найдите элемент события, который необходимо связать, и обработайте привязку события. - В Реакции v16,
ReactDOMServer
Визуализированный контент больше не поставляется сdata-react
Атрибуты,ReactDOM.render
Может использоваться, но выдаст предупреждение. - В Реакции v17,
ReactDOM.render
Больше не будет функции мультиплексирования контента SSR, унифицированного использованияhydrate()
Чтобы закончить оказанную услугу. - Поскольку HTML-код, возвращаемый сервером, представляет собой строку, несмотря на наличие контента, различные компоненты не имеют событий, на складе клиента нет данных, вы можете видетьсморщенная нить. Клиент завершит инициализацию React в соответствии с этими строками, такими как создание экземпляров компонентов, привязка событий, инициализация данных хранилища и т. д. гидрат играет очень важную роль в этом процессе, широко известном как «впрыск воды», который можно понимать как впрыскивание воды в сморщенные семена, чтобы сделать их более жизнеспособными.
-
При использовании Next.jsОткройте консоль браузера => найдите сеть => найдите запрос текущего маршрута и просмотрите ответ => вы можете видеть, что html, возвращаемый сервером, содержит данные, требуемые текущей страницей, так что клиент не будет повторно -инициировать запрос, полагаться на это
ReactDOM.hydrate
.
SSR должен использоватьStaticRouter
(Статический маршрутный контейнер), а неBrowserRouter
а такжеHashRouter
И клиент, и сервер должны настроить склад магазина, но эти два склада будут разными.
componentDidMount
не выполняется на стороне сервера иcomponentWillMount
Выполняется как на клиенте, так и на сервере, поэтому не рекомендуется использоватьcomponentWillMount
Причина отправки запроса
Регистрационные мероприятия должны быть размещены вcomponentDidMount
, нельзя помещать вcomponentWillMount
, потому что сервер не будет выполнятьсяcomponentWillUnmount
, если поместить вcomponentWillMount
, это приведет к повторной регистрации событий и утечкам памяти
Если вы не хотите использовать SSR, но хотите оптимизировать SEO, вы можете использоватьprerender илиprerender-spa-pluginзаменить ССР
При ручной настройке инфраструктуры SSR: используйтеnpm-run-al
l & nodemon
Для повышения эффективности разработки Node-проектов
- nodemon Отслеживание изменений в файлах кода и автоматический перезапуск при изменении кода.
- npm-run-allинструмент cli для запуска нескольких npm-скриптов параллельно или последовательно
npm install npm-run-all nodemon --save-dev
"scripts": {
"dev": "npm-run-all --parallel dev:**",
"dev:start": "nodemon build/server.js",
"dev:build:client": "webpack --config webpack.client.js --watch",
"dev:build:server": "webpack --config webpack.server.js --watch"
}
В Next.js: импортируется по умолчаниюimport React from "react"
, но если его не ввести, то редактор будет выдавать предупреждение при написании компонентов, так что лучше его ввести
В Next.js: каждый компонент маршрутизации в каталоге pages будет упакован отдельно, поэтому при нажатии кнопки для выполнения перехода маршрутизации он не сразу перейдет на соответствующую страницу маршрутизации, но сначала должна быть загружена целевая маршрутизация. файл, а затем перепрыгнуть через него. Это можно оптимизировать с помощью предварительной загрузки.
В Next.js: Webpack интегрирован внутри, а разделение кода и встряхивание дерева выполняются по умолчанию в сгенерированной среде.
Next.js работает с любым фреймворком узлов, ноrequest
,response
Должна быть разница в способе инкапсуляции, как это гарантирует, что Next.js экспортируетhandle
Совместим ли метод с этими фреймворками?
- гарантия
handle
Полученный метод является родным для Nodejsrequset
объект иresponse
Объект, а не фреймворк на основе собственной инкапсуляцииrequest
,response
объект. Вот почему при использовании koahandle
полученоctx.req
,ctx.res
, вместоctx.request
,ctx.response
причина.
В Next.js: как интегрировать стилизованные компоненты
- Необходимо интегрировать в _document.js
- Идеи аспектно-ориентированного программирования с использованием АОП
cnpm i styled-components babel-plugin-styled-components -D
// .babelrc
{
"presets": ["next/babel"],
"plugins": [
[
"import",
{
"libraryName": "antd"
}
],
["styled-components", { "ssr": true }]
]
}
// _document.js
import Docuemnt, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
function withLog(Comp) {
return props => {
console.log(props);
return <Comp {...props} />
}
}
class MyDocument extends Docuemnt {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
// 增强 APP 功能
enhanceApp: App => props => sheet.collectStyles(<App {...props} />),
// 增强组件功能
// enhanceComponent: Component => withLog(Component)
});
const props = await Docuemnt.getInitialProps(ctx);
return {
...props,
styles: (
<>
{props.styles}
{sheet.getStyleElement()}
</>
),
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
// pages/a.js
import { withRouter } from 'next/router'
import Link from 'next/link'
import styled from 'styled-components'
const Title = styled.h1`
color: yellow;
font-size: 40px;
`;
const color = '#113366';
const A = ({ router, name}) => {
return (
<>
<Title>This is Title</Title>
<Comp />
<Link href="#aaa">
<a className="link">
A {router.query.id} {name}
</a>
</Link>
<style jsx>{`
a {
color: blue;
}
.link {
color: ${color};
}
`}</style>
</>
)
};
export default withRouter(A)
В Next.js: как интегрировать CSS/Sass/Less/Stylus
для поддержки.css
,.scss
,.less
,.styl
, вам необходимо настроить файл next.config.js по умолчанию, подробности см. по ссылке ниже.
В Next.js: невозможно загрузить стили Antd по запросу при упаковке
блог woo woo woo.cn on.com/1ask/fear/1079…
woo woo Краткое описание.com/afraid/2 9 3 oh 41 from…
В Next.js: не настраивайте имена статических папок
Создайте новую папку в корневом каталоге с именемstatic
, код можно передать через/static/
для импорта связанных статических ресурсов. но только звониstatic
, потому что только с этим именем Next.js будет рассматривать его как статический ресурс.
В Next.js: почему приложение открывается медленно
- Можно поместить модуль, используемый только сервером, в getInitialProps, и тогда Webpack также упакует модуль. Может относиться кimport them properly
Список распространенных ошибок Next.js
послесловие
- Эта статья просто написана на основе моего понимания.Если есть неправильное понимание, пожалуйста, поправьте меня или предложите лучшее решение
- Для того, чтобы написать максимально подробно, потребовалось два месяца до и после, чтобы разобраться в этой статье.Увидев это, если вы считаете, что эта статья неплохая, пожалуйста, поставьте лайк~~
адрес проекта
Вручную создайте упрощенную версию платформы SSR.
React16.8 + Next.js + Koa2 разрабатывают проект полного стека Github
Ссылаться на
Практика разделения передней и задней части Taobao ! ! ! ! ! !
Зачем делать реактивный проект изоморфным приложением ssr
Демистификация изоморфных приложений React
Создайте высоконадежное и высокопроизводительное изоморфное решение React
Рекомендуемое чтение
Вы действительно понимаете жизненный цикл React?
Подробные хуки React [почти 1W слов] + бой проекта