@@ -3,7 +3,7 @@ import { createHash } from 'node:crypto'
33import fs from 'node:fs'
44import { createRequire } from 'node:module'
55import path from 'node:path'
6- import { fileURLToPath , pathToFileURL } from 'node:url'
6+ import { pathToFileURL } from 'node:url'
77import { createRequestListener } from '@remix-run/node-fetch-server'
88import * as esModuleLexer from 'es-module-lexer'
99import MagicString from 'magic-string'
@@ -41,6 +41,8 @@ import { cjsModuleRunnerPlugin } from './plugins/cjs'
4141import { evalValue , parseIdQuery } from './plugins/utils'
4242import { createDebug } from '@hiogawa/utils'
4343import { transformScanBuildStrip } from './plugins/scan'
44+ import { validateImportPlugin } from './plugins/validate-import'
45+ import { vitePluginFindSourceMapURL } from './plugins/find-source-map-url'
4446
4547// state for build orchestration
4648let serverReferences : Record < string , string > = { }
@@ -1657,102 +1659,6 @@ function collectAssetDepsInner(
16571659 }
16581660}
16591661
1660- //
1661- // support findSourceMapURL
1662- // https://github.com/facebook/react/pull/29708
1663- // https://github.com/facebook/react/pull/30741
1664- //
1665-
1666- export function vitePluginFindSourceMapURL ( ) : Plugin [ ] {
1667- return [
1668- {
1669- name : 'rsc:findSourceMapURL' ,
1670- apply : 'serve' ,
1671- configureServer ( server ) {
1672- server . middlewares . use ( async ( req , res , next ) => {
1673- const url = new URL ( req . url ! , `http://localhost` )
1674- if ( url . pathname === '/__vite_rsc_findSourceMapURL' ) {
1675- let filename = url . searchParams . get ( 'filename' ) !
1676- let environmentName = url . searchParams . get ( 'environmentName' ) !
1677- try {
1678- const map = await findSourceMapURL (
1679- server ,
1680- filename ,
1681- environmentName ,
1682- )
1683- res . setHeader ( 'content-type' , 'application/json' )
1684- if ( ! map ) res . statusCode = 404
1685- res . end ( JSON . stringify ( map ?? { } ) )
1686- } catch ( e ) {
1687- next ( e )
1688- }
1689- return
1690- }
1691- next ( )
1692- } )
1693- } ,
1694- } ,
1695- ]
1696- }
1697-
1698- export async function findSourceMapURL (
1699- server : ViteDevServer ,
1700- filename : string ,
1701- environmentName : string ,
1702- ) : Promise < object | undefined > {
1703- // this is likely server external (i.e. outside of Vite processing)
1704- if ( filename . startsWith ( 'file://' ) ) {
1705- filename = fileURLToPath ( filename )
1706- if ( fs . existsSync ( filename ) ) {
1707- // line-by-line identity source map
1708- const content = fs . readFileSync ( filename , 'utf-8' )
1709- return {
1710- version : 3 ,
1711- sources : [ filename ] ,
1712- sourcesContent : [ content ] ,
1713- mappings : 'AAAA' + ';AACA' . repeat ( content . split ( '\n' ) . length ) ,
1714- }
1715- }
1716- return
1717- }
1718-
1719- // server component stack, replace log, `registerServerReference`, etc...
1720- let mod : EnvironmentModuleNode | undefined
1721- let map :
1722- | NonNullable < EnvironmentModuleNode [ 'transformResult' ] > [ 'map' ]
1723- | undefined
1724- if ( environmentName === 'Server' ) {
1725- mod = server . environments . rsc ! . moduleGraph . getModuleById ( filename )
1726- // React extracts stacktrace via resetting `prepareStackTrace` on the server
1727- // and let browser devtools handle the mapping.
1728- // https://github.com/facebook/react/blob/4a36d3eab7d9bbbfae62699989aa95e5a0297c16/packages/react-server/src/ReactFlightStackConfigV8.js#L15-L20
1729- // This means it has additional +2 line offset due to Vite's module runner
1730- // function wrapper. We need to correct it just like Vite module runner.
1731- // https://github.com/vitejs/vite/blob/d94e7b25564abb81ab7b921d4cd44d0f0d22fec4/packages/vite/src/shared/utils.ts#L58-L69
1732- // https://github.com/vitejs/vite/blob/d94e7b25564abb81ab7b921d4cd44d0f0d22fec4/packages/vite/src/node/ssr/fetchModule.ts#L142-L146
1733- map = mod ?. transformResult ?. map
1734- if ( map && map . mappings ) {
1735- map = { ...map , mappings : ( ';;' + map . mappings ) as any }
1736- }
1737- }
1738-
1739- const base = server . config . base . slice ( 0 , - 1 )
1740-
1741- // `createServerReference(... findSourceMapURL ...)` called on browser
1742- if ( environmentName === 'Client' ) {
1743- try {
1744- const url = new URL ( filename ) . pathname . slice ( base . length )
1745- mod = server . environments . client . moduleGraph . urlToModuleMap . get ( url )
1746- map = mod ?. transformResult ?. map
1747- } catch ( e ) { }
1748- }
1749-
1750- if ( mod && map ) {
1751- // fix sources to match Vite's module url on browser
1752- return { ...map , sources : [ base + mod . url ] }
1753- }
1754- }
1755-
17561662//
17571663// css support
17581664//
@@ -2211,49 +2117,6 @@ export function __fix_cloudflare(): Plugin {
22112117 }
22122118}
22132119
2214- // https://github.com/vercel/next.js/blob/90f564d376153fe0b5808eab7b83665ee5e08aaf/packages/next/src/build/webpack-config.ts#L1249-L1280
2215- // https://github.com/pcattori/vite-env-only/blob/68a0cc8546b9a37c181c0b0a025eb9b62dbedd09/src/deny-imports.ts
2216- // https://github.com/sveltejs/kit/blob/84298477a014ec471839adf7a4448d91bc7949e4/packages/kit/src/exports/vite/index.js#L513
2217- function validateImportPlugin ( ) : Plugin {
2218- return {
2219- name : 'rsc:validate-imports' ,
2220- resolveId : {
2221- order : 'pre' ,
2222- async handler ( source , importer , options ) {
2223- // optimizer is not aware of server/client boudnary so skip
2224- if ( 'scan' in options && options . scan ) {
2225- return
2226- }
2227-
2228- // Validate client-only imports in server environments
2229- if ( source === 'client-only' ) {
2230- if ( this . environment . name === 'rsc' ) {
2231- throw new Error (
2232- `'client-only' cannot be imported in server build (importer: '${ importer ?? 'unknown' } ', environment: ${ this . environment . name } )` ,
2233- )
2234- }
2235- return { id : `\0virtual:vite-rsc/empty` , moduleSideEffects : false }
2236- }
2237- if ( source === 'server-only' ) {
2238- if ( this . environment . name !== 'rsc' ) {
2239- throw new Error (
2240- `'server-only' cannot be imported in client build (importer: '${ importer ?? 'unknown' } ', environment: ${ this . environment . name } )` ,
2241- )
2242- }
2243- return { id : `\0virtual:vite-rsc/empty` , moduleSideEffects : false }
2244- }
2245-
2246- return
2247- } ,
2248- } ,
2249- load ( id ) {
2250- if ( id . startsWith ( '\0virtual:vite-rsc/empty' ) ) {
2251- return `export {}`
2252- }
2253- } ,
2254- }
2255- }
2256-
22572120function sortObject < T extends object > ( o : T ) {
22582121 return Object . fromEntries (
22592122 Object . entries ( o ) . sort ( ( [ a ] , [ b ] ) => a . localeCompare ( b ) ) ,
0 commit comments