Skip to content
Merged
Show file tree
Hide file tree
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
19 changes: 19 additions & 0 deletions .changeset/thirty-buses-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"@lynx-js/rspeedy": patch
---

Support configure the base path of the server.

By default, the base path of the server is `/`, and users can access lynx bundle through `http://<host>:<port>/main.lynx.bundle`
If you want to access lynx bundle through `http://<host>:<port>/foo/main.lynx.bundle`, you can change `server.base` to `/foo`

example:

```js
import { defineConfig } from '@lynx-js/rspeedy';
export default defineConfig({
server: {
base: '/dist',
},
});
```
1 change: 1 addition & 0 deletions packages/rspeedy/core/etc/rspeedy.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ export type RspeedyInstance = RsbuildInstance & {

// @public
export interface Server {
base?: string | undefined;
headers?: Record<string, string | string[]> | undefined;
host?: string | undefined;
port?: number | undefined;
Expand Down
5 changes: 5 additions & 0 deletions packages/rspeedy/core/src/config/rsbuild/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,18 @@ export function toRsbuildConfig(
tsconfigPath: config.source?.tsconfigPath,
},
server: {
base: config.server?.base,

headers: config.server?.headers,

host: config.server?.host,

port: config.server?.port,
},
plugins: config.plugins,
performance: {
chunkSplit: config.performance?.chunkSplit,

removeConsole: toRsbuildRemoveConsole(config) as
| ConsoleType[]
| false
Expand Down
23 changes: 23 additions & 0 deletions packages/rspeedy/core/src/config/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@
* @public
*/
export interface Server {
/**
* Configure the base path of the server.
*
* @remarks
* By default, the base path of the server is `/`, and users can access lynx bundle through `http://<host>:<port>/main.lynx.bundle`
*
* If you want to access lynx bundle through `http://<host>:<port>/foo/main.lynx.bundle`, you can change `server.base` to `/foo`
*
* you can refer to {@link https://rsbuild.dev/config/server/base | server.base } for more information.
*
* @example
*
* ```js
* import { defineConfig } from '@lynx-js/rspeedy'
* export default defineConfig({
* server: {
* base: '/dist'
* },
* })
* ```
*/
base?: string | undefined

/**
* Adds headers to all responses.
*
Expand Down
7 changes: 7 additions & 0 deletions packages/rspeedy/core/src/plugins/dev.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ export function pluginDev(
}
}

if (server?.base) {
if ((assetPrefix as string).endsWith('/')) {
assetPrefix = (assetPrefix as string).slice(0, -1)
}
assetPrefix = `${assetPrefix}${server.base}/`
}

debug(`dev.assetPrefix is normalized to ${assetPrefix}`)

api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => {
Expand Down
5 changes: 5 additions & 0 deletions packages/rspeedy/core/test/config/server.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import { assertType, describe, test } from 'vitest'
import type { Server } from '../../src/index.js'

describe('Config - Server', () => {
test('server.base', () => {
assertType<Server>({})
assertType<Server>({ base: '/foo' })
})

test('server.headers', () => {
assertType<Server>({})
assertType<Server>({
Expand Down
22 changes: 22 additions & 0 deletions packages/rspeedy/core/test/config/validate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,8 @@ describe('Config Validation', () => {
test('valid type', () => {
const cases: Server[] = [
{},
{ base: '/foo' },
{ base: '/bar' },
{ headers: {} },
{ headers: { foo: 'bar' } },
{ headers: { foo: [] } },
Expand All @@ -1568,6 +1570,26 @@ describe('Config Validation', () => {
})

test('invalid type', () => {
expect(() => validate({ server: { base: 123 } }))
.toThrowErrorMatchingInlineSnapshot(`
[Error: Invalid configuration.

Invalid config on \`$input.server.base\`.
- Expect to be (string | undefined)
- Got: number
]
`)

expect(() => validate({ server: { base: null } }))
.toThrowErrorMatchingInlineSnapshot(`
[Error: Invalid configuration.

Invalid config on \`$input.server.base\`.
- Expect to be (string | undefined)
- Got: null
]
`)

expect(() => validate({ server: { headers: null } }))
.toThrowErrorMatchingInlineSnapshot(`
[Error: Invalid configuration.
Expand Down
41 changes: 41 additions & 0 deletions packages/rspeedy/core/test/plugins/dev.plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,4 +375,45 @@ describe('Plugins - Dev', () => {
],
})
})

test('server.base without /', async () => {
try {
const rsbuild = await createStubRspeedy({
server: {
base: 'dist',
},
})

await rsbuild.unwrapConfig()
} catch (error) {
expect(error).toMatchInlineSnapshot(
`[Error: [rsbuild:config] The "server.base" option should start with a slash, for example: "/base"]`,
)
}
})

test('dev.assetPrefix with server.base', async () => {
const rsbuild = await createStubRspeedy({
dev: {
assetPrefix: 'http://example.com/',
},
server: {
base: '/dist',
},
})

const config = await rsbuild.unwrapConfig()

expect(typeof config.output?.publicPath).toBe('string')

expect(config.output?.publicPath).toContain('http://example.com/')
expect(config.output?.publicPath).toContain('/dist/')

const { port, hostname, pathname } = new URL(config.output!.publicPath!)

expect(port).toBe('')
expect(isIP(hostname)).toBe(0)
expect(hostname).toBe('example.com')
expect(pathname).toBe('/dist/')
})
})
Loading