Skip to content

Commit

Permalink
wip: save
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jan 18, 2021
1 parent 54f7889 commit 10c1e15
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 22 deletions.
26 changes: 19 additions & 7 deletions packages/vite/src/node/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,14 @@ import { handleHMRUpdate, HmrOptions } from './hmr'
import { openBrowser } from './openBrowser'
import launchEditorMiddleware from 'launch-editor-middleware'
import { TransformResult } from 'rollup'
import { transformRequest } from './transformRequest'
import { TransformOptions, transformRequest } from './transformRequest'
import {
transformWithEsbuild,
EsbuildTransformResult
} from '../plugins/esbuild'
import { TransformOptions as EsbuildTransformOptions } from 'esbuild'
import { DepOptimizationMetadata, optimizeDeps } from '../optimizer'
import { ssrLoadModule } from './ssrModuleLoader'

export interface ServerOptions {
host?: string
Expand Down Expand Up @@ -167,7 +168,10 @@ export interface ViteDevServer {
* Programmatically resolve, load and transform a URL and get the result
* without going through the http request pipeline.
*/
transformRequest(url: string): Promise<TransformResult | null>
transformRequest(
url: string,
options?: TransformOptions
): Promise<TransformResult | null>
/**
* Util for transforming a file with esbuild.
* Can be useful for certain plugins.
Expand All @@ -178,6 +182,10 @@ export interface ViteDevServer {
options?: EsbuildTransformOptions,
inMap?: object
): Promise<EsbuildTransformResult>
/**
* Load a given URL as an instantiated module for SSR.
*/
ssrLoadModule(url: string): Promise<Record<string, any>>
/**
* Start the server.
*/
Expand All @@ -198,9 +206,10 @@ export async function createServer(
const config = await resolveConfig(inlineConfig, 'serve', 'development')
const root = config.root
const serverConfig = config.server || {}
const middlewareMode = !!serverConfig.middlewareMode

const app = connect() as Connect.Server
const httpServer = serverConfig.middlewareMode
const httpServer = middlewareMode
? null
: await resolveHttpServer(serverConfig, app)
const ws = createWebSocketServer(httpServer, config)
Expand Down Expand Up @@ -232,8 +241,11 @@ export async function createServer(
moduleGraph,
optimizeDepsMetadata: null,
transformWithEsbuild,
transformRequest(url) {
return transformRequest(url, server)
transformRequest(url, options) {
return transformRequest(url, server, options)
},
ssrLoadModule(url) {
return ssrLoadModule(url, server)
},
listen(port?: number) {
return startServer(server, port)
Expand Down Expand Up @@ -344,15 +356,15 @@ export async function createServer(
app.use(indexHtmlMiddleware(server, plugins))

// handle 404s
if (!serverConfig.middlewareMode) {
if (!middlewareMode) {
app.use((_, res) => {
res.statusCode = 404
res.end()
})
}

// error handler
app.use(errorMiddleware(server, serverConfig.middlewareMode))
app.use(errorMiddleware(server, middlewareMode))

if (httpServer) {
// overwrite listen to run optimizer before server start
Expand Down
12 changes: 8 additions & 4 deletions packages/vite/src/node/server/moduleGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ export class ModuleNode {
}
}

function invalidateSSRModule(mod: ModuleNode) {
mod.ssrModule = null
mod.importers.forEach(invalidateSSRModule)
}
export class ModuleGraph {
private urlToModuleMap = new Map<string, ModuleNode>()
private idToModuleMap = new Map<string, ModuleNode>()
urlToModuleMap = new Map<string, ModuleNode>()
idToModuleMap = new Map<string, ModuleNode>()
// a single file may corresponds to multiple modules with different queries
private fileToModulesMap = new Map<string, Set<ModuleNode>>()
fileToModulesMap = new Map<string, Set<ModuleNode>>()
container: PluginContainer

constructor(container: PluginContainer) {
Expand All @@ -66,7 +70,7 @@ export class ModuleGraph {
mods.forEach((mod) => {
mod.transformResult = null
mod.ssrTransformResult = null
mod.ssrModule = null
invalidateSSRModule(mod)
})
}
}
Expand Down
34 changes: 34 additions & 0 deletions packages/vite/src/node/server/ssrModuleLoader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ViteDevServer } from '..'
import { transformRequest } from './transformRequest'

export async function ssrLoadModule(
url: string,
server: ViteDevServer
): Promise<Record<string, any>> {
const { moduleGraph } = server
const mod = await moduleGraph.ensureEntryFromUrl(url)
if (mod.ssrModule) {
return mod.ssrModule
}

const result = await transformRequest(url, server, { ssr: true })
if (!result) {
// TODO more info? is this even necessary?
throw new Error(`failed to load module for ssr: $${url}`)
}

await Promise.all(result.deps!.map((dep) => ssrLoadModule(dep, server)))

const __import__ = (dep: string) => {
return moduleGraph.urlToModuleMap.get(dep)?.ssrModule
}
const __exports__ = {}

new Function(`__import__`, `__exports__`, result.code)(
__import__,
__exports__
)

mod.ssrModule = __exports__
return __exports__
}
45 changes: 39 additions & 6 deletions packages/vite/src/node/server/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ import MagicString from 'magic-string'
import { SourceMap } from 'rollup'
import { TransformResult } from './transformRequest'
import { parser } from './pluginContainer'
import { Node } from 'estree'
import { Node as _Node } from 'estree'

export async function transformForSSR(
type Node = _Node & {
start: number
end: number
}

export async function ssrTransform(
code: string,
map: SourceMap | null
inMap: SourceMap | null
): Promise<TransformResult | null> {
const s = new MagicString(code)

Expand All @@ -16,15 +21,41 @@ export async function transformForSSR(
locations: true
}) as any

let uid = 0
const deps = new Set<string>()

for (const node of ast.body as Node[]) {
// import foo from 'foo' --> foo -> __import_foo__.default
// import { baz } from 'foo' --> baz -> __import_foo__.baz
// import * as ok from 'foo' --> ok -> __import_foo__
if (node.type === 'ImportDeclaration') {
if (node.specifiers.length) {
const importId = `__vite_import_${uid++}__`
deps.add(node.source.value as string)
s.appendLeft(
node.start,
`const ${importId} = __import__(${JSON.stringify(node.source.value)})\n`
)
for (const spec of node.specifiers) {
if (spec.type === 'ImportSpecifier') {
s.appendLeft(
node.start,
`const ${spec.local.name} = ${importId}.${spec.imported.name}\n`
)
}
}
s.remove(node.start, node.end)
}
if (node.type === 'ExportNamedDeclaration') {
if (node.declaration) {
if (node.declaration.type === 'FunctionDeclaration') {
s.overwrite(
node.start,
node.start + 7,
`__exports__.${node.declaration.id!.name} = `
)
}
// TODO Class / Var
}
}
if (node.type === 'ExportDefaultDeclaration') {
}
Expand All @@ -33,7 +64,9 @@ export async function transformForSSR(
}

return {
code,
map
code: s.toString(),
// TODO handle inMap
map: s.generateMap({ hires: true }),
deps: [...deps]
}
}
8 changes: 3 additions & 5 deletions packages/vite/src/node/server/transformRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
timeFrom
} from '../utils'
import { checkPublicFile } from '../plugins/asset'
import { transformForSSR } from './ssrTransform'
import { ssrTransform } from './ssrTransform'

const debugLoad = createDebugger('vite:load')
const debugTransform = createDebugger('vite:transform')
Expand All @@ -24,6 +24,7 @@ export interface TransformResult {
code: string
map: SourceMap | null
etag?: string
deps?: string[]
}

export interface TransformOptions {
Expand Down Expand Up @@ -139,10 +140,7 @@ export async function transformRequest(
}

if (ssr) {
return (mod.ssrTransformResult = await transformForSSR(
code,
map as SourceMap
))
return (mod.ssrTransformResult = await ssrTransform(code, map as SourceMap))
} else {
return (mod.transformResult = {
code,
Expand Down

0 comments on commit 10c1e15

Please sign in to comment.