-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(server): support dev.watchFiles config (#2145)
Co-authored-by: gaoyuan <[email protected]> Co-authored-by: neverland <[email protected]>
- Loading branch information
1 parent
047eac7
commit c4973ea
Showing
14 changed files
with
316 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import path from 'node:path'; | ||
import { dev, gotoPage, rspackOnlyTest } from '@e2e/helper'; | ||
import { fse } from '@rsbuild/shared'; | ||
|
||
rspackOnlyTest('should work with string and path to file', async ({ page }) => { | ||
const file = path.join(__dirname, '/assets/example.txt'); | ||
const rsbuild = await dev({ | ||
cwd: __dirname, | ||
rsbuildConfig: { | ||
dev: { | ||
watchFiles: { | ||
paths: file, | ||
}, | ||
}, | ||
}, | ||
}); | ||
await gotoPage(page, rsbuild); | ||
|
||
await fse.writeFile(file, 'test'); | ||
// check the page is reloaded | ||
await new Promise((resolve) => { | ||
page.waitForURL(page.url()).then(resolve); | ||
}); | ||
|
||
// reset file | ||
fse.truncateSync(file); | ||
await rsbuild.close(); | ||
}); | ||
|
||
rspackOnlyTest( | ||
'should work with string and path to directory', | ||
async ({ page }) => { | ||
const file = path.join(__dirname, '/assets/example.txt'); | ||
const rsbuild = await dev({ | ||
cwd: __dirname, | ||
rsbuildConfig: { | ||
dev: { | ||
watchFiles: { | ||
paths: path.join(__dirname, '/assets'), | ||
}, | ||
}, | ||
}, | ||
}); | ||
await gotoPage(page, rsbuild); | ||
|
||
await fse.writeFile(file, 'test'); | ||
|
||
await new Promise((resolve) => { | ||
page.waitForURL(page.url()).then(resolve); | ||
}); | ||
|
||
// reset file | ||
fse.truncateSync(file); | ||
await rsbuild.close(); | ||
}, | ||
); | ||
|
||
rspackOnlyTest('should work with string array directory', async ({ page }) => { | ||
const file = path.join(__dirname, '/assets/example.txt'); | ||
const other = path.join(__dirname, '/other/other.txt'); | ||
const rsbuild = await dev({ | ||
cwd: __dirname, | ||
rsbuildConfig: { | ||
dev: { | ||
watchFiles: { | ||
paths: [ | ||
path.join(__dirname, '/assets'), | ||
path.join(__dirname, '/other'), | ||
], | ||
}, | ||
}, | ||
}, | ||
}); | ||
await gotoPage(page, rsbuild); | ||
|
||
await fse.writeFile(file, 'test'); | ||
// check the page is reloaded | ||
await new Promise((resolve) => { | ||
page.waitForURL(page.url()).then(resolve); | ||
}); | ||
// reset file | ||
fse.truncateSync(file); | ||
|
||
await fse.writeFile(other, 'test'); | ||
// check the page is reloaded | ||
await new Promise((resolve) => { | ||
page.waitForURL(page.url()).then(resolve); | ||
}); | ||
// reset file | ||
fse.truncateSync(other); | ||
|
||
await rsbuild.close(); | ||
}); | ||
|
||
rspackOnlyTest('should work with string and glob', async ({ page }) => { | ||
const file = path.join(__dirname, '/assets/example.txt'); | ||
const watchDir = path.join(__dirname, '/assets'); | ||
const rsbuild = await dev({ | ||
cwd: __dirname, | ||
rsbuildConfig: { | ||
dev: { | ||
watchFiles: { | ||
paths: `${watchDir}/**/*`, | ||
}, | ||
}, | ||
}, | ||
}); | ||
await gotoPage(page, rsbuild); | ||
|
||
await fse.writeFile(file, 'test'); | ||
// check the page is reloaded | ||
await new Promise((resolve) => { | ||
page.waitForURL(page.url()).then(resolve); | ||
}); | ||
|
||
// reset file | ||
fse.truncateSync(file); | ||
await rsbuild.close(); | ||
}); | ||
|
||
rspackOnlyTest('should work with options', async ({ page }) => { | ||
const file = path.join(__dirname, '/assets/example.txt'); | ||
const rsbuild = await dev({ | ||
cwd: __dirname, | ||
rsbuildConfig: { | ||
dev: { | ||
watchFiles: { | ||
paths: file, | ||
options: { | ||
usePolling: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
await gotoPage(page, rsbuild); | ||
|
||
await fse.writeFile(file, 'test'); | ||
// check the page is reloaded | ||
await new Promise((resolve) => { | ||
page.waitForURL(page.url()).then(resolve); | ||
}); | ||
|
||
// reset file | ||
fse.truncateSync(file); | ||
await rsbuild.close(); | ||
}); |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { defineConfig } from '@rsbuild/core'; | ||
import { pluginReact } from '@rsbuild/plugin-react'; | ||
|
||
export default defineConfig({ | ||
plugins: [pluginReact()], | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
const App = () => { | ||
return ( | ||
<div className="content"> | ||
<h1>Rsbuild with React</h1> | ||
<p>Start building amazing things with Rsbuild.</p> | ||
</div> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/client'; | ||
import App from './App'; | ||
|
||
const root = ReactDOM.createRoot(document.getElementById('root')!); | ||
root.render( | ||
<React.StrictMode> | ||
<App /> | ||
</React.StrictMode>, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { DevConfig, FSWatcher } from '@rsbuild/shared'; | ||
import type { RsbuildDevMiddlewareOptions } from './getDevMiddlewares'; | ||
|
||
export async function setupWatchFiles( | ||
dev: DevConfig, | ||
compileMiddlewareAPI: RsbuildDevMiddlewareOptions['compileMiddlewareAPI'], | ||
): Promise<FSWatcher | undefined> { | ||
const { watchFiles, hmr, liveReload } = dev; | ||
if (!watchFiles || (!hmr && !liveReload)) { | ||
return; | ||
} | ||
|
||
const chokidar = await import('@rsbuild/shared/chokidar'); | ||
|
||
const { paths, options } = watchFiles; | ||
const watcher = chokidar.watch(paths, options); | ||
|
||
watcher.on('change', () => { | ||
if (compileMiddlewareAPI) { | ||
compileMiddlewareAPI.sockWrite('static-changed'); | ||
} | ||
}); | ||
|
||
return watcher; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# dev.watchFiles | ||
|
||
- **Type:** | ||
|
||
```ts | ||
type WatchFiles = { | ||
paths: string | string[]; | ||
// watch options for chokidar | ||
options?: WatchOptions; | ||
}; | ||
``` | ||
|
||
- **Default:** `undefined` | ||
|
||
Watch files and directories for changes. When a file changes, the page will be reloaded. | ||
|
||
If both `dev.hmr` and `dev.liveReload` are set to false, `watchFiles` will be ignored. | ||
|
||
### Example | ||
|
||
You can configure a list of globs/directories/files to watch for file changes. | ||
|
||
```js | ||
export default { | ||
dev: { | ||
watchFiles: { | ||
// watch a single file | ||
paths: 'public/demo.txt', | ||
// use a glob pattern | ||
paths: 'src/**/*.txt', | ||
// watch multiple file paths | ||
paths: ['src/**/*.txt', 'public/**/*'], | ||
}, | ||
}, | ||
}; | ||
``` | ||
|
||
You can also specify [chokidar](https://github.com/paulmillr/chokidar#api) watcher options by passing an object with `paths` and `options` properties. | ||
|
||
```js | ||
export default { | ||
dev: { | ||
watchFiles: { | ||
paths: 'src/**/*.txt', | ||
options: { | ||
usePolling: false, | ||
}, | ||
}, | ||
}, | ||
}; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# dev.watchFiles | ||
|
||
- **类型:* | ||
|
||
```ts | ||
type WatchFiles = { | ||
paths: string | string[]; | ||
// chokidar 选项 | ||
options?: WatchOptions; | ||
}; | ||
``` | ||
|
||
- **默认值:** `undefined` | ||
|
||
监视指定文件和目录的变化。当文件发生变化时,页面将重新加载。 | ||
|
||
如果 `dev.hmr` 和 `dev.liveReload` 都设置为 false,则 `watchFiles` 将被忽略。 | ||
|
||
### 示例 | ||
|
||
你可以配置一个 glob 模式 / 目录 / 文件的列表,用于监视文件变化。 | ||
|
||
```js | ||
export default { | ||
dev: { | ||
watchFiles: { | ||
// 监视单个文件 | ||
paths: 'public/demo.txt', | ||
// 使用 glob 模式 | ||
paths: 'src/**/*.txt', | ||
// 监视多个文件路径 | ||
paths: ['src/**/*.txt', 'public/**/*'], | ||
}, | ||
}, | ||
}; | ||
``` | ||
|
||
你也可以通过传入一个包含 `paths` 和 `options` 属性的对象,来指定 [chokidar](https://github.com/paulmillr/chokidar#api) 选项。 | ||
|
||
```js | ||
export default { | ||
dev: { | ||
watchFiles: { | ||
paths: 'src/**/*.txt', | ||
options: { | ||
usePolling: false, | ||
}, | ||
}, | ||
}, | ||
}; | ||
``` |