@modern-js/main-doc 2.58.3 → 2.59.0
Sign up to get free protection for your applications and to get access to all the features.
- package/docs/en/apis/app/runtime/core/use-loader.mdx +1 -1
- package/docs/en/components/init-app.mdx +0 -1
- package/docs/en/components/init-rspack-app.mdx +0 -1
- package/docs/en/components/ssr-monitor.mdx +3 -0
- package/docs/en/configure/app/output/ssg.mdx +52 -141
- package/docs/en/configure/app/tools/tailwindcss.mdx +1 -1
- package/docs/en/guides/advanced-features/_meta.json +0 -8
- package/docs/en/guides/advanced-features/rsbuild-plugin.mdx +2 -2
- package/docs/en/guides/advanced-features/rspack-start.mdx +6 -14
- package/docs/en/guides/basic-features/_meta.json +31 -9
- package/docs/en/guides/basic-features/css/_meta.json +1 -0
- package/docs/en/guides/basic-features/css/css-in-js.mdx +34 -0
- package/docs/en/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -4
- package/docs/en/guides/basic-features/css/css.mdx +25 -0
- package/docs/en/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +5 -66
- package/docs/en/guides/basic-features/data/data-fetch.mdx +134 -235
- package/docs/en/guides/basic-features/data/data-write.mdx +66 -77
- package/docs/en/guides/basic-features/debug/_meta.json +1 -0
- package/docs/en/guides/basic-features/debug/rsdoctor.mdx +57 -0
- package/docs/en/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +2 -0
- package/docs/en/guides/basic-features/render/_meta.json +1 -0
- package/docs/en/guides/basic-features/render/ssg.mdx +208 -0
- package/docs/en/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +38 -50
- package/docs/en/guides/basic-features/render/ssr.mdx +301 -0
- package/docs/en/guides/basic-features/render/streaming-ssr.mdx +230 -0
- package/docs/en/guides/basic-features/routes.mdx +275 -263
- package/docs/en/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/en/guides/basic-features/static-assets.mdx +1 -1
- package/docs/en/guides/basic-features/testing/_meta.json +1 -0
- package/docs/en/guides/basic-features/testing/cypress.mdx +95 -0
- package/docs/en/guides/basic-features/testing/jest.mdx +148 -0
- package/docs/en/guides/basic-features/testing/playwright.mdx +111 -0
- package/docs/en/guides/basic-features/testing/vitest.mdx +100 -0
- package/docs/en/guides/concept/entries.mdx +9 -2
- package/docs/en/guides/get-started/quick-start.mdx +1 -1
- package/docs/en/guides/get-started/tech-stack.mdx +4 -4
- package/docs/en/guides/topic-detail/generator/create/config.mdx +0 -10
- package/docs/en/guides/topic-detail/generator/create/use.mdx +0 -1
- package/docs/en/tutorials/first-app/c03-css.mdx +1 -1
- package/docs/zh/apis/app/runtime/core/use-loader.mdx +1 -1
- package/docs/zh/components/init-app.mdx +0 -1
- package/docs/zh/components/init-rspack-app.mdx +0 -1
- package/docs/zh/components/ssr-monitor.mdx +3 -0
- package/docs/zh/configure/app/output/ssg.mdx +49 -139
- package/docs/zh/configure/app/tools/tailwindcss.mdx +1 -1
- package/docs/zh/guides/advanced-features/_meta.json +0 -8
- package/docs/zh/guides/advanced-features/rsbuild-plugin.mdx +2 -2
- package/docs/zh/guides/advanced-features/rspack-start.mdx +7 -16
- package/docs/zh/guides/basic-features/_meta.json +31 -9
- package/docs/zh/guides/basic-features/css/_meta.json +1 -0
- package/docs/zh/guides/basic-features/css/css-in-js.mdx +34 -0
- package/docs/zh/guides/basic-features/css/css.mdx +25 -0
- package/docs/zh/guides/basic-features/{css.mdx → css/tailwindcss.mdx} +3 -64
- package/docs/zh/guides/basic-features/data/data-fetch.mdx +96 -211
- package/docs/zh/guides/basic-features/data/data-write.mdx +54 -55
- package/docs/zh/guides/basic-features/debug/_meta.json +1 -0
- package/docs/zh/guides/basic-features/debug/rsdoctor.mdx +57 -0
- package/docs/zh/guides/{advanced-features → basic-features/debug}/using-storybook.mdx +1 -1
- package/docs/zh/guides/basic-features/render/_meta.json +1 -0
- package/docs/zh/guides/basic-features/render/ssg.mdx +210 -0
- package/docs/zh/guides/{advanced-features/ssr/cache.mdx → basic-features/render/ssr-cache.mdx} +16 -26
- package/docs/zh/guides/basic-features/render/ssr.mdx +309 -0
- package/docs/zh/guides/{advanced-features/ssr/stream.mdx → basic-features/render/streaming-ssr.mdx} +22 -37
- package/docs/zh/guides/basic-features/routes.mdx +252 -237
- package/docs/zh/guides/basic-features/static-assets/_meta.json +1 -0
- package/docs/zh/guides/basic-features/static-assets.mdx +2 -6
- package/docs/zh/guides/basic-features/testing/_meta.json +1 -0
- package/docs/zh/guides/basic-features/testing/cypress.mdx +95 -0
- package/docs/zh/guides/basic-features/testing/jest.mdx +148 -0
- package/docs/zh/guides/basic-features/testing/playwright.mdx +112 -0
- package/docs/zh/guides/basic-features/testing/vitest.mdx +100 -0
- package/docs/zh/guides/concept/entries.mdx +6 -3
- package/docs/zh/guides/get-started/quick-start.mdx +1 -1
- package/docs/zh/guides/get-started/tech-stack.mdx +8 -8
- package/docs/zh/guides/topic-detail/generator/create/config.mdx +0 -10
- package/docs/zh/guides/topic-detail/generator/create/use.mdx +0 -1
- package/docs/zh/tutorials/first-app/c03-css.mdx +1 -1
- package/i18n.json +16 -4
- package/package.json +6 -6
- package/docs/en/apis/app/hooks/config/storybook.mdx +0 -37
- package/docs/en/guides/advanced-features/ssg.mdx +0 -116
- package/docs/en/guides/advanced-features/ssr/_meta.json +0 -1
- package/docs/en/guides/advanced-features/ssr/index.mdx +0 -23
- package/docs/en/guides/advanced-features/ssr/stream.mdx +0 -248
- package/docs/en/guides/advanced-features/ssr/usage.mdx +0 -341
- package/docs/en/guides/advanced-features/ssr.mdx +0 -555
- package/docs/zh/apis/app/hooks/config/storybook.mdx +0 -38
- package/docs/zh/guides/advanced-features/ssg.mdx +0 -116
- package/docs/zh/guides/advanced-features/ssr/_meta.json +0 -1
- package/docs/zh/guides/advanced-features/ssr/index.mdx +0 -23
- package/docs/zh/guides/advanced-features/ssr/usage.mdx +0 -329
- /package/docs/en/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
- /package/docs/en/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
- /package/docs/en/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
- /package/docs/en/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
- /package/docs/en/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{css-modules.mdx → css/css-modules.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{mock.mdx → debug/mock.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{proxy.mdx → debug/proxy.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{json-files.mdx → static-assets/json-files.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{svg-assets.mdx → static-assets/svg-assets.mdx} +0 -0
- /package/docs/zh/guides/basic-features/{wasm-assets.mdx → static-assets/wasm-assets.mdx} +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
["json-files", "svg-assets", "wasm-assets"]
|
@@ -21,7 +21,7 @@ The following are the formats supported by Modern.js by default:
|
|
21
21
|
If you need to import assets in other formats, please refer to [Extend Asset Types](#extend-asset-types).
|
22
22
|
|
23
23
|
:::tip SVG images
|
24
|
-
SVG image is a special case. Modern.js support convert SVG to React components, so SVG is processed separately. For details, see [Import SVG Assets](/guides/basic-features/svg-assets.html).
|
24
|
+
SVG image is a special case. Modern.js support convert SVG to React components, so SVG is processed separately. For details, see [Import SVG Assets](/guides/basic-features/static-assets/svg-assets.html).
|
25
25
|
:::
|
26
26
|
|
27
27
|
## Import Assets in JS file
|
@@ -0,0 +1 @@
|
|
1
|
+
["playwright", "vitest", "jest", "cypress"]
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Cypress
|
2
|
+
|
3
|
+
Cypress is a framework for E2E testing and component testing.
|
4
|
+
|
5
|
+
To use Cypress in Modern.js, you need to install the dependencies first. You can run the following commands:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{ npm: "npm install -D cypress", yarn: "yarn add -D cypress", pnpm: "pnpm install -D cypress" }} />
|
10
|
+
|
11
|
+
Next, create a `cypress.config.ts` file and add the following content:
|
12
|
+
|
13
|
+
```ts
|
14
|
+
import { defineConfig } from 'cypress'
|
15
|
+
|
16
|
+
export default defineConfig({
|
17
|
+
e2e: {
|
18
|
+
setupNodeEvents(on, config) {},
|
19
|
+
},
|
20
|
+
})
|
21
|
+
```
|
22
|
+
|
23
|
+
## Writing Test Cases
|
24
|
+
|
25
|
+
Now, use Cypress to write an E2E test case by first creating two Modern.js pages.
|
26
|
+
|
27
|
+
```tsx title="routes/page.tsx"
|
28
|
+
import { Link } from '@modern-js/runtime/router';
|
29
|
+
|
30
|
+
const Index = () => (
|
31
|
+
<div>
|
32
|
+
<h1>Home</h1>
|
33
|
+
<Link to="/about">About</Link>
|
34
|
+
</div>
|
35
|
+
);
|
36
|
+
|
37
|
+
export default Index;
|
38
|
+
```
|
39
|
+
|
40
|
+
```tsx title="routes/about/page.tsx"
|
41
|
+
import { Link } from '@modern-js/runtime/router';
|
42
|
+
|
43
|
+
const Index = () => (
|
44
|
+
<div>
|
45
|
+
<h1>About</h1>
|
46
|
+
<Link to="/">Home</Link>
|
47
|
+
</div>
|
48
|
+
);
|
49
|
+
|
50
|
+
export default Index;
|
51
|
+
```
|
52
|
+
|
53
|
+
Next, create the test case file:
|
54
|
+
|
55
|
+
```ts title="cypress/e2e/app.cy.ts"
|
56
|
+
describe('Navigation', () => {
|
57
|
+
it('should navigate to the about page', () => {
|
58
|
+
// Start from the index page
|
59
|
+
cy.visit('http://localhost:8080/')
|
60
|
+
|
61
|
+
// Find a link with an href attribute containing "about" and click it
|
62
|
+
cy.get('a[href*="about"]').click()
|
63
|
+
|
64
|
+
// The new url should include "/about"
|
65
|
+
cy.url().should('include', '/about')
|
66
|
+
|
67
|
+
// The new page should contain an h1 with "About"
|
68
|
+
cy.get('h1').contains('About')
|
69
|
+
})
|
70
|
+
})
|
71
|
+
```
|
72
|
+
|
73
|
+
The test file may lack type definitions for the API. You can refer to the [Cypress - Typescript](https://docs.cypress.io/guides/tooling/typescript-support#Configure-tsconfigjson) documentation to resolve this.
|
74
|
+
|
75
|
+
You can add the command to your `package.json`:
|
76
|
+
|
77
|
+
```json title="package.json"
|
78
|
+
{
|
79
|
+
"scripts": {
|
80
|
+
"test": "cypress open"
|
81
|
+
}
|
82
|
+
}
|
83
|
+
```
|
84
|
+
|
85
|
+
## Run Test Cases
|
86
|
+
|
87
|
+
Execute the above `test` command to run the test cases:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
DevTools listening on ws://127.0.0.1:55203/devtools/browser/xxxxx
|
91
|
+
```
|
92
|
+
|
93
|
+
Cypress will open a headless browser. Following the prompts, you can find the corresponding test files and automatically run the E2E tests:
|
94
|
+
|
95
|
+

|
@@ -0,0 +1,148 @@
|
|
1
|
+
# Jest
|
2
|
+
|
3
|
+
Jest is a JavaScript testing framework that is primarily used with React Testing Library for unit testing and Snapshot testing.
|
4
|
+
|
5
|
+
To use Jest in Modern.js, you need to install the dependencies first. You can run the following commands:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{
|
10
|
+
npm: "npm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom",
|
11
|
+
yarn: "yarn add -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom",
|
12
|
+
pnpm: "pnpm install -D jest jest-environment-jsdom @testing-library/react @testing-library/dom @testing-library/jest-dom"
|
13
|
+
}} />
|
14
|
+
|
15
|
+
Next, you can run the following commands to automatically initialize Jest in your project and generate a basic `jest.config.[jt]s` configuration:
|
16
|
+
|
17
|
+
<PackageManagerTabs command={{
|
18
|
+
npm: "npm init jest@latest",
|
19
|
+
yarn: "yarn create jest@latest",
|
20
|
+
pnpm: "pnpm create jest@latest"
|
21
|
+
}} />
|
22
|
+
|
23
|
+
## Configuration File
|
24
|
+
|
25
|
+
:::note
|
26
|
+
This section will use `.ts` files for Jest testing.
|
27
|
+
:::
|
28
|
+
|
29
|
+
Compared to other testing frameworks, Jest requires more configuration at the build level, such as handling JSX and ESM syntax. Therefore, you need to install some additional dependencies:
|
30
|
+
|
31
|
+
<PackageManagerTabs command={{
|
32
|
+
npm: "npm install -D babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript",
|
33
|
+
yarn: "yarn add -D babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript",
|
34
|
+
pnpm: "pnpm install -D babel-jest @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript"
|
35
|
+
}} />
|
36
|
+
|
37
|
+
### Configure Jest
|
38
|
+
|
39
|
+
You need to further configure the `jest.config.ts` file to allow Jest to correctly compile and run test cases. Here is a basic configuration:
|
40
|
+
|
41
|
+
```ts title="jest.config.ts"
|
42
|
+
import type { Config } from 'jest';
|
43
|
+
|
44
|
+
const config: Config = {
|
45
|
+
coverageProvider: 'babel',
|
46
|
+
setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'],
|
47
|
+
testEnvironment: 'jsdom',
|
48
|
+
transform: {
|
49
|
+
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
|
50
|
+
},
|
51
|
+
transformIgnorePatterns: [],
|
52
|
+
};
|
53
|
+
|
54
|
+
export default config;
|
55
|
+
```
|
56
|
+
|
57
|
+
In the configuration, the `transformIgnorePatterns` is set to an empty array, meaning that all files will be compiled. If you want to speed up the test run, you can configure it as needed.
|
58
|
+
|
59
|
+
The `setupFilesAfterEnv` will be executed at startup. In `jest.setup.ts`, you can import `@testing-library/jest-dom`, which includes a set of convenient custom matchers, such as `.toBeInTheDocument()`, to make writing tests easier:
|
60
|
+
|
61
|
+
```ts title="jest.setup.ts"
|
62
|
+
import '@testing-library/jest-dom';
|
63
|
+
```
|
64
|
+
|
65
|
+
### Configure Babel
|
66
|
+
|
67
|
+
You need to configure Babel to allow Jest to automatically compile JSX and other syntax. Here is a basic configuration:
|
68
|
+
|
69
|
+
```js title="babel.config.js"
|
70
|
+
module.exports = {
|
71
|
+
presets: [
|
72
|
+
['@babel/preset-env', { targets: { node: 'current' } }],
|
73
|
+
['@babel/preset-react', { runtime: 'automatic' }],
|
74
|
+
'@babel/preset-typescript',
|
75
|
+
],
|
76
|
+
};
|
77
|
+
```
|
78
|
+
|
79
|
+
## Writing Test Cases
|
80
|
+
|
81
|
+
Now, you can start writing tests. First, add a `test` command in `package.json`:
|
82
|
+
|
83
|
+
```json title="package.json"
|
84
|
+
{
|
85
|
+
"scripts": {
|
86
|
+
"test": "jest"
|
87
|
+
}
|
88
|
+
}
|
89
|
+
```
|
90
|
+
|
91
|
+
Create a simple page for testing:
|
92
|
+
|
93
|
+
```tsx title="routes/page.tsx"
|
94
|
+
import { Link } from '@modern-js/runtime/router';
|
95
|
+
|
96
|
+
const Index = () => (
|
97
|
+
<div>
|
98
|
+
<h1>Home</h1>
|
99
|
+
<Link to="/about">About</Link>
|
100
|
+
</div>
|
101
|
+
);
|
102
|
+
|
103
|
+
export default Index;
|
104
|
+
```
|
105
|
+
|
106
|
+
Add a test case to check if the page has the expected text:
|
107
|
+
|
108
|
+
```tsx title="__tests__/page.test.tsx"
|
109
|
+
import '@testing-library/jest-dom';
|
110
|
+
import { render, screen } from '@testing-library/react';
|
111
|
+
import { BrowserRouter as Router } from '@modern-js/runtime/router';
|
112
|
+
import Page from '../routes/page';
|
113
|
+
|
114
|
+
describe('Page', () => {
|
115
|
+
it('renders a heading', () => {
|
116
|
+
render(
|
117
|
+
<Router>
|
118
|
+
<Page />
|
119
|
+
</Router>,
|
120
|
+
);
|
121
|
+
|
122
|
+
const heading = screen.getByRole('heading', { level: 1 });
|
123
|
+
|
124
|
+
expect(heading).toBeInTheDocument();
|
125
|
+
});
|
126
|
+
});
|
127
|
+
```
|
128
|
+
|
129
|
+
In the above test case, we imported the `<Router>` component from `@modern-js/runtime/router` because React Router requires the corresponding context when rendering some route-related components.
|
130
|
+
|
131
|
+
:::note
|
132
|
+
When running directly in the Modern.js application, the `<Router>` component will be automatically injected.
|
133
|
+
:::
|
134
|
+
|
135
|
+
## Run Test Cases
|
136
|
+
|
137
|
+
Execute the above `test` command to run the test cases:
|
138
|
+
|
139
|
+
```bash
|
140
|
+
PASS src/__tests__/page.test.tsx
|
141
|
+
Page
|
142
|
+
✓ renders a heading (31 ms)
|
143
|
+
|
144
|
+
Test Suites: 1 passed, 1 total
|
145
|
+
Tests: 1 passed, 1 total
|
146
|
+
Snapshots: 0 total
|
147
|
+
Time: 0.959 s, estimated 1 s
|
148
|
+
```
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# Playwright
|
2
|
+
|
3
|
+
Playwright is a testing framework that allows you to run tests automatically in Chromium, Firefox, and WebKit environments using a single API. You can use it to **write E2E tests**.
|
4
|
+
|
5
|
+
To use Playwright in Modern.js, you need to install the dependencies first. You can run the following commands:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{ npm: "npm init playwright", yarn: "yarn create playwright", pnpm: "pnpm create playwright" }} />
|
10
|
+
|
11
|
+
The above commands will automatically install Playwright dependencies and help you install and configure it in your project through a series of prompts, including adding a `playwright.config.ts` file.
|
12
|
+
|
13
|
+
:::info
|
14
|
+
Refer to the official Playwright documentation at [Install Playwright](https://playwright.dev/docs/intro#installation) for a more detailed guide.
|
15
|
+
:::
|
16
|
+
|
17
|
+
After creating with the default configuration, you can see the following files in your project:
|
18
|
+
|
19
|
+
```ts title="tests/example.spec.ts"
|
20
|
+
import { test, expect } from '@playwright/test';
|
21
|
+
|
22
|
+
test('has title', async ({ page }) => {
|
23
|
+
await page.goto('https://playwright.dev/');
|
24
|
+
|
25
|
+
// Expect a title "to contain" a substring.
|
26
|
+
await expect(page).toHaveTitle(/Playwright/);
|
27
|
+
});
|
28
|
+
|
29
|
+
test('get started link', async ({ page }) => {
|
30
|
+
await page.goto('https://playwright.dev/');
|
31
|
+
|
32
|
+
// Click the get started link.
|
33
|
+
await page.getByRole('link', { name: 'Get started' }).click();
|
34
|
+
|
35
|
+
// Expects page to have a heading with the name of Installation.
|
36
|
+
await expect(
|
37
|
+
page.getByRole('heading', { name: 'Installation' }),
|
38
|
+
).toBeVisible();
|
39
|
+
});
|
40
|
+
```
|
41
|
+
|
42
|
+
This is the default test file. Now create some new pages and test them.
|
43
|
+
|
44
|
+
## Create E2E Tests
|
45
|
+
|
46
|
+
First, create two Modern.js pages.
|
47
|
+
|
48
|
+
```tsx title="routes/page.tsx"
|
49
|
+
import { Link } from '@modern-js/runtime/router';
|
50
|
+
|
51
|
+
const Index = () => (
|
52
|
+
<div>
|
53
|
+
<h1>Home</h1>
|
54
|
+
<Link to="/about">About</Link>
|
55
|
+
</div>
|
56
|
+
);
|
57
|
+
|
58
|
+
export default Index;
|
59
|
+
```
|
60
|
+
|
61
|
+
```tsx title="routes/about/page.tsx"
|
62
|
+
import { Link } from '@modern-js/runtime/router';
|
63
|
+
|
64
|
+
const Index = () => (
|
65
|
+
<div>
|
66
|
+
<h1>About</h1>
|
67
|
+
<Link to="/">Home</Link>
|
68
|
+
</div>
|
69
|
+
);
|
70
|
+
|
71
|
+
export default Index;
|
72
|
+
```
|
73
|
+
|
74
|
+
Next, add test cases to ensure the links on your pages work properly.
|
75
|
+
|
76
|
+
```ts title="tests/example.spec.ts"
|
77
|
+
import { test, expect } from '@playwright/test'
|
78
|
+
|
79
|
+
test('should navigate to the about page', async ({ page }) => {
|
80
|
+
// Start from the index page (the baseURL is set via the webServer in the playwright.config.ts)
|
81
|
+
await page.goto('http://localhost:8080/')
|
82
|
+
// Find an element with the text 'About' and click on it
|
83
|
+
await page.click('text=About')
|
84
|
+
// The new URL should be "/about" (baseURL is used there)
|
85
|
+
await expect(page).toHaveURL('http://localhost:8080/about')
|
86
|
+
// The new page should contain an h1 with "About"
|
87
|
+
await expect(page.locator('h1')).toContainText('About')
|
88
|
+
})
|
89
|
+
```
|
90
|
+
|
91
|
+
## Run Test Cases
|
92
|
+
|
93
|
+
Playwright requires your Modern.js server to be running. We recommend running your test cases under production builds; you can run `pnpm run build` and `pnpm run serve` to simulate the production environment locally.
|
94
|
+
|
95
|
+
```bash
|
96
|
+
info Starting production server...
|
97
|
+
|
98
|
+
> Local: http://localhost:8080/
|
99
|
+
> Network: http://10.94.59.30:8080/
|
100
|
+
```
|
101
|
+
|
102
|
+
After the project is successfully built and running, you can run Playwright cases in another terminal by executing `npx playwright test`:
|
103
|
+
|
104
|
+
```bash
|
105
|
+
Running 3 tests using 3 workers
|
106
|
+
3 passed (2.0s)
|
107
|
+
|
108
|
+
To open last HTML report run:
|
109
|
+
|
110
|
+
npx playwright show-report
|
111
|
+
```
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# Vitest
|
2
|
+
|
3
|
+
Vitest is a testing framework driven by Vite, which can be used for unit testing in combination with React Testing Library.
|
4
|
+
|
5
|
+
To use Vitest in Modern.js, you need to install the dependencies first. You can run the following commands:
|
6
|
+
|
7
|
+
import { PackageManagerTabs } from '@theme';
|
8
|
+
|
9
|
+
<PackageManagerTabs command={{
|
10
|
+
npm: "npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom",
|
11
|
+
yarn: "yarn add -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom",
|
12
|
+
pnpm: "pnpm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom",
|
13
|
+
bun: "bun add -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom"
|
14
|
+
}} />
|
15
|
+
|
16
|
+
Next, you need to create a Vitest configuration file `vitest.config.ts` with the following content:
|
17
|
+
|
18
|
+
```ts title="vitest.config.ts"
|
19
|
+
import { defineConfig } from 'vitest/config'
|
20
|
+
import react from '@vitejs/plugin-react'
|
21
|
+
|
22
|
+
export default defineConfig({
|
23
|
+
plugins: [react()],
|
24
|
+
test: {
|
25
|
+
environment: 'jsdom',
|
26
|
+
},
|
27
|
+
})
|
28
|
+
```
|
29
|
+
|
30
|
+
For more information about Vitest configuration, you can refer to the [Vitest configuration documentation](https://vitest.dev/config/#configuration).
|
31
|
+
|
32
|
+
You can optionally add the `vitest` command to `package.json`:
|
33
|
+
|
34
|
+
```json title="package.json"
|
35
|
+
{
|
36
|
+
"scripts": {
|
37
|
+
"test": "vitest"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
```
|
41
|
+
|
42
|
+
After running this command, Vitest will automatically watch your file changes and rerun the test cases.
|
43
|
+
|
44
|
+
## Create Unit Tests
|
45
|
+
|
46
|
+
First, create a simple page for testing:
|
47
|
+
|
48
|
+
```tsx title="routes/page.tsx"
|
49
|
+
import { Link } from '@modern-js/runtime/router';
|
50
|
+
|
51
|
+
const Index = () => (
|
52
|
+
<div>
|
53
|
+
<h1>Home</h1>
|
54
|
+
<Link to="/about">About</Link>
|
55
|
+
</div>
|
56
|
+
);
|
57
|
+
|
58
|
+
export default Index;
|
59
|
+
```
|
60
|
+
|
61
|
+
Add a test case to check if the page has the expected text:
|
62
|
+
|
63
|
+
```tsx title="__tests__/page.test.tsx"
|
64
|
+
import { expect, test } from 'vitest';
|
65
|
+
import { render, screen } from '@testing-library/react';
|
66
|
+
import { BrowserRouter as Router } from '@modern-js/runtime/router';
|
67
|
+
import Page from '../routes/page';
|
68
|
+
|
69
|
+
test('Page', () => {
|
70
|
+
render(
|
71
|
+
<Router>
|
72
|
+
<Page />
|
73
|
+
</Router>,
|
74
|
+
);
|
75
|
+
expect(screen.getByRole('heading', { level: 1, name: 'Home' })).toBeDefined();
|
76
|
+
});
|
77
|
+
```
|
78
|
+
|
79
|
+
In the above test case, we imported the `<Router>` component from `@modern-js/runtime/router` because React Router requires the corresponding context when rendering some route-related components.
|
80
|
+
|
81
|
+
:::note
|
82
|
+
When running directly in the Modern.js application, the `<Router>` component will be automatically injected.
|
83
|
+
:::
|
84
|
+
|
85
|
+
## Run Test Cases
|
86
|
+
|
87
|
+
Execute the above `test` command to run the test cases:
|
88
|
+
|
89
|
+
```bash
|
90
|
+
✓ src/__tests__/page.test.tsx (1)
|
91
|
+
✓ Page
|
92
|
+
|
93
|
+
Test Files 1 passed (1)
|
94
|
+
Tests 1 passed (1)
|
95
|
+
Start at 15:37:12
|
96
|
+
Duration 999ms (transform 119ms, setup 0ms, collect 365ms, tests 33ms, environment 421ms, prepare 44ms)
|
97
|
+
|
98
|
+
|
99
|
+
PASS Waiting for file changes...
|
100
|
+
```
|
@@ -116,6 +116,8 @@ For more information, please refer to [Conventional Routing](/guides/basic-featu
|
|
116
116
|
|
117
117
|
#### Self-controlled Routing
|
118
118
|
|
119
|
+
## Manual Routing
|
120
|
+
|
119
121
|
If there is an `App.[jt]sx?` file within the entry, we refer to this entry as a self-controlled route. For example:
|
120
122
|
|
121
123
|
```bash
|
@@ -124,7 +126,9 @@ If there is an `App.[jt]sx?` file within the entry, we refer to this entry as a
|
|
124
126
|
│ └── App.tsx
|
125
127
|
```
|
126
128
|
|
127
|
-
|
129
|
+
For entry points defined as `src/App.tsx`, Modern.js does not perform any additional routing operations. Developers can use the [React Router 6](https://reactrouter.com/en/main) API for development, define client-side routes or not to set any client-side routes.
|
130
|
+
|
131
|
+
for example, define client-side routes in application:
|
128
132
|
|
129
133
|
```tsx
|
130
134
|
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
|
@@ -141,7 +145,10 @@ export default () => {
|
|
141
145
|
};
|
142
146
|
```
|
143
147
|
|
144
|
-
|
148
|
+
:::note
|
149
|
+
We recommend that developers use conventional routing. Modern.js provides a series of optimizations in resource loading and rendering for conventional routing by default and offers built-in SSR capabilities. When using manual routing, these capabilities need to be encapsulated by developers themselves.
|
150
|
+
:::
|
151
|
+
|
145
152
|
|
146
153
|
#### Custom Entry
|
147
154
|
|
@@ -60,7 +60,7 @@ During production builds, Modern.js uses [Terser](https://github.com/terser/ters
|
|
60
60
|
|
61
61
|
Modern.js uses [PostCSS](https://postcss.org/) to transform CSS code and enables [autoprefixer](https://github.com/postcss/autoprefixer) by default to add CSS prefixes.
|
62
62
|
|
63
|
-
Modern.js supports enabling ["Tailwind CSS"](/
|
63
|
+
Modern.js supports enabling ["Tailwind CSS"](/guides/basic-features/css/tailwindcss) and is compatible with both Tailwind CSS v2 and v3.
|
64
64
|
|
65
65
|
## CSS Preprocessors
|
66
66
|
|
@@ -73,11 +73,11 @@ Modern.js supports three CSS preprocessors: [Sass](https://sass-lang.com/), [Les
|
|
73
73
|
|
74
74
|
Modern.js provides out-of-the-box support for [CSS Modules](https://github.com/css-modules/css-modules), which is implemented internally based on [css-loader](https://www.npmjs.com/package/css-loader).
|
75
75
|
|
76
|
-
Please refer to ["Use CSS Modules"](/guides/basic-features/css-modules) for usage instructions.
|
76
|
+
Please refer to ["Use CSS Modules"](/guides/basic-features/css/css-modules) for usage instructions.
|
77
77
|
|
78
78
|
## CSS-in-JS
|
79
79
|
|
80
|
-
Modern.js supports the use of [styled-components](https://styled-components.com/). Please refer to ["Using CSS-in-JS"](/en/guides/basic-features/css
|
80
|
+
Modern.js supports the use of [styled-components](https://styled-components.com/). Please refer to ["Using CSS-in-JS"](/en/guides/basic-features/css/css-in-js) for usage instructions.
|
81
81
|
|
82
82
|
If you need to use other CSS-in-JS solutions, you can integrate them into your project on your own.
|
83
83
|
|
@@ -89,7 +89,7 @@ Additionally, Modern.js provides built-in support for [on-demand import](/config
|
|
89
89
|
|
90
90
|
## Component Development
|
91
91
|
|
92
|
-
Modern.js supports the use of [Storybook](https://storybook.js.org/) for developing UI components. This feature is optional. Please refer to ["Using Storybook"](/
|
92
|
+
Modern.js supports the use of [Storybook](https://storybook.js.org/) for developing UI components. This feature is optional. Please refer to ["Using Storybook"](/guides/basic-features/debug/using-storybook) to enable it.
|
93
93
|
|
94
94
|
## Node.js Framework
|
95
95
|
|
@@ -40,16 +40,6 @@ import PackageManager from '@site-docs-en/components/package-manager';
|
|
40
40
|
|
41
41
|
<PackageManager />
|
42
42
|
|
43
|
-
### buildTools
|
44
|
-
|
45
|
-
Question: Please select the bundler.
|
46
|
-
|
47
|
-
Options:
|
48
|
-
|
49
|
-
- webpack -- webpack
|
50
|
-
|
51
|
-
- Rspack -- rspack
|
52
|
-
|
53
43
|
## Npm Module
|
54
44
|
|
55
45
|
### packageName
|
@@ -35,7 +35,6 @@ npx @modern-js/create@latest web-app
|
|
35
35
|
? Please select the type of project you want to create: Web App
|
36
36
|
? Please select the programming language: TS
|
37
37
|
? Please select the package manager: pnpm
|
38
|
-
? Please select the bundler: webpack
|
39
38
|
```
|
40
39
|
|
41
40
|
### Create an Npm Module Project
|
@@ -294,7 +294,7 @@ A Utility Class named `custom-text-gray` is implemented in `src/routes/styles/ut
|
|
294
294
|
```
|
295
295
|
|
296
296
|
:::info note
|
297
|
-
Modern.js integrates with [PostCSS](/guides/basic-features/css) and supports modern CSS syntax features such as [custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).
|
297
|
+
Modern.js integrates with [PostCSS](/guides/basic-features/css/css) and supports modern CSS syntax features such as [custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).
|
298
298
|
|
299
299
|
:::
|
300
300
|
|
@@ -52,7 +52,7 @@ function useLoader(loaderFn: LoaderFn, options: Options): ReturnData;
|
|
52
52
|
- `initialData`:首次执行前的初始数据,对应返回值中的 `data` 字段。
|
53
53
|
- `skip`:当值为 `true` 时,函数不执行。
|
54
54
|
- `params`:当 `params` 序列化结果发生改变时,函数会重新执行。同时,`params` 也会作为函数的第二个参数被传入。
|
55
|
-
- `static`:当值为 `true` 时,`useLoader` 用于 [SSG](/guides/
|
55
|
+
- `static`:当值为 `true` 时,`useLoader` 用于 [SSG](/guides/basic-features/render/ssg) 编译阶段数据的获取。
|
56
56
|
|
57
57
|
### 返回值
|
58
58
|
|