Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
# Conflicts:
#	docs/1.getting-started/11.testing.md
#	docs/1.getting-started/12.upgrade.md
#	docs/1.getting-started/4.styling.md
#	docs/1.getting-started/5.routing.md
#	docs/1.getting-started/6.data-fetching.md
#	docs/2.guide/1.concepts/3.rendering.md
#	docs/2.guide/2.directory-structure/1.components.md
#	docs/2.guide/2.directory-structure/1.composables.md
#	docs/2.guide/2.directory-structure/1.middleware.md
#	docs/2.guide/2.directory-structure/3.app-config.md
#	docs/3.api/2.composables/use-fetch.md
  • Loading branch information
Ivan Bochkarev committed Oct 14, 2024
2 parents 638f634 + e063885 commit 4e90829
Show file tree
Hide file tree
Showing 101 changed files with 2,093 additions and 1,604 deletions.
10 changes: 8 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ jobs:
run: pnpm build

- name: Cache dist
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
retention-days: 3
name: dist
Expand Down Expand Up @@ -191,20 +191,26 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest]
env: ["dev", "built"]
builder: ["vite", "webpack"]
builder: ["vite", "rspack", "webpack"]
context: ["async", "default"]
manifest: ["manifest-on", "manifest-off"]
payload: ["json", "js"]
node: [18]
exclude:
- builder: "webpack"
payload: "js"
- builder: "rspack"
payload: "js"
- manifest: "manifest-off"
payload: "js"
- context: "default"
payload: "js"
- os: windows-latest
payload: "js"
- env: "dev"
builder: "rspack"
- manifest: "manifest-off"
builder: "rspack"
- env: "dev"
builder: "webpack"
- manifest: "manifest-off"
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/docs-check-links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
steps:
# Cache lychee results (e.g. to avoid hitting rate limits)
- name: Restore lychee cache
uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: .lycheecache
key: cache-lychee-${{ github.sha }}
Expand All @@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1

- name: Lychee link checker
uses: lycheeverse/lychee-action@7da8ec1fc4e01b5a12062ac6c589c10a4ce70d67 # for v1.8.0
uses: lycheeverse/lychee-action@7cd0af4c74a61395d455af97419279d86aafaede # for v1.8.0
with:
# arguments with file types to check
args: >-
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
# Upload the results as artifacts (опциональный). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
if: github.repository == 'nuxt/nuxt' && success()
with:
name: SARIF file
Expand Down
4 changes: 4 additions & 0 deletions docs/1.getting-started/11.testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ bun add --dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
> Т.е. `vitest.config.m{ts,js}`.
::

::tip
It is possible to set environment variables for testing by using the `.env.test` file.
::

### Использование среды выполнения Nuxt

По умолчанию, `@nuxt/test-utils` не изменяет окружение Vitest, поэтому вы можете выполнить детальную настройку и запустить тесты Nuxt вместе с другими юнит-тестами.
Expand Down
1 change: 1 addition & 0 deletions docs/1.getting-started/12.upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ nuxt.config.ts
1. Создайте новую директорию с именем `app/`.
2. Переместите в нее папки `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/` и `utils/`, а также `app.vue`, `error.vue`, `app.config.ts`. Если у вас есть папки `app/router-options.ts` или `app/spa-loading-template.html`, эти пути остаются прежними.
3. Убедитесь, что папки `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/` и `server/` находятся вне папки `app/`, в корне вашего проекта.
4. Remember to update any third-party configuration files to work with the new directory structure, such as your `tailwindcss` or `eslint` configuration (if required - `@nuxtjs/tailwindcss` should automatically configure `tailwindcss` correctly).

::tip
Вы можете автоматизировать эту миграцию, запустив `npx codemod@latest nuxt/4/file-structure`
Expand Down
2 changes: 1 addition & 1 deletion docs/1.getting-started/4.styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ export default defineNuxtConfig({
hooks: {
'build:manifest': (manifest) => {
// ищем список файлов css в точке входа в приложение
const css = manifest['node_modules/nuxt/dist/app/entry.js']?.css
const css = Object.values(manifest).find(options => options.isEntry)?.css
if (css) {
// начинаем с конца массива и двигаемся к его началу
for (let i = css.length - 1; i >= 0; i--) {
Expand Down
2 changes: 1 addition & 1 deletion docs/1.getting-started/5.routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ navigation.icon: i-ph-signpost
::code-group

```bash [Структура директории]
| pages/
-| pages/
---| about.vue
---| index.vue
---| posts/
Expand Down
84 changes: 54 additions & 30 deletions docs/1.getting-started/6.data-fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,59 +8,59 @@ Nuxt поставляется с двумя композаблами и встр

В двух словах:

- [`useFetch`](/docs/api/composables/use-fetch) - это самый простой способ получениях данных в функции `setup` компонента.
- [`$fetch`](/docs/api/utils/dollarfetch) отлично подходит для выполнения сетевых запросов на основе взаимодействия с пользователем.
- [`useAsyncData`](/docs/api/composables/use-async-data) в сочетании с `$fetch` предлагает больший контроль.
- [`$fetch`](/docs/api/utils/dollarfetch) is the simplest way to make a network request.
- [`useFetch`](/docs/api/composables/use-fetch) is wrapper around `$fetch` that fetches data only once in [universal rendering](/docs/guide/concepts/rendering#universal-rendering).
- [`useAsyncData`](/docs/api/composables/use-async-data) is similar to `useFetch` but offers more fine-grained control.

И `useFetch`, и `useAsyncData` имеют общий набор опций и паттернов, которые мы подробно рассмотрим в следующих разделах.

Но прежде необходимо знать, зачем вообще существуют эти композаблы.

## Зачем использовать специальные композаблы для получения данных?
## The need for `useFetch` and `useAsyncData`

Nuxt - это фреймворк, который может выполнять изоморфный (или универсальный) код как в серверном, так и в клиентском окружениях. Если функция [`$fetch`](/docs/api/utils/dollarfetch) используется для получения данных в функции `setup` компонента Vue, это может привести к тому, что данные будут получены дважды, один раз на сервере (чтобы отрендерить HTML) и еще раз на клиенте (когда HTML будет гидратирован). Именно поэтому Nuxt предлагает специальные композаблы для получения данных, чтобы данные запрашивались только один раз.

### Дублирование сетевых вызовов

Композаблы [`useFetch`](/docs/api/composables/use-fetch) и [`useAsyncData`](/docs/api/composables/use-async-data) гарантируют, что после выполнения вызова API на сервере данные будут правильно переданы клиенту в полезной нагрузке.
The [`useFetch`](/docs/api/composables/use-fetch) and [`useAsyncData`](/docs/api/composables/use-async-data) composables solve this problem by ensuring that if an API call is made on the server, the data is forwarded to the client in the payload.

Полезная нагрузка - это объект JavaScript, доступный через [`useNuxtApp().payload`](/docs/api/composables/use-nuxt-app#payload). Он используется на клиенте, чтобы избежать повторного запроса одних и тех же данных при выполнении кода в браузере [во время гидратации](/docs/guide/concepts/rendering#universal-rendering).

::tip
Используйте [Nuxt DevTools](https://devtools.nuxt.com) для просмотра этих данных на вкладке **Payload**.
::

### Suspense

Nuxt использует компонент Vue [`<Suspense>`](https://ru.vuejs.org/guide/built-ins/suspense) под капотом, чтобы предотвратить навигацию до того, как все асинхронные данные будут доступны для просмотра. Композаблы для получения данных могут помочь вам использовать эту функцию и использовать то, что лучше всего подходит для каждого вызова.

::note
Вы можете добавить [`<NuxtLoadingIndicator>`](/docs/api/components/nuxt-loading-indicator), чтобы добавить индикатор прогресса между переходами по странице.
::

## `useFetch`

Композабл [`useFetch`](/docs/api/composables/use-fetch) является наиболее простым способом получения данных.

```vue twoslash [app.vue]
```vue [app.vue]
<script setup lang="ts">
const { data: count } = await useFetch('/api/count')
const { data } = await useFetch('/api/data')
async function handleFormSubmit() {
const res = await $fetch('/api/submit', {
method: 'POST',
body: {
// My form data
}
})
}
</script>
<template>
<p>Количество просмотров страницы: {{ count }}</p>
<div v-if="data == null">
No data
</div>
<div v-else>
<form @submit="handleFormSubmit">
<!-- form input tags -->
</form>
</div>
</template>
```

Этот композабл представляет собой обертку вокруг композабла [`useAsyncData`](/docs/api/composables/use-async-data) и утилиты `$fetch`.
In the example above, `useFetch` would make sure that the request would occur in the server and is properly forwarded to the browser. `$fetch` has no such mechanism and is a better option to use when the request is solely made from the browser.

::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=njsGVmcWviY" target="_blank"}
Посмотрите видео от Александра Лихтера, чтобы не использовать `useFetch` неправильно!
::
### Suspense

:read-more{to="/docs/api/composables/use-fetch"}
Nuxt uses Vue’s [`<Suspense>`](https://vuejs.org/guide/built-ins/suspense) component under the hood to prevent navigation before every async data is available to the view. The data fetching composables can help you leverage this feature and use what suits best on a per-call basis.

:link-example{to="/docs/examples/features/data-fetching"}
::note
You can add the [`<NuxtLoadingIndicator>`](/docs/api/components/nuxt-loading-indicator) to add a progress bar between page navigations.
::

## `$fetch`

Expand Down Expand Up @@ -88,6 +88,30 @@ async function addTodo() {
Узнайте больше о `$fetch`.
::

## `useFetch`

The [`useFetch`](/docs/api/composables/use-fetch) composable uses `$fetch` under-the-hood to make SSR-safe network calls in the setup function.

```vue twoslash [app.vue]
<script setup lang="ts">
const { data: count } = await useFetch('/api/count')
</script>
<template>
<p>Page visits: {{ count }}</p>
</template>
```

This composable is a wrapper around the [`useAsyncData`](/docs/api/composables/use-async-data) composable and `$fetch` utility.

::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=njsGVmcWviY" target="_blank"}
Watch the video from Alexander Lichter to avoid using `useFetch` the wrong way!
::

:read-more{to="/docs/api/composables/use-fetch"}

:link-example{to="/docs/examples/features/data-fetching"}

## `useAsyncData`

Композабл `useAsyncData` отвечает за обертывание асинхронной логики и возврат результата после его разрешения.
Expand Down
37 changes: 30 additions & 7 deletions docs/2.guide/1.concepts/3.rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,42 @@ Nuxt поддерживает разные режимы рендеринга: [

## Универсальный Рендеринг

Когда браузер запрашивает URL-адрес с включенным универсальным (серверным + клиентским) рендерингом, сервер возвращает браузеру полностью отрисованную HTML-страницу. Независимо от того, была ли страница сгенерирована заранее и кэширована или отрисовывается налету, в какой-то момент Nuxt запустил код JavaScript (Vue.js) в среде сервера, создав HTML-документ. Пользователи сразу получают контент нашего приложения, в отличие от рендеринга на клиенте. Этот шаг аналогичен традиционному **рендерингу на сервере**, выполняемому приложениями PHP или Ruby.
This step is similar to traditional **server-side rendering** performed by PHP or Ruby applications. When the browser requests a URL with universal rendering enabled, Nuxt runs the JavaScript (Vue.js) code in a server environment and returns a fully rendered HTML page to the browser. Nuxt may also return a fully rendered HTML page from a cache if the page was generated in advance. Users immediately get the entirety of the initial content of the application, contrary to client-side rendering.

Чтобы не потерять преимущества метода рендеринга на клиенте, такие как динамические интерфейсы и переходы страниц, клиент (браузер) загружает код JavaScript, который запускается на сервере в фоновом режиме после загрузки HTML-документа. Браузер снова интерпретирует его (отсюда и **универсальный рендеринг**), а Vue.js берет на себя управление документом и обеспечивает интерактивность.

Процесс, когда статичная страница становится интерактивной в браузере, называется "Гидратация".
Once the HTML document has been downloaded, the browser interprets this and Vue.js takes control of the document. The same JavaScript code that once ran on the server runs on the client (browser) **again** in the background now enabling interactivity (hence **Universal rendering**) by binding its listeners to the HTML. This is called **Hydration**. When hydration is complete, the page can enjoy benefits such as dynamic interfaces and page transitions.

Универсальный рендеринг позволяет Nuxt-приложению обеспечить быструю загрузку страницы, сохраняя при этом преимущества рендеринга на клиенте. Более того, поскольку контент уже присутствует в HTML-документе, поисковые роботы могут индексировать его без дополнительных затрат.

![Пользователи могут получить доступ к статическому содержимому, когда HTML-документ загружен. Затем гидратация обеспечивает интерактивность страницы.](/assets/docs/concepts/rendering/ssr.svg)

**Преимущества рендеринга на сервере:**
- **Производительность**: Пользователи могут получить немедленный доступ к содержимому страницы, поскольку браузеры могут отображать статический контент гораздо быстрее, чем контент, сгенерированный JavaScript. В то же время Nuxt сохраняет интерактивность веб-приложения, когда происходит процесс гидратации.
- **Поисковая оптимизация**: Универсальный рендеринг доставляет все HTML-содержимое страницы в браузер как классическое серверное приложение. Поисковые роботы могут напрямую индексировать содержимое страницы, что делает универсальный рендеринг отличным выбором для любого контента, который вы хотите быстро проиндексировать.
**What's server-rendered and what's client-rendered?**

It is normal to ask which parts of a Vue file runs on the server and/or the client in universal rendering mode.

```vue [app.vue]
<script setup lang="ts">
const counter = ref(0); // executes in server and client environments
const handleClick = () => {
counter.value++; // executes only in a client environment
};
</script>
<template>
<div>
<p>Count: {{ counter }}</p>
<button @click="handleClick">Increment</button>
</div>
</template>
```

On the initial request, the `counter` ref is initialized in the server since it is rendered inside the `<p>` tag. The contents of `handleClick` is never executed here. During hydration in the browser, the `counter` ref is re-initialized. The `handleClick` finally binds itself to the button; Therefore it is reasonable to deduce that the body of `handleClick` will always run in a browser environment.

[Middlewares](/docs/guide/directory-structure/middleware) and [pages](/docs/guide/directory-structure/pages) run in the server and on the client during hydration. [Plugins](/docs/guide/directory-structure/plugins) can be rendered on the server or client or both. [Components](/docs/guide/directory-structure/components) can be forced to run on the client only as well. [Composables](/docs/guide/directory-structure/composables) and [utilities](/docs/guide/directory-structure/utils) are rendered based on the context of their usage.

**Benefits of server-side rendering:**
- **Performance**: Users can get immediate access to the page's content because browsers can display static content much faster than JavaScript-generated content. At the same time, Nuxt preserves the interactivity of a web application during the hydration process.
- **Search Engine Optimization**: Universal rendering delivers the entire HTML content of the page to the browser as a classic server application. Web crawlers can directly index the page's content, which makes Universal rendering a great choice for any content that you want to index quickly.

**Недостатки рендеринга на сервере:**
- **Ограничения разработки:** Среды сервера и браузера не предоставляют одни и те же API, и может быть сложно написать код, который мог бы беспрепятственно выполняться на обеих сторонах. К счастью, Nuxt предоставляет рекомендации и специальные переменные, которые помогут вам определить, где выполняется фрагмент кода.
Expand Down
Loading

0 comments on commit 4e90829

Please sign in to comment.