nav tabs on admin dashboard
This commit is contained in:
+39
-7
@@ -23,12 +23,13 @@ export type RenderOptions = {
|
||||
directives?: Object;
|
||||
isUnaryTag?: Function;
|
||||
cache?: RenderCache;
|
||||
template?: string;
|
||||
template?: string | (content: string, context: any) => string;
|
||||
inject?: boolean;
|
||||
basedir?: string;
|
||||
shouldPreload?: Function;
|
||||
shouldPrefetch?: Function;
|
||||
clientManifest?: ClientManifest;
|
||||
serializer?: Function;
|
||||
runInNewContext?: boolean | 'once';
|
||||
};
|
||||
|
||||
@@ -41,7 +42,8 @@ export function createRenderer ({
|
||||
cache,
|
||||
shouldPreload,
|
||||
shouldPrefetch,
|
||||
clientManifest
|
||||
clientManifest,
|
||||
serializer
|
||||
}: RenderOptions = {}): Renderer {
|
||||
const render = createRenderFunction(modules, directives, isUnaryTag, cache)
|
||||
const templateRenderer = new TemplateRenderer({
|
||||
@@ -49,7 +51,8 @@ export function createRenderer ({
|
||||
inject,
|
||||
shouldPreload,
|
||||
shouldPrefetch,
|
||||
clientManifest
|
||||
clientManifest,
|
||||
serializer
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -79,11 +82,26 @@ export function createRenderer ({
|
||||
}, cb)
|
||||
try {
|
||||
render(component, write, context, err => {
|
||||
if (template) {
|
||||
result = templateRenderer.renderSync(result, context)
|
||||
}
|
||||
if (err) {
|
||||
cb(err)
|
||||
return cb(err)
|
||||
}
|
||||
if (context && context.rendered) {
|
||||
context.rendered(context)
|
||||
}
|
||||
if (template) {
|
||||
try {
|
||||
const res = templateRenderer.render(result, context)
|
||||
if (typeof res !== 'string') {
|
||||
// function template returning promise
|
||||
res
|
||||
.then(html => cb(null, html))
|
||||
.catch(cb)
|
||||
} else {
|
||||
cb(null, res)
|
||||
}
|
||||
} catch (e) {
|
||||
cb(e)
|
||||
}
|
||||
} else {
|
||||
cb(null, result)
|
||||
}
|
||||
@@ -106,13 +124,27 @@ export function createRenderer ({
|
||||
render(component, write, context, done)
|
||||
})
|
||||
if (!template) {
|
||||
if (context && context.rendered) {
|
||||
const rendered = context.rendered
|
||||
renderStream.once('beforeEnd', () => {
|
||||
rendered(context)
|
||||
})
|
||||
}
|
||||
return renderStream
|
||||
} else if (typeof template === 'function') {
|
||||
throw new Error(`function template is only supported in renderToString.`)
|
||||
} else {
|
||||
const templateStream = templateRenderer.createStream(context)
|
||||
renderStream.on('error', err => {
|
||||
templateStream.emit('error', err)
|
||||
})
|
||||
renderStream.pipe(templateStream)
|
||||
if (context && context.rendered) {
|
||||
const rendered = context.rendered
|
||||
renderStream.once('beforeEnd', () => {
|
||||
rendered(context)
|
||||
})
|
||||
}
|
||||
return templateStream
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -225,7 +225,11 @@ function nodesToSegments (
|
||||
} else if (c.type === 2) {
|
||||
segments.push({ type: INTERPOLATION, value: c.expression })
|
||||
} else if (c.type === 3) {
|
||||
segments.push({ type: RAW, value: escape(c.text) })
|
||||
let text = escape(c.text)
|
||||
if (c.isComment) {
|
||||
text = '<!--' + text + '-->'
|
||||
}
|
||||
segments.push({ type: RAW, value: text })
|
||||
}
|
||||
}
|
||||
return segments
|
||||
|
||||
+4
-6
@@ -19,8 +19,6 @@ import {
|
||||
import type { StringSegment } from './codegen'
|
||||
import type { CodegenState } from 'compiler/codegen/index'
|
||||
|
||||
type Attr = { name: string; value: string };
|
||||
|
||||
const plainStringRE = /^"(?:[^"\\]|\\.)*"$|^'(?:[^'\\]|\\.)*'$/
|
||||
|
||||
// let the model AST transform translate v-model into appropriate
|
||||
@@ -42,14 +40,14 @@ export function applyModelTransform (el: ASTElement, state: CodegenState) {
|
||||
}
|
||||
|
||||
export function genAttrSegments (
|
||||
attrs: Array<Attr>
|
||||
attrs: Array<ASTAttr>
|
||||
): Array<StringSegment> {
|
||||
return attrs.map(({ name, value }) => genAttrSegment(name, value))
|
||||
}
|
||||
|
||||
export function genDOMPropSegments (
|
||||
props: Array<Attr>,
|
||||
attrs: ?Array<Attr>
|
||||
props: Array<ASTAttr>,
|
||||
attrs: ?Array<ASTAttr>
|
||||
): Array<StringSegment> {
|
||||
const segments = []
|
||||
props.forEach(({ name, value }) => {
|
||||
@@ -92,7 +90,7 @@ export function genClassSegments (
|
||||
classBinding: ?string
|
||||
): Array<StringSegment> {
|
||||
if (staticClass && !classBinding) {
|
||||
return [{ type: RAW, value: ` class=${staticClass}` }]
|
||||
return [{ type: RAW, value: ` class="${JSON.parse(staticClass)}"` }]
|
||||
} else {
|
||||
return [{
|
||||
type: EXPRESSION,
|
||||
|
||||
+1
@@ -84,6 +84,7 @@ function optimizeSiblings (el) {
|
||||
tag: 'template',
|
||||
attrsList: [],
|
||||
attrsMap: {},
|
||||
rawAttrsMap: {},
|
||||
children: currentOptimizableGroup,
|
||||
ssrOptimizability: optimizability.FULL
|
||||
})
|
||||
|
||||
+46
-46
@@ -66,54 +66,54 @@ export class RenderContext {
|
||||
}
|
||||
|
||||
next () {
|
||||
const lastState = this.renderStates[this.renderStates.length - 1]
|
||||
if (isUndef(lastState)) {
|
||||
return this.done()
|
||||
}
|
||||
switch (lastState.type) {
|
||||
case 'Element':
|
||||
case 'Fragment':
|
||||
const { children, total } = lastState
|
||||
const rendered = lastState.rendered++
|
||||
if (rendered < total) {
|
||||
this.renderNode(children[rendered], false, this)
|
||||
} else {
|
||||
this.renderStates.pop()
|
||||
if (lastState.type === 'Element') {
|
||||
this.write(lastState.endTag, this.next)
|
||||
// eslint-disable-next-line
|
||||
while (true) {
|
||||
const lastState = this.renderStates[this.renderStates.length - 1]
|
||||
if (isUndef(lastState)) {
|
||||
return this.done()
|
||||
}
|
||||
/* eslint-disable no-case-declarations */
|
||||
switch (lastState.type) {
|
||||
case 'Element':
|
||||
case 'Fragment':
|
||||
const { children, total } = lastState
|
||||
const rendered = lastState.rendered++
|
||||
if (rendered < total) {
|
||||
return this.renderNode(children[rendered], false, this)
|
||||
} else {
|
||||
this.next()
|
||||
this.renderStates.pop()
|
||||
if (lastState.type === 'Element') {
|
||||
return this.write(lastState.endTag, this.next)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'Component':
|
||||
this.renderStates.pop()
|
||||
this.activeInstance = lastState.prevActive
|
||||
this.next()
|
||||
break
|
||||
case 'ComponentWithCache':
|
||||
this.renderStates.pop()
|
||||
const { buffer, bufferIndex, componentBuffer, key } = lastState
|
||||
const result = {
|
||||
html: buffer[bufferIndex],
|
||||
components: componentBuffer[bufferIndex]
|
||||
}
|
||||
this.cache.set(key, result)
|
||||
if (bufferIndex === 0) {
|
||||
// this is a top-level cached component,
|
||||
// exit caching mode.
|
||||
this.write.caching = false
|
||||
} else {
|
||||
// parent component is also being cached,
|
||||
// merge self into parent's result
|
||||
buffer[bufferIndex - 1] += result.html
|
||||
const prev = componentBuffer[bufferIndex - 1]
|
||||
result.components.forEach(c => prev.add(c))
|
||||
}
|
||||
buffer.length = bufferIndex
|
||||
componentBuffer.length = bufferIndex
|
||||
this.next()
|
||||
break
|
||||
break
|
||||
case 'Component':
|
||||
this.renderStates.pop()
|
||||
this.activeInstance = lastState.prevActive
|
||||
break
|
||||
case 'ComponentWithCache':
|
||||
this.renderStates.pop()
|
||||
const { buffer, bufferIndex, componentBuffer, key } = lastState
|
||||
const result = {
|
||||
html: buffer[bufferIndex],
|
||||
components: componentBuffer[bufferIndex]
|
||||
}
|
||||
this.cache.set(key, result)
|
||||
if (bufferIndex === 0) {
|
||||
// this is a top-level cached component,
|
||||
// exit caching mode.
|
||||
this.write.caching = false
|
||||
} else {
|
||||
// parent component is also being cached,
|
||||
// merge self into parent's result
|
||||
buffer[bufferIndex - 1] += result.html
|
||||
const prev = componentBuffer[bufferIndex - 1]
|
||||
result.components.forEach(c => prev.add(c))
|
||||
}
|
||||
buffer.length = bufferIndex
|
||||
componentBuffer.length = bufferIndex
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -42,6 +42,7 @@ export default class RenderStream extends stream.Readable {
|
||||
})
|
||||
|
||||
this.end = () => {
|
||||
this.emit('beforeEnd')
|
||||
// the rendering is finished; we should push out the last of the buffer.
|
||||
this.done = true
|
||||
this.push(this.buffer)
|
||||
|
||||
+55
-14
@@ -3,6 +3,7 @@
|
||||
import { escape } from 'web/server/util'
|
||||
import { SSR_ATTR } from 'shared/constants'
|
||||
import { RenderContext } from './render-context'
|
||||
import { resolveAsset } from 'core/util/options'
|
||||
import { generateComponentTrace } from 'core/util/debug'
|
||||
import { ssrCompileToFunctions } from 'web/server/compiler'
|
||||
import { installSSRHelpers } from './optimizing-compiler/runtime-helpers'
|
||||
@@ -18,6 +19,7 @@ let warned = Object.create(null)
|
||||
const warnOnce = msg => {
|
||||
if (!warned[msg]) {
|
||||
warned[msg] = true
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(`\n\u001b[31m${msg}\u001b[39m\n`)
|
||||
}
|
||||
}
|
||||
@@ -48,6 +50,27 @@ const normalizeRender = vm => {
|
||||
}
|
||||
}
|
||||
|
||||
function waitForServerPrefetch (vm, resolve, reject) {
|
||||
let handlers = vm.$options.serverPrefetch
|
||||
if (isDef(handlers)) {
|
||||
if (!Array.isArray(handlers)) handlers = [handlers]
|
||||
try {
|
||||
const promises = []
|
||||
for (let i = 0, j = handlers.length; i < j; i++) {
|
||||
const result = handlers[i].call(vm, vm)
|
||||
if (result && typeof result.then === 'function') {
|
||||
promises.push(result)
|
||||
}
|
||||
}
|
||||
Promise.all(promises).then(resolve).catch(reject)
|
||||
return
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
}
|
||||
resolve()
|
||||
}
|
||||
|
||||
function renderNode (node, isRoot, context) {
|
||||
if (node.isString) {
|
||||
renderStringNode(node, context)
|
||||
@@ -91,7 +114,12 @@ function renderComponent (node, isRoot, context) {
|
||||
const registerComponent = registerComponentForCache(Ctor.options, write)
|
||||
|
||||
if (isDef(getKey) && isDef(cache) && isDef(name)) {
|
||||
const key = name + '::' + getKey(node.componentOptions.propsData)
|
||||
const rawKey = getKey(node.componentOptions.propsData)
|
||||
if (rawKey === false) {
|
||||
renderComponentInner(node, isRoot, context)
|
||||
return
|
||||
}
|
||||
const key = name + '::' + rawKey
|
||||
const { has, get } = context
|
||||
if (isDef(has)) {
|
||||
has(key, hit => {
|
||||
@@ -165,13 +193,20 @@ function renderComponentInner (node, isRoot, context) {
|
||||
context.activeInstance
|
||||
)
|
||||
normalizeRender(child)
|
||||
const childNode = child._render()
|
||||
childNode.parent = node
|
||||
context.renderStates.push({
|
||||
type: 'Component',
|
||||
prevActive
|
||||
})
|
||||
renderNode(childNode, isRoot, context)
|
||||
|
||||
const resolve = () => {
|
||||
const childNode = child._render()
|
||||
childNode.parent = node
|
||||
context.renderStates.push({
|
||||
type: 'Component',
|
||||
prevActive
|
||||
})
|
||||
renderNode(childNode, isRoot, context)
|
||||
}
|
||||
|
||||
const reject = context.done
|
||||
|
||||
waitForServerPrefetch(child, resolve, reject)
|
||||
}
|
||||
|
||||
function renderAsyncComponent (node, isRoot, context) {
|
||||
@@ -324,11 +359,13 @@ function renderStartingTag (node: VNode, context) {
|
||||
if (dirs) {
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
const name = dirs[i].name
|
||||
const dirRenderer = directives[name]
|
||||
if (dirRenderer && name !== 'show') {
|
||||
// directives mutate the node's data
|
||||
// which then gets rendered by modules
|
||||
dirRenderer(node, dirs[i])
|
||||
if (name !== 'show') {
|
||||
const dirRenderer = resolveAsset(context, 'directives', name)
|
||||
if (dirRenderer) {
|
||||
// directives mutate the node's data
|
||||
// which then gets rendered by modules
|
||||
dirRenderer(node, dirs[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -391,6 +428,10 @@ export function createRenderFunction (
|
||||
})
|
||||
installSSRHelpers(component)
|
||||
normalizeRender(component)
|
||||
renderNode(component._render(), true, context)
|
||||
|
||||
const resolve = () => {
|
||||
renderNode(component._render(), true, context)
|
||||
}
|
||||
waitForServerPrefetch(component, resolve, done)
|
||||
}
|
||||
}
|
||||
|
||||
+40
-20
@@ -11,11 +11,12 @@ import type { ParsedTemplate } from './parse-template'
|
||||
import type { AsyncFileMapper } from './create-async-file-mapper'
|
||||
|
||||
type TemplateRendererOptions = {
|
||||
template: ?string;
|
||||
template?: string | (content: string, context: any) => string;
|
||||
inject?: boolean;
|
||||
clientManifest?: ClientManifest;
|
||||
shouldPreload?: (file: string, type: string) => boolean;
|
||||
shouldPrefetch?: (file: string, type: string) => boolean;
|
||||
serializer?: Function;
|
||||
};
|
||||
|
||||
export type ClientManifest = {
|
||||
@@ -41,26 +42,39 @@ type Resource = {
|
||||
export default class TemplateRenderer {
|
||||
options: TemplateRendererOptions;
|
||||
inject: boolean;
|
||||
parsedTemplate: ParsedTemplate | null;
|
||||
parsedTemplate: ParsedTemplate | Function | null;
|
||||
publicPath: string;
|
||||
clientManifest: ClientManifest;
|
||||
preloadFiles: Array<Resource>;
|
||||
prefetchFiles: Array<Resource>;
|
||||
mapFiles: AsyncFileMapper;
|
||||
serialize: Function;
|
||||
|
||||
constructor (options: TemplateRendererOptions) {
|
||||
this.options = options
|
||||
this.inject = options.inject !== false
|
||||
// if no template option is provided, the renderer is created
|
||||
// as a utility object for rendering assets like preload links and scripts.
|
||||
this.parsedTemplate = options.template
|
||||
? parseTemplate(options.template)
|
||||
|
||||
const { template } = options
|
||||
this.parsedTemplate = template
|
||||
? typeof template === 'string'
|
||||
? parseTemplate(template)
|
||||
: template
|
||||
: null
|
||||
|
||||
// function used to serialize initial state JSON
|
||||
this.serialize = options.serializer || (state => {
|
||||
return serialize(state, { isJSON: true })
|
||||
})
|
||||
|
||||
// extra functionality with client manifest
|
||||
if (options.clientManifest) {
|
||||
const clientManifest = this.clientManifest = options.clientManifest
|
||||
this.publicPath = clientManifest.publicPath.replace(/\/$/, '')
|
||||
// ensure publicPath ends with /
|
||||
this.publicPath = clientManifest.publicPath === ''
|
||||
? ''
|
||||
: clientManifest.publicPath.replace(/([^\/])$/, '$1/')
|
||||
// preload/prefetch directives
|
||||
this.preloadFiles = (clientManifest.initial || []).map(normalizeFile)
|
||||
this.prefetchFiles = (clientManifest.async || []).map(normalizeFile)
|
||||
@@ -79,12 +93,17 @@ export default class TemplateRenderer {
|
||||
}
|
||||
|
||||
// render synchronously given rendered app content and render context
|
||||
renderSync (content: string, context: ?Object) {
|
||||
render (content: string, context: ?Object): string | Promise<string> {
|
||||
const template = this.parsedTemplate
|
||||
if (!template) {
|
||||
throw new Error('renderSync cannot be called without a template.')
|
||||
throw new Error('render cannot be called without a template.')
|
||||
}
|
||||
context = context || {}
|
||||
|
||||
if (typeof template === 'function') {
|
||||
return template(content, context)
|
||||
}
|
||||
|
||||
if (this.inject) {
|
||||
return (
|
||||
template.head(context) +
|
||||
@@ -108,13 +127,13 @@ export default class TemplateRenderer {
|
||||
}
|
||||
|
||||
renderStyles (context: Object): string {
|
||||
const cssFiles = this.clientManifest
|
||||
? this.clientManifest.all.filter(isCSS)
|
||||
: []
|
||||
const initial = this.preloadFiles || []
|
||||
const async = this.getUsedAsyncFiles(context) || []
|
||||
const cssFiles = initial.concat(async).filter(({ file }) => isCSS(file))
|
||||
return (
|
||||
// render links for css files
|
||||
(cssFiles.length
|
||||
? cssFiles.map(file => `<link rel="stylesheet" href="${this.publicPath}/${file}">`).join('')
|
||||
? cssFiles.map(({ file }) => `<link rel="stylesheet" href="${this.publicPath}${file}">`).join('')
|
||||
: '') +
|
||||
// context.styles is a getter exposed by vue-style-loader which contains
|
||||
// the inline component styles collected during SSR
|
||||
@@ -153,7 +172,7 @@ export default class TemplateRenderer {
|
||||
extra = ` type="font/${extension}" crossorigin`
|
||||
}
|
||||
return `<link rel="preload" href="${
|
||||
this.publicPath}/${file
|
||||
this.publicPath}${file
|
||||
}"${
|
||||
asType !== '' ? ` as="${asType}"` : ''
|
||||
}${
|
||||
@@ -179,7 +198,7 @@ export default class TemplateRenderer {
|
||||
if (alreadyRendered(file)) {
|
||||
return ''
|
||||
}
|
||||
return `<link rel="prefetch" href="${this.publicPath}/${file}">`
|
||||
return `<link rel="prefetch" href="${this.publicPath}${file}">`
|
||||
}).join('')
|
||||
} else {
|
||||
return ''
|
||||
@@ -191,22 +210,23 @@ export default class TemplateRenderer {
|
||||
contextKey = 'state',
|
||||
windowKey = '__INITIAL_STATE__'
|
||||
} = options || {}
|
||||
const state = serialize(context[contextKey], { isJSON: true })
|
||||
const state = this.serialize(context[contextKey])
|
||||
const autoRemove = process.env.NODE_ENV === 'production'
|
||||
? ';(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());'
|
||||
: ''
|
||||
const nonceAttr = context.nonce ? ` nonce="${context.nonce}"` : ''
|
||||
return context[contextKey]
|
||||
? `<script>window.${windowKey}=${state}${autoRemove}</script>`
|
||||
? `<script${nonceAttr}>window.${windowKey}=${state}${autoRemove}</script>`
|
||||
: ''
|
||||
}
|
||||
|
||||
renderScripts (context: Object): string {
|
||||
if (this.clientManifest) {
|
||||
const initial = this.preloadFiles
|
||||
const async = this.getUsedAsyncFiles(context)
|
||||
const needed = [initial[0]].concat(async || [], initial.slice(1))
|
||||
return needed.filter(({ file }) => isJS(file)).map(({ file }) => {
|
||||
return `<script src="${this.publicPath}/${file}" defer></script>`
|
||||
const initial = this.preloadFiles.filter(({ file }) => isJS(file))
|
||||
const async = (this.getUsedAsyncFiles(context) || []).filter(({ file }) => isJS(file))
|
||||
const needed = [initial[0]].concat(async, initial.slice(1))
|
||||
return needed.map(({ file }) => {
|
||||
return `<script src="${this.publicPath}${file}" defer></script>`
|
||||
}).join('')
|
||||
} else {
|
||||
return ''
|
||||
|
||||
+6
-11
@@ -1,6 +1,6 @@
|
||||
const hash = require('hash-sum')
|
||||
const uniq = require('lodash.uniq')
|
||||
import { isJS } from './util'
|
||||
import { isJS, isCSS, onEmit } from './util'
|
||||
|
||||
export default class VueSSRClientPlugin {
|
||||
constructor (options = {}) {
|
||||
@@ -10,7 +10,7 @@ export default class VueSSRClientPlugin {
|
||||
}
|
||||
|
||||
apply (compiler) {
|
||||
compiler.plugin('emit', (compilation, cb) => {
|
||||
onEmit(compiler, 'vue-client-plugin', (compilation, cb) => {
|
||||
const stats = compilation.getStats().toJson()
|
||||
|
||||
const allFiles = uniq(stats.assets
|
||||
@@ -19,10 +19,10 @@ export default class VueSSRClientPlugin {
|
||||
const initialFiles = uniq(Object.keys(stats.entrypoints)
|
||||
.map(name => stats.entrypoints[name].assets)
|
||||
.reduce((assets, all) => all.concat(assets), [])
|
||||
.filter(isJS))
|
||||
.filter((file) => isJS(file) || isCSS(file)))
|
||||
|
||||
const asyncFiles = allFiles
|
||||
.filter(isJS)
|
||||
.filter((file) => isJS(file) || isCSS(file))
|
||||
.filter(file => initialFiles.indexOf(file) < 0)
|
||||
|
||||
const manifest = {
|
||||
@@ -43,7 +43,8 @@ export default class VueSSRClientPlugin {
|
||||
if (!chunk || !chunk.files) {
|
||||
return
|
||||
}
|
||||
const files = manifest.modules[hash(m.identifier)] = chunk.files.map(fileToIndex)
|
||||
const id = m.identifier.replace(/\s\w+$/, '') // remove appended hash
|
||||
const files = manifest.modules[hash(id)] = chunk.files.map(fileToIndex)
|
||||
// find all asset modules associated with the same chunk
|
||||
assetModules.forEach(m => {
|
||||
if (m.chunks.some(id => id === cid)) {
|
||||
@@ -53,12 +54,6 @@ export default class VueSSRClientPlugin {
|
||||
}
|
||||
})
|
||||
|
||||
// const debug = (file, obj) => {
|
||||
// require('fs').writeFileSync(__dirname + '/' + file, JSON.stringify(obj, null, 2))
|
||||
// }
|
||||
// debug('stats.json', stats)
|
||||
// debug('client-manifest.json', manifest)
|
||||
|
||||
const json = JSON.stringify(manifest, null, 2)
|
||||
compilation.assets[this.options.filename] = {
|
||||
source: () => json,
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { validate, isJS } from './util'
|
||||
import { validate, isJS, onEmit } from './util'
|
||||
|
||||
export default class VueSSRServerPlugin {
|
||||
constructor (options = {}) {
|
||||
@@ -10,7 +10,7 @@ export default class VueSSRServerPlugin {
|
||||
apply (compiler) {
|
||||
validate(compiler)
|
||||
|
||||
compiler.plugin('emit', (compilation, cb) => {
|
||||
onEmit(compiler, 'vue-server-plugin', (compilation, cb) => {
|
||||
const stats = compilation.getStats().toJson()
|
||||
const entryName = Object.keys(stats.entrypoints)[0]
|
||||
const entryInfo = stats.entrypoints[entryName]
|
||||
@@ -43,7 +43,7 @@ export default class VueSSRServerPlugin {
|
||||
}
|
||||
|
||||
stats.assets.forEach(asset => {
|
||||
if (asset.name.match(/\.js$/)) {
|
||||
if (isJS(asset.name)) {
|
||||
bundle.files[asset.name] = compilation.assets[asset.name].source()
|
||||
} else if (asset.name.match(/\.js\.map$/)) {
|
||||
bundle.maps[asset.name.replace(/\.map$/, '')] = JSON.parse(compilation.assets[asset.name].source())
|
||||
|
||||
+10
@@ -21,4 +21,14 @@ export const validate = compiler => {
|
||||
}
|
||||
}
|
||||
|
||||
export const onEmit = (compiler, name, hook) => {
|
||||
if (compiler.hooks) {
|
||||
// Webpack >= 4.0.0
|
||||
compiler.hooks.emit.tapAsync(name, hook)
|
||||
} else {
|
||||
// Webpack < 4.0.0
|
||||
compiler.plugin('emit', hook)
|
||||
}
|
||||
}
|
||||
|
||||
export { isJS, isCSS } from '../util'
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/* @flow */
|
||||
|
||||
const MAX_STACK_DEPTH = 1000
|
||||
const MAX_STACK_DEPTH = 800
|
||||
const noop = _ => _
|
||||
|
||||
const defer = typeof process !== 'undefined' && process.nextTick
|
||||
|
||||
Reference in New Issue
Block a user