Conversation
| ``` | ||
|
|
||
| One way to do code-splitting is with `React.lazy`. However, this means that the code is not fetched until the component renders, which can cause network waterfalls. A more optimal solution is to use a router feature that fetches the code in parallel while the code is downloading. For example, React Router provides a `lazy` option to specify that a route should be code split and optimize when it is loaded: | ||
| コード分割を行う方法のひとつは、`React.lazy` を使用することです。しかし、この方法ではレンダーされる段階になって初めてコードが取得されるため、ネットワークウォーターフォールが発生する可能性があります。より良い解決策は、コードがダウンロードされる間に並行してコードをフェッチするためのルータ機能を使用することです。例えば、React Router は `lazy` オプションを提供しており、これを使ってルートをコード分割対象として指定し、読み込みタイミングを最適化できます。 |
There was a problem hiding this comment.
ここよく分かっていません。とりあえず直訳していますが、「コードがダウンロードされる間に並行してコードをフェッチ」って何やねん、と思っています。
「コードがダウンロードされる間に並行してデータをフェッチ」と言いたい? 「コードがダウンロードされる間に並行して別のルートのコードをを(プリ)フェッチ」と言いたい? ただ直後のコードサンプルからはそのような雰囲気が全く感じられませんし…。
There was a problem hiding this comment.
僕はてっきり「ファイルがロードされたら、即座に該当するチャンクのダウンロードをする」という動作だと思っていましたが、
https://ja.react.dev/reference/react/lazy を見た感じ、「MarkdownPreview を 初回レンダーしたときに はじめてチャンクのダウンロードが始まる」という挙動になるらしいです。
ローカルでは試していませんが、同ページにデモがあったので、そちらで確認できました。
import { useState, Suspense, lazy } from 'react';
import Loading from './Loading.js';
const MarkdownPreview = lazy(() => delayForDemo(import('./MarkdownPreview.js')));
// MarkdownPreview.js のダウンロードは、トップレベルでいきなり開始する……のではなく、
export default function MarkdownEditor() {
const [showPreview, setShowPreview] = useState(false);
const [markdown, setMarkdown] = useState('Hello, **world**!');
console.log("render")
return (
<>
<textarea value={markdown} onChange={e => setMarkdown(e.target.value)} />
<label>
<input type="checkbox" checked={showPreview} onChange={e => setShowPreview(e.target.checked)} />
Show preview
</label>
<hr />
{showPreview && (
<Suspense fallback={<Loading />}>
<h2>Preview</h2>
<MarkdownPreview markdown={markdown} />
{/* ^ 実は、この JSX 式のぶんがレンダーされるときに始まる */}
</Suspense>
)}
</>
);
}
// Add a fixed delay so you can see the loading state
function delayForDemo(promise) {
console.log("start loading")
return new Promise(resolve => {
setTimeout(resolve, 2000);
}).then(() => promise);
}There was a problem hiding this comment.
なので、
App.jsが読み込まれるApp.jsにおいて、<MarkdownPreview />がレンダーされるMarkdownPreview.jsのダウンロードが始まる
というウォーターフォールが発生してしまうので、それを避けたい、ということだと思うので、その訳文で問題ないと思います。
ただ、「コードがダウンロードされる間に並行してコードをフェッチ」は、それでもあと 30% ぐらいしっくり来ない…
downloading を「ダウンロードされる」ではなく「(何かを)ダウンロードしている」と訳すべきなのか…?
それとは別に、
- 前者の「コードが」は「createBrowserRouter が書かれているような、ルーター設定側のコード」
- 後者の「コードを」は、「そのファイルから参照されている、(lazy) な個別ルートのコード」
と解釈できなくもないですが、根拠がない…
There was a problem hiding this comment.
これ分かりました。React Router の Router-level lazy ("Route.lazy") のメリットがよく分かっていなかったのですが、React-based lazyと比べた場合の最大の利点はルーティングがネストしている場合に並行ロードができる、という挙動のようですね。
https://remix.run/blog/lazy-loading-routes#introducing-routelazy
// Router-based lazy
const routes = [{
path: '/',
loader: () => getUser(),
element: <Layout />,
children: [{
index: true,
element: <Home />,
}, {
path: 'projects',
lazy: () => import("./projects"), // 💤 Lazy load!
children: [{
path: ':projectId',
lazy: () => import("./project"), // 💤 Lazy load!
}],
}],
}]ちょっと前まではこういう場合、<Projects> と <Project> を愚直な React-based lazy で囲んでこう書いていたと思うのですが…
// React-based lazy
const Projects = React.lazy(() => import("./projects"));
const Project = React.lazy(() => import("./project"));
const routes = [{
path: '/',
loader: () => getUser(),
element: <Layout />,
children: [{
index: true,
element: <Home />,
}, {
path: 'projects',
element: <Projects />,
children: [{
path: ':projectId',
element: <Project />
}],
}],
}]…これで /projects/123 にアクセスした場合、Projects と Project のコンポーネントのコードがウォーターフォールでフェッチされてしまいます。が、Router-level lazy で定義されていれば、深いところに隠れている遅延ロードも(レンダーサイクルとは無関係な)ルータ本体のレベルで認識できるので、この2つのコード(上記の projects.jsx と project.jsx)を同時にフェッチできる、と。
(「コードと関連するデータ」間ではウォーターフォールが残っているので微妙ですが、少なくとも「2つのコード間」のウォーターフォールはないので、そこが良い、みたいな話)
なので意図を汲んで意訳するなら コードのダウンロード中に関連コード群を並行的にフェッチするためのルータ機能 としておくのが良いかなと思いました。直後のコードサンプルでは React-based lazy との違いが表現できてなくて微妙ですが…。
There was a problem hiding this comment.
なるほど!(いつも Next.js ばかり使っていてそちらに任せていたのでよく分かってなかったところでした)
その訳で問題ないと思います!
よく考えたら code って、ソースコードの意味ではたぶん不可算なので、それで意味が取りにくかったのかもしれませんね…
This comment was marked as outdated.
This comment was marked as outdated.
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
| ``` | ||
|
|
||
| One way to do code-splitting is with `React.lazy`. However, this means that the code is not fetched until the component renders, which can cause network waterfalls. A more optimal solution is to use a router feature that fetches the code in parallel while the code is downloading. For example, React Router provides a `lazy` option to specify that a route should be code split and optimize when it is loaded: | ||
| コード分割を行う方法のひとつは、`React.lazy` を使用することです。しかし、この方法ではレンダーされる段階になって初めてコードが取得されるため、ネットワークウォーターフォールが発生する可能性があります。より良い解決策は、コードがダウンロードされる間に並行してコードをフェッチするためのルータ機能を使用することです。例えば、React Router は `lazy` オプションを提供しており、これを使ってルートをコード分割対象として指定し、読み込みタイミングを最適化できます。 |
There was a problem hiding this comment.
僕はてっきり「ファイルがロードされたら、即座に該当するチャンクのダウンロードをする」という動作だと思っていましたが、
https://ja.react.dev/reference/react/lazy を見た感じ、「MarkdownPreview を 初回レンダーしたときに はじめてチャンクのダウンロードが始まる」という挙動になるらしいです。
ローカルでは試していませんが、同ページにデモがあったので、そちらで確認できました。
import { useState, Suspense, lazy } from 'react';
import Loading from './Loading.js';
const MarkdownPreview = lazy(() => delayForDemo(import('./MarkdownPreview.js')));
// MarkdownPreview.js のダウンロードは、トップレベルでいきなり開始する……のではなく、
export default function MarkdownEditor() {
const [showPreview, setShowPreview] = useState(false);
const [markdown, setMarkdown] = useState('Hello, **world**!');
console.log("render")
return (
<>
<textarea value={markdown} onChange={e => setMarkdown(e.target.value)} />
<label>
<input type="checkbox" checked={showPreview} onChange={e => setShowPreview(e.target.checked)} />
Show preview
</label>
<hr />
{showPreview && (
<Suspense fallback={<Loading />}>
<h2>Preview</h2>
<MarkdownPreview markdown={markdown} />
{/* ^ 実は、この JSX 式のぶんがレンダーされるときに始まる */}
</Suspense>
)}
</>
);
}
// Add a fixed delay so you can see the loading state
function delayForDemo(promise) {
console.log("start loading")
return new Promise(resolve => {
setTimeout(resolve, 2000);
}).then(() => promise);
}| ``` | ||
|
|
||
| One way to do code-splitting is with `React.lazy`. However, this means that the code is not fetched until the component renders, which can cause network waterfalls. A more optimal solution is to use a router feature that fetches the code in parallel while the code is downloading. For example, React Router provides a `lazy` option to specify that a route should be code split and optimize when it is loaded: | ||
| コード分割を行う方法のひとつは、`React.lazy` を使用することです。しかし、この方法ではレンダーされる段階になって初めてコードが取得されるため、ネットワークウォーターフォールが発生する可能性があります。より良い解決策は、コードがダウンロードされる間に並行してコードをフェッチするためのルータ機能を使用することです。例えば、React Router は `lazy` オプションを提供しており、これを使ってルートをコード分割対象として指定し、読み込みタイミングを最適化できます。 |
There was a problem hiding this comment.
なので、
App.jsが読み込まれるApp.jsにおいて、<MarkdownPreview />がレンダーされるMarkdownPreview.jsのダウンロードが始まる
というウォーターフォールが発生してしまうので、それを避けたい、ということだと思うので、その訳文で問題ないと思います。
ただ、「コードがダウンロードされる間に並行してコードをフェッチ」は、それでもあと 30% ぐらいしっくり来ない…
downloading を「ダウンロードされる」ではなく「(何かを)ダウンロードしている」と訳すべきなのか…?
それとは別に、
- 前者の「コードが」は「createBrowserRouter が書かれているような、ルーター設定側のコード」
- 後者の「コードを」は、「そのファイルから参照されている、(lazy) な個別ルートのコード」
と解釈できなくもないですが、根拠がない…
Co-authored-by: honey32 <honey32@bearwapps.com>
|
@honey32 ありがとうございます、3箇所再チェックをお願いできますでしょうか |
|
@honey32 ありがとうございました! |

No description provided.