Skip to content

Commit 53b3f48

Browse files
authored
refactor(rsc): organize plugin utils (#755)
1 parent 08986dd commit 53b3f48

File tree

2 files changed

+99
-81
lines changed

2 files changed

+99
-81
lines changed

packages/plugin-rsc/src/plugin.ts

Lines changed: 18 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import assert from 'node:assert'
2-
import { createHash } from 'node:crypto'
32
import fs from 'node:fs'
43
import { createRequire } from 'node:module'
54
import path from 'node:path'
@@ -38,7 +37,16 @@ import {
3837
prepareError,
3938
} from './vite-utils'
4039
import { cjsModuleRunnerPlugin } from './plugins/cjs'
41-
import { evalValue, parseIdQuery } from './plugins/utils'
40+
import {
41+
createVirtualPlugin,
42+
evalValue,
43+
getEntrySource,
44+
hashString,
45+
normalizeRelativePath,
46+
parseIdQuery,
47+
sortObject,
48+
withRollupError,
49+
} from './plugins/utils'
4250
import { createDebug } from '@hiogawa/utils'
4351
import { transformScanBuildStrip } from './plugins/scan'
4452
import { validateImportPlugin } from './plugins/validate-import'
@@ -86,6 +94,12 @@ class RscPluginManager {
8694
clientReferenceMetaMap: Record<string, ClientReferenceMeta> = {}
8795
serverReferenceMetaMap: Record<string, ServerRerferenceMeta> = {}
8896
serverResourcesMetaMap: Record<string, { key: string }> = {}
97+
98+
stabilize(): void {
99+
// sort for stable build
100+
this.clientReferenceMetaMap = sortObject(this.clientReferenceMetaMap)
101+
this.serverResourcesMetaMap = sortObject(this.serverResourcesMetaMap)
102+
}
89103
}
90104

91105
export type RscPluginOptions = {
@@ -225,13 +239,7 @@ export default function vitePluginRsc(
225239
builder.environments.rsc!.config.build.write = true
226240
builder.environments.client!.config.build.write = true
227241
await builder.build(builder.environments.rsc!)
228-
// sort for stable build
229-
manager.clientReferenceMetaMap = sortObject(
230-
manager.clientReferenceMetaMap,
231-
)
232-
manager.serverResourcesMetaMap = sortObject(
233-
manager.serverResourcesMetaMap,
234-
)
242+
manager.stabilize()
235243
await builder.build(builder.environments.client!)
236244
writeAssetsManifest(['rsc'])
237245
return
@@ -247,9 +255,7 @@ export default function vitePluginRsc(
247255
builder.environments.rsc!.config.build.write = true
248256
builder.environments.ssr!.config.build.write = true
249257
await builder.build(builder.environments.rsc!)
250-
// sort for stable build
251-
manager.clientReferenceMetaMap = sortObject(manager.clientReferenceMetaMap)
252-
manager.serverResourcesMetaMap = sortObject(manager.serverResourcesMetaMap)
258+
manager.stabilize()
253259
await builder.build(builder.environments.client!)
254260
await builder.build(builder.environments.ssr!)
255261
writeAssetsManifest(['ssr', 'rsc'])
@@ -967,30 +973,6 @@ function scanBuildStripPlugin({
967973
}
968974
}
969975

970-
function normalizeRelativePath(s: string) {
971-
s = normalizePath(s)
972-
return s[0] === '.' ? s : './' + s
973-
}
974-
975-
function getEntrySource(
976-
config: Pick<ResolvedConfig, 'build'>,
977-
name: string = 'index',
978-
) {
979-
const input = config.build.rollupOptions.input
980-
assert(
981-
typeof input === 'object' &&
982-
!Array.isArray(input) &&
983-
name in input &&
984-
typeof input[name] === 'string',
985-
`[vite-rsc:getEntrySource] expected 'build.rollupOptions.input' to be an object with a '${name}' property that is a string, but got ${JSON.stringify(input)}`,
986-
)
987-
return input[name]
988-
}
989-
990-
function hashString(v: string) {
991-
return createHash('sha256').update(v).digest().toString('hex').slice(0, 12)
992-
}
993-
994976
function vitePluginUseClient(
995977
useClientPluginOptions: Pick<
996978
RscPluginOptions,
@@ -1544,45 +1526,6 @@ function vitePluginUseServer(
15441526
]
15451527
}
15461528

1547-
// Rethrow transform error through `this.error` with `error.pos` which is injected by `@hiogawa/transforms`
1548-
function withRollupError<F extends (...args: any[]) => any>(
1549-
ctx: Rollup.TransformPluginContext,
1550-
f: F,
1551-
): F {
1552-
function processError(e: any): never {
1553-
if (e && typeof e === 'object' && typeof e.pos === 'number') {
1554-
return ctx.error(e, e.pos)
1555-
}
1556-
throw e
1557-
}
1558-
return function (this: any, ...args: any[]) {
1559-
try {
1560-
const result = f.apply(this, args)
1561-
if (result instanceof Promise) {
1562-
return result.catch((e: any) => processError(e))
1563-
}
1564-
return result
1565-
} catch (e: any) {
1566-
processError(e)
1567-
}
1568-
} as F
1569-
}
1570-
1571-
function createVirtualPlugin(name: string, load: Plugin['load']) {
1572-
name = 'virtual:' + name
1573-
return {
1574-
name: `rsc:virtual-${name}`,
1575-
resolveId(source, _importer, _options) {
1576-
return source === name ? '\0' + name : undefined
1577-
},
1578-
load(id, options) {
1579-
if (id === '\0' + name) {
1580-
return (load as Function).apply(this, [id, options])
1581-
}
1582-
},
1583-
} satisfies Plugin
1584-
}
1585-
15861529
class RuntimeAsset {
15871530
runtime: string
15881531
constructor(value: string) {
@@ -2183,9 +2126,3 @@ function __vite_rsc_wrap_css__(value, name) {
21832126
return { output: result.output }
21842127
}
21852128
}
2186-
2187-
function sortObject<T extends object>(o: T) {
2188-
return Object.fromEntries(
2189-
Object.entries(o).sort(([a], [b]) => a.localeCompare(b)),
2190-
) as T
2191-
}

packages/plugin-rsc/src/plugins/utils.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
import assert from 'node:assert'
2+
import { createHash } from 'node:crypto'
3+
import {
4+
normalizePath,
5+
type Plugin,
6+
type ResolvedConfig,
7+
type Rollup,
8+
} from 'vite'
9+
110
// https://github.com/vitejs/vite/blob/ea9aed7ebcb7f4be542bd2a384cbcb5a1e7b31bd/packages/vite/src/node/utils.ts#L1469-L1475
211
export function evalValue<T = any>(rawValue: string): T {
312
const fn = new Function(`
@@ -25,3 +34,75 @@ const postfixRE = /[?#].*$/
2534
export function cleanUrl(url: string): string {
2635
return url.replace(postfixRE, '')
2736
}
37+
38+
export function sortObject<T extends object>(o: T) {
39+
return Object.fromEntries(
40+
Object.entries(o).sort(([a], [b]) => a.localeCompare(b)),
41+
) as T
42+
}
43+
44+
// Rethrow transform error through `this.error` with `error.pos`
45+
export function withRollupError<F extends (...args: any[]) => any>(
46+
ctx: Rollup.TransformPluginContext,
47+
f: F,
48+
): F {
49+
function processError(e: any): never {
50+
if (e && typeof e === 'object' && typeof e.pos === 'number') {
51+
return ctx.error(e, e.pos)
52+
}
53+
throw e
54+
}
55+
return function (this: any, ...args: any[]) {
56+
try {
57+
const result = f.apply(this, args)
58+
if (result instanceof Promise) {
59+
return result.catch((e: any) => processError(e))
60+
}
61+
return result
62+
} catch (e: any) {
63+
processError(e)
64+
}
65+
} as F
66+
}
67+
68+
export function createVirtualPlugin(
69+
name: string,
70+
load: Plugin['load'],
71+
): Plugin {
72+
name = 'virtual:' + name
73+
return {
74+
name: `rsc:virtual-${name}`,
75+
resolveId(source, _importer, _options) {
76+
return source === name ? '\0' + name : undefined
77+
},
78+
load(id, options) {
79+
if (id === '\0' + name) {
80+
return (load as Function).apply(this, [id, options])
81+
}
82+
},
83+
}
84+
}
85+
86+
export function normalizeRelativePath(s: string): string {
87+
s = normalizePath(s)
88+
return s[0] === '.' ? s : './' + s
89+
}
90+
91+
export function getEntrySource(
92+
config: Pick<ResolvedConfig, 'build'>,
93+
name: string = 'index',
94+
): string {
95+
const input = config.build.rollupOptions.input
96+
assert(
97+
typeof input === 'object' &&
98+
!Array.isArray(input) &&
99+
name in input &&
100+
typeof input[name] === 'string',
101+
`[vite-rsc:getEntrySource] expected 'build.rollupOptions.input' to be an object with a '${name}' property that is a string, but got ${JSON.stringify(input)}`,
102+
)
103+
return input[name]
104+
}
105+
106+
export function hashString(v: string): string {
107+
return createHash('sha256').update(v).digest().toString('hex').slice(0, 12)
108+
}

0 commit comments

Comments
 (0)