Skip to content

docs(code-splitting): translate code splitting #55

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 22, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 39 additions & 71 deletions content/docs/code-splitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ permalink: docs/code-splitting.html

## Bundling {#bundling}

Most React apps will have their files "bundled" using tools like
[Webpack](https://webpack.js.org/) or [Browserify](http://browserify.org/).
Bundling is the process of following imported files and merging them into a
single file: a "bundle". This bundle can then be included on a webpage to load
an entire app at once.
大部分 React 應用程式會使用像是 [Webpack](https://webpack.js.org/) 或 [Browserify](http://browserify.org/) 的工具來 bundle 它們的檔案。

#### Example {#example}
Bundle 是將被 import 的檔案合併成一個單一的檔案:「bundle」。這個 bundle 檔案可以被引入到網頁內來載入整個應用程式。

**App:**
#### 範例 {#example}

**應用程式:**

```js
// app.js
Expand All @@ -30,7 +28,7 @@ export function add(a, b) {
}
```

**Bundle:**
**Bundle**

```js
function add(a, b) {
Expand All @@ -40,86 +38,62 @@ function add(a, b) {
console.log(add(16, 26)); // 42
```

> Note:
> 注意:
>
> Your bundles will end up looking a lot different than this.
> 你的 bundle 後的最終結果看起來會與此不同。

If you're using [Create React App](https://github.com/facebookincubator/create-react-app), [Next.js](https://github.com/zeit/next.js/), [Gatsby](https://www.gatsbyjs.org/), or a similar tool, you will have a Webpack setup out of the box to bundle your
app.
如果你使用 [Create React App](https://github.com/facebookincubator/create-react-app)、[Next.js](https://github.com/zeit/next.js/)、[Gatsby](https://www.gatsbyjs.org/),或者是類似的工具,會有一個內建的 Webpack 設定來 bundle 你的應用程式。

If you aren't, you'll need to setup bundling yourself. For example, see the
[Installation](https://webpack.js.org/guides/installation/) and
[Getting Started](https://webpack.js.org/guides/getting-started/) guides on the
Webpack docs.
如果沒有的話,你需要自己設定 bundle。例如,拜訪 Webpack 文件的 [Installation](https://webpack.js.org/guides/installation/) 和 [Getting Started](https://webpack.js.org/guides/getting-started/) 指南。

## Code Splitting {#code-splitting}
## Code-Splitting {#code-splitting}

Bundling is great, but as your app grows, your bundle will grow too. Especially
if you are including large third-party libraries. You need to keep an eye on
the code you are including in your bundle so that you don't accidentally make
it so large that your app takes a long time to load.
Bundle 非常棒,但隨著你的應用程式成長,你的 bundle 也將會隨著增長。特別是你引入了大量的第三方函式庫。
你需要隨時留意 bundle 後的程式碼,這樣你就不會得意外的讓 bundle 檔案變得太大,以至於你的應用程式需要很長的時間才能被載入。

To avoid winding up with a large bundle, it's good to get ahead of the problem
and start "splitting" your bundle.
[Code-Splitting](https://webpack.js.org/guides/code-splitting/) is a feature
supported by bundlers like Webpack and Browserify (via
[factor-bundle](https://github.com/browserify/factor-bundle)) which can create
multiple bundles that can be dynamically loaded at runtime.
為了避免 bundle 的結果過大,最好的解決問題的方式是開始「split」你的 bundle。[Code-Splitting](https://webpack.js.org/guides/code-splitting/) 是透過由像是 Webpack 和 Browserify 的 bundler 所支援的功能,它會建立多個 bundle,可以在 runtime 時動態的被載入。

Code-splitting your app can help you "lazy-load" just the things that are
currently needed by the user, which can dramatically improve the performance of
your app. While you haven't reduced the overall amount of code in your app,
you've avoided loading code that the user may never need, and reduced the amount
of code needed during the initial load.
Code-splitting 可以幫助你「延遲載入」目前使用者所需要的東西,這可以大幅提供你的應用程式效能。雖然你還沒有減少應用程式的程式碼總數量,但你可以避免載入使用者目前使用不到的程式碼,來減少初始載入應用程式的時間。

## `import()` {#import}

The best way to introduce code-splitting into your app is through the dynamic
`import()` syntax.
將 code-splitting 引入到你的應用程式最好的方式是透過動態 `import()` 語法。

**Before:**
**加入前:**

```js
import { add } from './math';

console.log(add(16, 26));
```

**After:**
**加入後:**

```js
import("./math").then(math => {
console.log(math.add(16, 26));
});
```

> Note:
> 注意:
>
> The dynamic `import()` syntax is a ECMAScript (JavaScript)
> [proposal](https://github.com/tc39/proposal-dynamic-import) not currently
> part of the language standard. It is expected to be accepted in the
> near future.
> 動態 `import()` 語法是 ECMAScript(JavaScript)的[提案](https://github.com/tc39/proposal-dynamic-import),並不是語言標準的一部分。預計在不久的將來會被接受。

When Webpack comes across this syntax, it automatically starts code-splitting
your app. If you're using Create React App, this is already configured for you
and you can [start using it](https://facebook.github.io/create-react-app/docs/code-splitting) immediately. It's also supported
out of the box in [Next.js](https://github.com/zeit/next.js/#dynamic-import).
當 Webpack 遇到這種語法時,它將自動的在你的應用程式啟動 code-splitting 。如果你使用 Create React App 的話,它已經幫你設定好了,你可以立即的[使用它](https://facebook.github.io/create-react-app/docs/code-splitting)。在 [Next.js](https://github.com/zeit/next.js/#dynamic-import) 也內建支援這個功能。

If you're setting up Webpack yourself, you'll probably want to read Webpack's
[guide on code splitting](https://webpack.js.org/guides/code-splitting/). Your Webpack config should look vaguely [like this](https://gist.github.com/gaearon/ca6e803f5c604d37468b0091d9959269).
如果你是自行設定 Webpack,你可以閱讀 Webpack 的 [code-splitting 指南](https://webpack.js.org/guides/code-splitting/)。你的 Webpack 設定看起來應該[像這樣](https://gist.github.com/gaearon/ca6e803f5c604d37468b0091d9959269)。

When using [Babel](https://babeljs.io/), you'll need to make sure that Babel can
parse the dynamic import syntax but is not transforming it. For that you will need [babel-plugin-syntax-dynamic-import](https://yarnpkg.com/en/package/babel-plugin-syntax-dynamic-import).
當使用 [Babel](https://babeljs.io/) 時,你將需要確保 Babel 可以解析動態的 import 語法而不是去轉換它。你可能會需要 [babel-plugin-syntax-dynamic-import](https://yarnpkg.com/en/package/babel-plugin-syntax-dynamic-import)。

## `React.lazy` {#reactlazy}

> Note:
> 注意:
>
> `React.lazy` and Suspense is not yet available for server-side rendering. If you want to do code-splitting in a server rendered app, we recommend [Loadable Components](https://github.com/smooth-code/loadable-components). It has a nice [guide for bundle splitting with server-side rendering](https://github.com/smooth-code/loadable-components/blob/master/packages/server/README.md).
> `React.lazy` Suspense 還無法在 server-side render 使用。如果你想要在 server render 應用程式做 code-splitting,我們推薦 [Loadable Components](https://github.com/smooth-code/loadable-components)。它有一個用於 server-side render 的 [bundle splitting 的指南]((https://github.com/smooth-code/loadable-components/blob/master/packages/server/README.md))。

The `React.lazy` function lets you render a dynamic import as a regular component.
`React.lazy` 讓你 render 一個動態 import 的 component 作為正常的 component

**Before:**
**加入前:**

```js
import OtherComponent from './OtherComponent';
Expand All @@ -133,7 +107,7 @@ function MyComponent() {
}
```

**After:**
**加入後:**

```js
const OtherComponent = React.lazy(() => import('./OtherComponent'));
Expand All @@ -147,13 +121,13 @@ function MyComponent() {
}
```

This will automatically load the bundle containing the `OtherComponent` when this component gets rendered.
當 render 這個 component 時,將會自動的載入包含 `OtherComponent` 的 bundle。

`React.lazy` takes a function that must call a dynamic `import()`. This must return a `Promise` which resolves to a module with a `default` export containing a React component.
`React.lazy` 接受一個必須呼叫一個動態 `import()` 的 function。它必須回傳一個 `Promise`,resolve 一個包含 React component 的 `default` export 的 module。

### Suspense {#suspense}

If the module containing the `OtherComponent` is not yet loaded by the time `MyComponent` renders, we must show some fallback content while we're waiting for it to load - such as a loading indicator. This is done using the `Suspense` component.
如果在 `MyComponent` render 時,尚未載入包含 `OtherComponent` 的 module,我們必須在等待載入時,顯示一些 fallback 內容 - 像是一個載入的符號。這是使用 `Suspense` component 完成的。

```js
const OtherComponent = React.lazy(() => import('./OtherComponent'));
Expand All @@ -169,7 +143,7 @@ function MyComponent() {
}
```

The `fallback` prop accepts any React elements that you want to render while waiting for the component to load. You can place the `Suspense` component anywhere above the lazy component. You can even wrap multiple lazy components with a single `Suspense` component.
`fallback` prop 接受在等待 component 載入時要 render 的任何 React element。你可以將 `Suspense` component 放在 lazy component 上方的任何位置。你甚至可以包覆多個 lazy component 到 `Suspense` component 內。

```js
const OtherComponent = React.lazy(() => import('./OtherComponent'));
Expand All @@ -189,9 +163,9 @@ function MyComponent() {
}
```

### Error boundaries {#error-boundaries}
### 錯誤邊界 {#error-boundaries}

If the other module fails to load (for example, due to network failure), it will trigger an error. You can handle these errors to show a nice user experience and manage recovery with [Error Boundaries](/docs/error-boundaries.html). Once you've created your Error Boundary, you can use it anywhere above your lazy components to display an error state when there's a network error.
如果其他的 module 載入失敗(例如,因為網路失敗),它將會觸發一個錯誤。你可以透過[錯誤邊界](/docs/error-boundaries.html)處理這些錯誤來呈現一個好的使用者體驗和管理恢復。一旦你建立了你的錯誤邊界,你可以在任何的 lazy component 上方使用它,當網路發生錯誤時可以顯示一個錯誤狀態。

```js
import MyErrorBoundary from './MyErrorBoundary';
Expand All @@ -212,19 +186,13 @@ const MyComponent = () => (
);
```

## Route-based code splitting {#route-based-code-splitting}
## 基於 Route 的 Code-Splitting {#route-based-code-splitting}

Deciding where in your app to introduce code splitting can be a bit tricky. You
want to make sure you choose places that will split bundles evenly, but won't
disrupt the user experience.
在你的應用程式決定採用 code-splitting 可能有點棘手。你想要確保選擇的位置可以適當的 split bundle,但不會破壞使用者的體驗。

A good place to start is with routes. Most people on the web are used to
page transitions taking some amount of time to load. You also tend to be
re-rendering the entire page at once so your users are unlikely to be
interacting with other elements on the page at the same time.
Route 是一個開始的好地方。Web 上大多數的人都習慣花一些時間來等待頁面的過渡。你也傾向於重新 render 一次整個頁面,所以你的使用者不能同時與頁面上的其他 element 做互動。

Here's an example of how to setup route-based code splitting into your app using
libraries like [React Router](https://reacttraining.com/react-router/) with `React.lazy`.
這裡是如何在你的應用程式使用像是 [React Router](https://reacttraining.com/react-router/) 的函式庫與 `React.lazy` 來設定基於 route 的 code-splitting。

```js
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
Expand All @@ -247,7 +215,7 @@ const App = () => (

## Named Exports {#named-exports}

`React.lazy` currently only supports default exports. If the module you want to import uses named exports, you can create an intermediate module that reexports it as the default. This ensures that tree shaking keeps working and that you don't pull in unused components.
`React.lazy` 目前只支援 default exports。如果你想 import 的 module 使用 named export,你可以建立一個中介 module 來重新 export 它做為預設。這可以確保 tree shaking 不會 pull 無用的 component。

```js
// ManyComponents.js
Expand Down