Skip to content

Commit 709e3c0

Browse files
committed
feat: enhance QR code plugin with web environment support and middleware integration
1 parent 6411f84 commit 709e3c0

File tree

13 files changed

+236
-110
lines changed

13 files changed

+236
-110
lines changed

.changeset/crazy-jeans-hunt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@lynx-js/rspeedy": patch
3+
---
4+
5+
fix: error `lynx.getJSModule` is not a function on web platform

.changeset/tricky-lamps-battle.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"@lynx-js/qrcode-rsbuild-plugin": patch
3+
---
4+
5+
feat: support web platform preview
6+
7+
use rspeedy settings to enable Lynx Web Platform preview
8+
9+
```js
10+
// rspeedy configurations
11+
environments:{
12+
web:{},
13+
lynx:{}
14+
}
15+
```

examples/react/lynx.config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import { defineConfig } from '@lynx-js/rspeedy';
55
const enableBundleAnalysis = !!process.env['RSPEEDY_BUNDLE_ANALYSIS'];
66

77
export default defineConfig({
8+
source: {
9+
entry: {
10+
main: './src/index.tsx',
11+
main2: './src/index.tsx',
12+
},
13+
},
814
plugins: [
915
pluginReactLynx(),
1016
pluginQRCode({
@@ -17,4 +23,8 @@ export default defineConfig({
1723
performance: {
1824
profile: enableBundleAnalysis,
1925
},
26+
environments: {
27+
web: {},
28+
lynx: {},
29+
},
2030
});

packages/rspeedy/core/src/plugins/dev.plugin.ts

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import color from 'picocolors'
1212
import type { Dev } from '../config/dev/index.js'
1313
import type { Server } from '../config/server/index.js'
1414
import { debug } from '../debug.js'
15+
import { isLynx } from '../utils/is-lynx.js'
1516
import { ProvidePlugin } from '../webpack/ProvidePlugin.js'
1617

1718
export function pluginDev(
@@ -119,53 +120,55 @@ export function pluginDev(
119120
searchParams.set('token', environment.webSocketToken)
120121
}
121122

122-
// dprint-ignore
123-
chain
124-
.resolve
125-
.alias
126-
.set(
127-
'webpack/hot/log.js',
128-
require.resolve('@rspack/core/hot/log', {
129-
paths: [rsbuildPath],
130-
})
131-
)
132-
.set(
133-
'webpack/hot/emitter.js',
134-
require.resolve('@rspack/core/hot/emitter', {
135-
paths: [rsbuildPath],
136-
}),
137-
)
138-
.set(
139-
'@lynx-js/webpack-dev-transport/client',
140-
`${require.resolve('@lynx-js/webpack-dev-transport/client')}?${searchParams.toString()}`
141-
)
142-
.set(
143-
'@rspack/core/hot/dev-server',
144-
require.resolve('@rspack/core/hot/dev-server', {
145-
paths: [rsbuildPath],
146-
})
147-
)
123+
if (isLynx(environment)) {
124+
// dprint-ignore
125+
chain
126+
.resolve
127+
.alias
128+
.set(
129+
'webpack/hot/log.js',
130+
require.resolve('@rspack/core/hot/log', {
131+
paths: [rsbuildPath],
132+
})
133+
)
134+
.set(
135+
'webpack/hot/emitter.js',
136+
require.resolve('@rspack/core/hot/emitter', {
137+
paths: [rsbuildPath],
138+
}),
139+
)
140+
.set(
141+
'@lynx-js/webpack-dev-transport/client',
142+
`${require.resolve('@lynx-js/webpack-dev-transport/client')}?${searchParams.toString()}`
143+
)
144+
.set(
145+
'@rspack/core/hot/dev-server',
146+
require.resolve('@rspack/core/hot/dev-server', {
147+
paths: [rsbuildPath],
148+
})
149+
)
150+
.end()
148151
.end()
149-
.end()
150-
.plugin('lynx.hmr.provide')
151-
.use(ProvidePlugin, [
152-
{
153-
WebSocket: [
154-
options?.client?.websocketTransport ?? require.resolve('@lynx-js/websocket'),
155-
'default',
156-
],
157-
__webpack_dev_server_client__: [
158-
require.resolve(
159-
'./client/hmr/WebSocketClient.js',
160-
{
161-
paths: [rspeedyDir],
162-
},
163-
),
164-
'default'
165-
],
166-
}
167-
])
168-
.end()
152+
.plugin('lynx.hmr.provide')
153+
.use(ProvidePlugin, [
154+
{
155+
WebSocket: [
156+
options?.client?.websocketTransport ?? require.resolve('@lynx-js/websocket'),
157+
'default',
158+
],
159+
__webpack_dev_server_client__: [
160+
require.resolve(
161+
'./client/hmr/WebSocketClient.js',
162+
{
163+
paths: [rspeedyDir],
164+
},
165+
),
166+
'default'
167+
],
168+
}
169+
])
170+
.end()
171+
}
169172
})
170173
},
171174
}

packages/rspeedy/core/test/plugins/dev.plugin.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,27 @@ describe('Plugins - Dev', () => {
9999
)
100100
})
101101

102+
test('no HMR when environment.web', async () => {
103+
const rsbuild = await createStubRspeedy({
104+
environments: {
105+
web: {},
106+
},
107+
})
108+
109+
const config = await rsbuild.unwrapConfig()
110+
111+
expect(config.resolve?.alias).not.toHaveProperty(
112+
'@rspack/core/hot/dev-server',
113+
expect.stringContaining('hot/dev-server.js'.replaceAll('/', path.sep)),
114+
)
115+
expect(config.resolve?.alias).not.toHaveProperty(
116+
'@lynx-js/webpack-dev-transport/client',
117+
expect.stringContaining(
118+
'packages/webpack/webpack-dev-transport'.replaceAll('/', path.sep),
119+
),
120+
)
121+
})
122+
102123
test('not inject entry and provide variables in production', async () => {
103124
vi.stubEnv('NODE_ENV', 'production')
104125
const rsbuild = await createStubRspeedy({})

packages/rspeedy/plugin-qrcode/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
"build": "rslib build",
4848
"test": "pnpm -w run test --project rspeedy/qrcode"
4949
},
50+
"dependencies": {
51+
"@lynx-js/web-rsbuild-server-middleware": "workspace:*"
52+
},
5053
"devDependencies": {
5154
"@clack/prompts": "1.0.0-alpha.5",
5255
"@lynx-js/rspeedy": "workspace:*",

packages/rspeedy/plugin-qrcode/src/generateDevUrls.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function generateDevUrls(
1212
entry: string,
1313
schemaFn: CustomizedSchemaFn,
1414
port: number,
15-
): Record<string, string> {
15+
): { lynx: Record<string, string>, web: string } {
1616
const { dev: { assetPrefix } } = api.getNormalizedConfig()
1717
const { config } = api.useExposed<ExposedAPI>(
1818
Symbol.for('rspeedy.api'),
@@ -35,15 +35,35 @@ export default function generateDevUrls(
3535
name = filename
3636
}
3737

38+
// <port> is supported in `dev.assetPrefix`, we should replace it with the real port
39+
let base: string
40+
try {
41+
base = new URL(
42+
'',
43+
assetPrefix.replaceAll('<port>', String(port)),
44+
).toString()
45+
} catch {
46+
base = `http://localhost:${port}/`
47+
}
3848
const customSchema = schemaFn(
3949
new URL(
4050
name.replace('[name]', entry).replace('[platform]', 'lynx'),
41-
// <port> is supported in `dev.assetPrefix`, we should replace it with the real port
42-
assetPrefix.replaceAll('<port>', String(port)),
51+
base,
4352
).toString(),
4453
)
4554

46-
return typeof customSchema === 'string'
55+
const outputPathname = new URL(
56+
name.replace('[name]', entry).replace('[platform]', 'web'),
57+
base,
58+
).pathname
59+
const web = new URL(
60+
`/web?casename=${outputPathname}`,
61+
base,
62+
).toString()
63+
64+
const lynx = typeof customSchema === 'string'
4765
? { default: customSchema }
4866
: customSchema
67+
68+
return { lynx, web }
4969
}

packages/rspeedy/plugin-qrcode/src/index.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
import type { EnvironmentContext, RsbuildPlugin } from '@rsbuild/core'
1212

13+
import { createWebVirtualFilesMiddleware } from '@lynx-js/web-rsbuild-server-middleware'
14+
1315
import { registerConsoleShortcuts } from './shortcuts.js'
1416

1517
/**
@@ -101,8 +103,13 @@ export function pluginQRCode(
101103
name: 'lynx:rsbuild:qrcode',
102104
pre: ['lynx:rsbuild:api'],
103105
setup(api) {
106+
api.onBeforeStartDevServer(({ environments, server }) => {
107+
if (environments['web']) {
108+
server.middlewares.use(createWebVirtualFilesMiddleware('/web'))
109+
}
110+
})
104111
api.onAfterStartProdServer(async ({ environments, port }) => {
105-
await main(environments['lynx'], port)
112+
await main(environments, port)
106113
})
107114

108115
let printedQRCode = false
@@ -122,7 +129,7 @@ export function pluginQRCode(
122129

123130
printedQRCode = true
124131

125-
await main(environments['lynx'], api.context.devServer.port)
132+
await main(environments, api.context.devServer.port)
126133
})
127134

128135
api.modifyRsbuildConfig((config) => {
@@ -138,23 +145,29 @@ export function pluginQRCode(
138145
})
139146

140147
async function main(
141-
environmentContext: EnvironmentContext | undefined,
148+
environments: Record<string, EnvironmentContext>,
142149
port: number,
143150
) {
144-
if (!environmentContext) {
145-
// Not lynx environment, skip print QRCode
146-
return
147-
}
148-
149-
const entries = Object.keys(environmentContext.entry)
150-
151-
if (entries.length === 0) {
151+
const lynxEntries = Object.keys(environments['lynx']?.entry ?? {})
152+
const webEntries = Object.keys(environments['web']?.entry ?? {})
153+
const allEntries = [
154+
...new Set([
155+
...lynxEntries,
156+
...webEntries,
157+
]),
158+
]
159+
if (allEntries.length === 0) {
160+
// Not lynx or web environment, skip print
152161
return
153162
}
154163

155164
const unregister = await registerConsoleShortcuts(
156165
{
157-
entries,
166+
entries: {
167+
all: allEntries,
168+
lynx: lynxEntries,
169+
web: webEntries,
170+
},
158171
api,
159172
port,
160173
schema,

0 commit comments

Comments
 (0)