Skip to content

Commit

Permalink
feat: ssr manifest for preload inference
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Jan 18, 2021
1 parent c6115e9 commit 107e79e
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 7 deletions.
17 changes: 16 additions & 1 deletion packages/plugin-vue/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export async function transformMain(
`_sfc_main.__scopeId = ${JSON.stringify(`data-v-${descriptor.id}`)}`
)
}
if (devServer) {
if (devServer && !isProduction) {
// expose filename during serve for devtools to pickup
output.push(`_sfc_main.__file = ${JSON.stringify(filename)}`)
}
Expand All @@ -122,6 +122,21 @@ export async function transformMain(
)
}

// SSR module registration by wrapping user setup
if (ssr) {
output.push(
`import { useSSRContext } from 'vue'`,
`const _sfc_setup = _sfc_main.setup`,
`_sfc_main.setup = (props, ctx) => {`,
` const ssrContext = useSSRContext()`,
` ;(ssrContext.modules || (ssrContext.modules = new Set())).add(${JSON.stringify(
filename
)})`,
` return _sfc_setup ? _sfc_setup(props, ctx) : undefined`,
`}`
)
}

// if the template is inlined into the main module (indicated by the presence
// of templateMap, we need to concatenate the two source maps.
let resolvedMap = map
Expand Down
20 changes: 16 additions & 4 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { CleanCSS } from 'types/clean-css'
import { dataURIPlugin } from './plugins/dataUri'
import { buildImportAnalysisPlugin } from './plugins/importAnaysisBuild'
import { resolveSSRExternal } from './ssr/ssrExternal'
import { ssrManifestPlugin } from './ssr/ssrManifestPlugin'

export interface BuildOptions {
/**
Expand Down Expand Up @@ -148,9 +149,15 @@ export interface BuildOptions {
*/
lib?: LibraryOptions | false
/**
* @internal for now
* Produce SSR oriented build. Note this requires specifying SSR entry via
* `rollupOptions.input`.
*/
ssr?: boolean
/**
* Generate SSR manifest for determining style links and asset preload
* directives in production.
*/
ssrManifest?: boolean
}

export interface LibraryOptions {
Expand Down Expand Up @@ -187,6 +194,7 @@ export function resolveBuildOptions(
manifest: false,
lib: false,
ssr: false,
ssrManifest: false,
...raw
}

Expand Down Expand Up @@ -233,6 +241,7 @@ export function resolveBuildPlugins(
? [terserPlugin(options.terserOptions)]
: []),
...(options.manifest ? [manifestPlugin()] : []),
...(options.ssrManifest ? [ssrManifestPlugin(config)] : []),
...(!config.logLevel || config.logLevel === 'info'
? [buildReporterPlugin(config)]
: [])
Expand Down Expand Up @@ -272,13 +281,15 @@ async function doBuild(
inlineConfig: InlineConfig = {}
): Promise<RollupOutput | RollupOutput[]> {
const config = await resolveConfig(inlineConfig, 'build', 'production')
config.logger.info(chalk.cyan(`building for ${config.mode}...`))

const options = config.build
const ssr = !!options.ssr
const libOptions = options.lib
const resolve = (p: string) => path.resolve(config.root, p)

config.logger.info(
chalk.cyan(`building ${ssr ? `SSR bundle ` : ``}for ${config.mode}...`)
)

const resolve = (p: string) => path.resolve(config.root, p)
const input = libOptions
? libOptions.entry
: options.rollupOptions?.input || resolve('index.html')
Expand Down Expand Up @@ -351,6 +362,7 @@ async function doBuild(
// #764 add `Symbol.toStringTag` when build es module into cjs chunk
// #1048 add `Symbol.toStringTag` for module default export
namespaceToStringTag: true,
inlineDynamicImports: ssr && typeof input === 'string',
...output
})
}
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ cli
`or specify minifier to use (default: terser)`
)
.option('--manifest', `[boolean] emit build manifest json`)
.option('--ssrManifest', `[boolean] emit ssr manifest json`)
.option(
'--emptyOutDir',
`[boolean] force empty outDir when it's outside of root`
Expand Down
5 changes: 4 additions & 1 deletion packages/vite/src/node/plugins/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ export function assetPlugin(config: ResolvedConfig): Plugin {
// do not emit assets for SSR build
if (config.command === 'build' && config.build.ssr) {
for (const file in bundle) {
if (bundle[file].type === 'asset') {
if (
bundle[file].type === 'asset' &&
!file.includes('ssr-manifest.json')
) {
delete bundle[file]
}
}
Expand Down
8 changes: 7 additions & 1 deletion packages/vite/src/node/plugins/manifest.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { Plugin } from '../plugin'

export function manifestPlugin(): Plugin {
const manifest: Record<string, { file: string; imports?: string[] }> = {}
const manifest: Record<
string,
{
file: string
imports?: string[]
}
> = {}

return {
name: 'vite:manifest',
Expand Down
38 changes: 38 additions & 0 deletions packages/vite/src/node/ssr/ssrManifestPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ResolvedConfig } from '..'
import { Plugin } from '../plugin'
import { chunkToEmittedCssFileMap } from '../plugins/css'

export function ssrManifestPlugin(config: ResolvedConfig): Plugin {
// module id => preload assets mapping
const ssrManifest: Record<string, string[]> = {}
const base = config.build.base

return {
name: 'vite:manifest',
generateBundle(_options, bundle) {
for (const file in bundle) {
const chunk = bundle[file]
if (chunk.type === 'chunk' && !chunk.isEntry) {
// links for entry chunks are already generated in static HTML
// so we only need to record info for non-entry chunks
// TODO: also include non-CSS assets
const cssFileHandle = chunkToEmittedCssFileMap.get(chunk)
const cssFile = cssFileHandle && this.getFileName(cssFileHandle)
for (const id in chunk.modules) {
const mappedChunks = ssrManifest[id] || (ssrManifest[id] = [])
mappedChunks.push(base + chunk.fileName)
if (cssFile) {
mappedChunks.push(base + cssFile)
}
}
}
}

this.emitFile({
fileName: 'ssr-manifest.json',
type: 'asset',
source: JSON.stringify(ssrManifest, null, 2)
})
}
}
}

0 comments on commit 107e79e

Please sign in to comment.