Skip to content

Commit

Permalink
docs: translate some basic and advanced docs (#524)
Browse files Browse the repository at this point in the history
  • Loading branch information
Timeless0911 authored Dec 5, 2024
1 parent 71bfcca commit ed55ef3
Show file tree
Hide file tree
Showing 16 changed files with 488 additions and 37 deletions.
4 changes: 2 additions & 2 deletions website/docs/en/guide/advanced/output-compatibility.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ And install [core-js-pure](https://www.npmjs.com/package/core-js-pure) as the ru

<PackageManagerTabs command="add core-js-pure" />

Configure the Babel plugin with polyfill options, set the [target](https://babeljs.io/docs/options#targets) field to specify the target browser version.
Configure the Babel plugin with polyfill options, set the [targets](https://babeljs.io/docs/options#targets) field to specify the target browser version.

```ts title="rslib.config.ts" {1,11-24}
import { pluginBabel } from '@rsbuild/plugin-babel';
Expand Down Expand Up @@ -97,7 +97,7 @@ export default defineConfig({
#### Configurations

- For projects with `bundle` enabled, the Node Polyfill will be injected and included in the output.
- For projects with `bundle` disabled, polyfills are not injected into the output by default. To avoid inlining the polyfill in every module. The modules are externalized and need to be added to dependencies manually, follow these steps:
- For projects with `bundle` disabled, polyfills are not injected into the output by default. To avoid inlining the polyfill in every module, the modules are externalized and need to be added to dependencies manually, follow these steps:

1. Configure `output.external` with `resolvedPolyfillToModules`, which you can import from [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill). This will externalize the polyfill modules to the installed polyfill dependencies.
2. Install used polyfill modules as dependencies.
Expand Down
11 changes: 6 additions & 5 deletions website/docs/en/guide/advanced/third-party-deps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ Generally, third-party dependencies required by a project can be installed via t
}
```

Dependencies under `"dependencies"` are generally related to project code and builds, and if these third-party dependencies are declared under `"devDependencies"`, then there will be missing dependencies in production runtime.
Dependencies under `"dependencies"` are generally required for the package in runtime, and if these third-party dependencies are declared under `"devDependencies"`, then there will be missing dependencies in production runtime.

In addition to `"dependencies"`, `"peerDependencies"`can also declare dependencies that are needed in the production environment, but it puts more emphasis on the existence of these dependencies declared by `"peerDependencies"` in the project's runtime environment, similar to the plugin mechanism.

## Default handling of third-party dependencies

By default, **third-party dependencies under `"dependencies"`, `"optionalDependencies"` and `"peerDependencies"` are not bundled by Rslib**.
By default, third-party dependencies under `"dependencies"`, `"optionalDependencies"` and `"peerDependencies"` are not bundled by Rslib.

This is because when the npm package is installed, its `"dependencies"` will also be installed. By not packaging `"dependencies"`, you can reduce the size of the package product.

If you need to package some dependencies, it is recommended to move them from `"dependencies"` to `"devDependencies"`, which is equivalent to **prebundle** the dependencies and reduces the size of the dependency installation.
If you need to package some dependencies, it is recommended to move them from `"dependencies"` to `"devDependencies"`, which is equivalent to prebundle the dependencies and reduces the size of the dependency installation.

### Example

Expand Down Expand Up @@ -51,13 +51,14 @@ import * as __WEBPACK_EXTERNAL_MODULE_react__ from 'react';
console.info(__WEBPACK_EXTERNAL_MODULE_react__['default']);
```

If you want to modify the default processing, you can use the following API.
If you want to modify the default processing, you can use the following API:

- [lib.autoExternal](/config/lib/auto-external)
- [output.externals](/config/rsbuild/output#outputexternals)

## Exclude specified third-party dependencies

We previously introduced the use of [`lib.autoExternal`](/config/lib/auto-external). This configuration lets you manage third-party dependencies more precisely.
The configuration described above allows you to implement more fine-grained handling of third-party dependencies.

For example, when we need to leave only certain dependencies unbundled, we can configure it as follows.

Expand Down
32 changes: 12 additions & 20 deletions website/docs/en/guide/basic/output-format.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,33 @@ import MF from '../start/components/MF.mdx';

# Output Format

This sets the output format for the generated JavaScript files. There are three supported values now: `esm`, `cjs`, and `umd`. In this guide, we will discuss the differences between these formats and how to choose the right one for your library.
There are four supported output formats for the generated JavaScript files in Rslib: `esm`, `cjs`, `umd`, and `mf`. In this chapter, we will introduce the differences between these formats and how to choose the right one for your library.

## ESM / CJS

Library authors need to carefully consider which module formats to support. Let's understand ESM (ECMAScript Modules) and CJS (CommonJS) and when to use them.

### What are ESM and CJS?

<ESM />

- **ESM**: ESM is <ESM />

- **CommonJS**: [CommonJS](https://nodejs.org/api/modules.html#modules-commonjs-modules) is <CJS />

### What is the dilemma of esm / cjs
### What is the dilemma of ESM / CJS

> The following references are from [Node Modules at War: Why CommonJS and ES Modules Can't Get Along](https://redfin.engineering/node-modules-at-war-why-commonjs-and-es-modules-cant-get-along-9617135eeca1).
1. You can't `require()` ESM scripts; you can only import ESM scripts, like this: `import {foo} from 'foo'`
2. CJS scripts can't use static `import` statements like the one above.
3. ESM scripts can `import` CJS scripts, but only by using the default import syntax `import _ from 'lodash'`, not the named import syntax `import {shuffle} from 'lodash'`, which is a hassle if the CJS script uses named exports. (Except, sometimes, unpredictibly, Node can figure out what you meant!)
3. ESM scripts can `import` CJS scripts, but only by using the **default import** syntax `import _ from 'lodash'`, not the **named import** syntax `import {shuffle} from 'lodash'`, which is a hassle if the CJS script uses named exports. (Except, sometimes, unpredictibly, Node can figure out what you meant!)
4. ESM scripts can `require()` CJS scripts, even with named exports, but it's typically not worth the trouble, because it requires even more boilerplate, and, worst of all, bundlers like Webpack and Rollup don't/won't know how to work with ESM scripts that use `require()`.
5. CJS is the default; you have to opt-in to ESM mode. You can opt-in to ESM mode by renaming your script from `.js` to `.mjs`. Alternately, you can set `"type": "module"` in `package.json`, and then you can opt-out of ESM by renaming scripts from `.js` to `.cjs`. (You can even tweak just an individual subdirectory by putting a one-line `{"type": "module"}` `package.json` file in there.)

### When to support which format?

For different shapes of libraries, the choice of module format may vary. Here are two common scenarios:

#### ship [pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) package.
#### ship [pure ESM](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) package

shipping only ESM is the best choice for libraries that are intended to be used in modern environments, such as browser applications or Node.js applications that support ESM. However, if the upstream library is in format of CJS, they only can import pure ESM by using dynamic import like `const pureEsmLib = await import('pure-esm-lib')`.

Expand All @@ -47,7 +45,7 @@ shipping only ESM is the best choice for libraries that are intended to be used
- Some Node.js tools and libraries still have limited or incomplete support for ESM, requiring workarounds or additional configuration.
- You must explicitly include file extensions in import paths, which can be cumbersome, especially when working with TypeScript or other transpiled languages.

#### ship [ESM & CJS (dual)](https://antfu.me/posts/publish-esm-and-cjs#compatibility) package.
#### ship [ESM & CJS (dual)](https://antfu.me/posts/publish-esm-and-cjs#compatibility) package

The community is migrating to ESM, but there are still many projects using CJS. If you want to support both ESM and CJS, you can publish a dual package. For most library authors, offering dual formats is a safer and smoother way to access the best of both worlds. You could read antfu' blog post [Publish ESM and CJS packages](https://antfu.me/posts/publish-esm-and-cjs) for more details.

Expand All @@ -60,8 +58,8 @@ The community is migrating to ESM, but there are still many projects using CJS.

- **Cons:**

- Increased complexity: Maintaining two module formats adds complexity to the build process, requiring additional configuration and testing to ensure both versions work correctly14.
- Dual package hazard: Mixing ESM and CJS can lead to issues such as broken instanceof checks or unexpected behavior when dependencies are loaded in different formats13.
- Increased complexity: Maintaining two module formats adds complexity to the build process, requiring additional configuration and testing to ensure both versions work correctly.
- Dual package hazard: Mixing ESM and CJS can lead to issues such as broken instanceof checks or unexpected behavior when dependencies are loaded in different formats.

## UMD

Expand All @@ -78,17 +76,17 @@ A detailed answer from StackOverflow: [What is the Universal Module Definition (
> However, for frontend libraries, you still offer a single file for convenience, that users can download (from a CDN) and directly embed in their web pages. This still commonly employs a UMD pattern, it's just no longer written/copied by the library author into their source code, but added automatically by the transpiler/bundler.
>
> And similarly, for backend/universal libraries that are supposed to work in
> node.js, you still also distribute a commonjs module build via npm to support
> all the users who still use a legacy version of node.js (and don't want/need
> Node.js, you still also distribute a commonjs module build via npm to support
> all the users who still use a legacy version of Node.js (and don't want/need
> to employ a transpiler themselves). This is less common nowadays for new
> libraries, but existing ones try hard to stay backwards-compatible and not
> cause applications to break.
### How to build a UMD library?

- Set the `lib.format` to `umd` in the Rslib configuration file.
- If the library need to be exported with a name, set `lib.umdName` to the name of the UMD library.
- Use `output.externals` to specify the external dependencies that the UMD library depends on, `lib.autoExtension` is enabled by default for UMD.
- Set the [lib.format](/config/lib/format) to `umd` in the Rslib configuration file.
- If the library need to be exported with a name, set [lib.umdName](/config/lib/umd-name) to the name of the UMD library.
- Use [output.externals](/config/rsbuild/output#outputexternals) to specify the external dependencies that the UMD library depends on, [lib.autoExtension](/config/lib/auto-extension) is enabled by default for UMD.

### Examples

Expand Down Expand Up @@ -136,9 +134,3 @@ export default defineConfig({
### What is MF?

MF stands for Module Federation. <MF />

### When to use MF?

### How to build a MF library?

Check out [Advanced - Module Federation](/guide/advanced/module-federation) chapter for more details.
4 changes: 3 additions & 1 deletion website/docs/en/guide/basic/output-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ So first let's understand bundle and bundleless.

A bundle is a package of build artifacts, which may be a single file or multiple files based on a certain [code splitting strategy](https://esbuild.github.io/api/#splitting).

bundleless, on the other hand, means that each source file is compiled and built separately, but not bundled together. Each output file can be found with its corresponding source code file. The process of **bundleless build can also be understood as the process of code conversion of source files only**.
bundleless, on the other hand, means that each source file is compiled and built separately, but not bundled together. Each output file can be found with its corresponding source code file. The process of bundleless build can also be understood as the process of code conversion of source files only.

They have their own benefits.

- bundle can reduce the size of build artifacts and also pre-package dependencies to reduce the size of installed dependencies. Packaging libraries in advance can speed up application project builds.
- bundleless maintains the original file structure and is more conducive to debugging and tree shaking.

:::warning

bundleless is a single-file compilation mode, so for referencing and exporting types, you need to add the `type` keyword. For example, `import type { A } from './types'`. Please refer to [TypeScript - isolatedModules](/guide/basic/typescript#isolatedmodules) for more information.

:::

You can specify whether to bundle using the [bundle](/config/lib/bundle) option, which is set to `true` by default.
4 changes: 2 additions & 2 deletions website/docs/en/guide/basic/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export type { SomeType } from './types';
## tsconfig.json Path

Rslib by default reads the `tsconfig.json` file from the root directory. You can use [source.tsconfigPath](https://rsbuild.dev/config/source/tsconfig-path) to configure a custom tsconfig.json file path.
Rslib by default reads the `tsconfig.json` file from the root directory. You can use [source.tsconfigPath](/config/rsbuild/source#sourcetsconfigpath) to configure a custom `tsconfig.json` file path.

```ts
```ts title="rslib.config.ts"
export default {
lib: [
// ...
Expand Down
6 changes: 4 additions & 2 deletions website/docs/en/guide/basic/upgrade-rslib.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ This section explains how to upgrade the project's Rslib dependencies to the lat
{/* > Please see [Releases](/community/releases/index) to understand the Rsbuild release strategy. */}

:::info
Rslib is still in the early stages of development, and the API may change frequently. We recommend upgrading to the latest version to access new features and bug fixes. We plan to release version 0.1.0 in the fourth quarter of 2024.

Rslib is still in 0.x version stage, and the API may change frequently. We recommend upgrading to the latest version to access new features and bug fixes.

:::

## Using Taze
Expand All @@ -22,7 +24,7 @@ npx taze major --include "/(rsbuild|rslib)/" -w
```

:::tip
Rslib has not yet reached version 0.1.0, so you need to add the `major` parameter when updating.
Rslib has not yet reached version 1.0.0, so you need to add the `major` parameter when updating.
:::

The result will look similar to:
Expand Down
106 changes: 106 additions & 0 deletions website/docs/zh/guide/advanced/output-compatibility.mdx
Original file line number Diff line number Diff line change
@@ -1 +1,107 @@
import { Steps, SourceCode } from '@theme';
import { PackageManagerTabs } from '@theme';

# 产物兼容性

本节介绍如何指定支持的目标环境。

## 语法降级

通过设置 [lib.syntax](/config/lib/syntax),你可以选择 JavaScript 和 CSS 将被降级到的语法。你可以使用 [Browserslist](https://browsersl.ist/) 的查询语法。Rslib 还支持常见的 ECMAScript 版本号,例如 `ES2015`

Rslib 还支持使用 [.browserslistrc](https://github.com/browserslist/browserslist#config-file) 文件来设置。需要注意的是,[lib.syntax](/config/lib/syntax) 优先于 `.browserslistrc`。如果两者都存在,将使用 `lib.syntax`

默认情况下,syntax 被设置为 `ESNext`,这代表将仅支持主流浏览器(Chrome / Firefox / Edge / macOS Safari / iOS Safari)或 Node.js 的最新版本,具体取决于 [output.target](/config/rsbuild/output#outputtarget)

## Polyfill

在处理兼容性问题之前,建议了解以下背景知识,以便更好地处理相关问题。请查看有关[语法降级和 API 降级](https://rsbuild.dev/zh/guide/advanced/browser-compatibility#%E8%AF%AD%E6%B3%95%E9%99%8D%E7%BA%A7%E5%92%8C-api-%E9%99%8D%E7%BA%A7)的背景知识。

### 浏览器

通常,我们不需要为 npm 包注入 polyfill,这个步骤应该在 web 应用框架侧完成,但在某些场景下,我们需要注入 polyfill 以使我们的库直接在低版本浏览器中运行。

需要注意的是,这个插件不会转换你的代码语法,它只会为代码中使用的未支持函数注入 polyfill,将它们作为普通函数导入,而不是污染全局。你需要安装 [core-js-pure](https://www.npmjs.com/package/core-js-pure) 依赖。

#### 设置

polyfill 依赖于 Babel 注入 polyfill 代码,因此你需要安装 [Rsbuild Babel 插件](https://rsbuild.dev/zh/plugins/list/plugin-babel)[babel-plugin-polyfill-corejs3](https://www.npmjs.com/package/babel-plugin-polyfill-corejs3) 来注入 polyfill 代码。

<PackageManagerTabs command="add @rsbuild/plugin-babel babel-plugin-polyfill-corejs3 -D" />

并安装 [core-js-pure](https://www.npmjs.com/package/core-js-pure) 作为运行时依赖代码。

<PackageManagerTabs command="add core-js-pure" />

配置 Babel 插件,设置 [targets](https://babeljs.io/docs/options#targets) 字段以指定目标浏览器版本。

```ts title="rslib.config.ts" {1,11-24}
import { pluginBabel } from '@rsbuild/plugin-babel';
import { defineConfig } from '@rslib/core';

export default defineConfig({
lib: [
{
format: 'esm',
},
],
plugins: [
pluginBabel({
babelLoaderOptions: {
plugins: [
[
require('babel-plugin-polyfill-corejs3'),
{
method: 'usage-pure',
targets: { ie: '10' },
version: '3.29',
},
],
],
},
}),
],
});
```

#### 配置

更多详细信息,请查看 [babel-plugin-polyfill-corejs3](https://www.npmjs.com/package/babel-plugin-polyfill-corejs3) 文档。

### Node.js

:::tip 关于 Node Polyfill
通常,我们不需要在浏览器侧使用 Node 库。然而,在某些情况下,代码将在 Node 侧和浏览器侧运行,Node Polyfill 提供了这些 Node 库的浏览器版本 polyfill。
:::

通过使用 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill),Node 核心库的 polyfill 会自动注入到浏览器侧,允许你在浏览器侧使用这些模块。

#### 设置

Rslib 使用 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) 提供 Node Polyfill 功能。

<PackageManagerTabs command="add @rsbuild/plugin-node-polyfill -D" />

然后将其添加到插件字段中。

```ts title="rslib.config.ts"
import { defineConfig } from '@rslib/core';
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';

export default defineConfig({
lib: [{ format: 'esm' }],
plugins: [pluginNodePolyfill()],
});
```

#### 配置

- 对于启用了 `bundle` 的项目,Node Polyfill 将被注入并包含在输出中。
- 对于未启用 `bundle` 的项目,默认情况下不会注入 polyfill。为了避免在每个模块中内联 polyfill,模块需要被 external,并手动添加到依赖中,请按照以下步骤操作:

1. 配置 `output.external``resolvedPolyfillToModules`,你可以从 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) 导入。这将 polyfill 模块 external 到已安装的 polyfill 依赖中。
2. 安装使用的 polyfill 模块作为依赖。

通过以下步骤,每个 polyfill 模块的使用将被替换为 `externals` 字段中的相应模块。更多详细信息,请查看 <SourceCode href="https://github.com/web-infra-dev/rslib/blob/main/tests/integration/node-polyfill/bundle-false/rslib.config.ts" /> 的示例。

更多详细信息,请查看 [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) 文档,所有配置均适用于 Rslib。
Loading

0 comments on commit ed55ef3

Please sign in to comment.