Navigation Menu

Skip to content

Commit

Permalink
inline css links in renderStyles()
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Apr 23, 2017
1 parent 3a621d1 commit 2efc044
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 21 deletions.
22 changes: 15 additions & 7 deletions src/server/template-renderer/index.js
Expand Up @@ -3,15 +3,13 @@
const path = require('path')
const serialize = require('serialize-javascript')

import { isJS, isCSS } from '../util'
import TemplateStream from './template-stream'
import { parseTemplate } from './parse-template'
import { createMapper } from './create-async-file-mapper'
import type { ParsedTemplate } from './parse-template'
import type { AsyncFileMapper } from './create-async-file-mapper'

const JS_RE = /\.js($|\?)/
export const isJS = (file: string): boolean => JS_RE.test(file)

type TemplateRendererOptions = {
template: ?string;
inject?: boolean;
Expand Down Expand Up @@ -100,8 +98,18 @@ export default class TemplateRenderer {
}

renderStyles (context: Object): string {
// context.styles is a getter exposed by vue-style-loader
return context.styles || ''
const cssFiles = this.clientManifest
? this.clientManifest.all.filter(isCSS)
: []
return (
// render links for css files
(cssFiles.length
? 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
(context.styles || '')
)
}

renderResourceHints (context: Object): string {
Expand All @@ -117,8 +125,8 @@ export default class TemplateRenderer {
const ext = path.extname(withoutQuery).slice(1)
const type = getPreloadType(ext)
const shouldPreload = this.options.shouldPreload
// by default, we only preload scripts
if (!shouldPreload && type !== 'script') {
// by default, we only preload scripts or css
if (!shouldPreload && type !== 'script' && type !== 'style') {
return ''
}
// user wants to explicitly control what to preload
Expand Down
7 changes: 4 additions & 3 deletions src/server/template-renderer/template-stream.js
Expand Up @@ -49,9 +49,10 @@ export default class TemplateStream extends Transform {
this.push(links)
}

// inline server-rendered CSS collected by vue-style-loader
if (this.context.styles) {
this.push(this.context.styles)
// CSS files and inline server-rendered CSS collected by vue-style-loader
const styles = this.renderer.renderStyles(this.context)
if (styles) {
this.push(styles)
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/server/util.js
@@ -0,0 +1,5 @@
/* @flow */

export const isJS = (file: string): boolean => /\.js($|\?)/.test(file)

export const isCSS = (file: string): boolean => /\.css($|\?)/.test(file)
10 changes: 5 additions & 5 deletions src/server/webpack-plugin/client.js
Expand Up @@ -15,20 +15,20 @@ export default class VueSSRClientPlugin {
const allFiles = stats.assets
.map(a => a.name)

const initialScripts = Object.keys(stats.entrypoints)
const initialFiles = Object.keys(stats.entrypoints)
.map(name => stats.entrypoints[name].assets)
.reduce((assets, all) => all.concat(assets), [])
.filter(isJS)

const asyncScripts = allFiles
const asyncFiles = allFiles
.filter(isJS)
.filter(file => initialScripts.indexOf(file) < 0)
.filter(file => initialFiles.indexOf(file) < 0)

const manifest = {
publicPath: stats.publicPath,
all: allFiles,
initial: initialScripts,
async: asyncScripts,
initial: initialFiles,
async: asyncFiles,
modules: { /* [identifier: string]: Array<index: number> */ }
}

Expand Down
2 changes: 1 addition & 1 deletion src/server/webpack-plugin/util.js
Expand Up @@ -21,4 +21,4 @@ export const validate = compiler => {
}
}

export const isJS = file => /\.js($|\?)/.test(file)
export { isJS, isCSS } from '../util'
2 changes: 1 addition & 1 deletion test/ssr/compile-with-webpack.js
Expand Up @@ -16,7 +16,7 @@ export function compileWithWebpack (file, extraConfig, cb) {
loader: require.resolve('./async-loader')
},
{
test: /\.(png|woff2)$/,
test: /\.(png|woff2|css)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]'
Expand Down
1 change: 1 addition & 0 deletions test/ssr/fixtures/async-foo.js
@@ -1,4 +1,5 @@
// import image and font
import './test.css'
import font from './test.woff2'
import image from './test.png'

Expand Down
Empty file added test/ssr/fixtures/test.css
Empty file.
12 changes: 8 additions & 4 deletions test/ssr/ssr-template.spec.js
Expand Up @@ -225,11 +225,14 @@ describe('SSR: template option', () => {
`<link rel="preload" href="/manifest.js" as="script">` +
`<link rel="preload" href="/main.js" as="script">` +
`<link rel="preload" href="/0.js" as="script">` +
`<link rel="preload" href="/test.css" as="style">` +
// images and fonts are only preloaded when explicitly asked for
(preloadOtherAssets ? `<link rel="preload" href="/test.png" as="image">` : ``) +
(preloadOtherAssets ? `<link rel="preload" href="/test.woff2" as="font" type="font/woff2" crossorigin>` : ``) +
// unused chunks should have prefetch
`<link rel="prefetch" href="/1.js" as="script">` +
// css assets should be loaded
`<link rel="stylesheet" href="/test.css">` +
`</head><body>` +
`<div data-server-rendered="true"><div>async test.woff2 test.png</div></div>` +
// manifest chunk should be first
Expand All @@ -243,7 +246,7 @@ describe('SSR: template option', () => {
createClientManifestAssertions(false)

function createClientManifestAssertions (runInNewContext) {
it('bundleRenderer + renderToString + clientManifest', done => {
it('bundleRenderer + renderToString + clientManifest ()', done => {
createRendererWithManifest('split.js', { runInNewContext }, renderer => {
renderer.renderToString({}, (err, res) => {
expect(err).toBeNull()
Expand All @@ -257,7 +260,7 @@ describe('SSR: template option', () => {
createRendererWithManifest('split.js', {
runInNewContext,
shouldPreload: (file, type) => {
if (type === 'image' || type === 'script' || type === 'font') {
if (type === 'image' || type === 'script' || type === 'font' || type === 'style') {
return true
}
}
Expand All @@ -278,7 +281,7 @@ describe('SSR: template option', () => {
createRendererWithManifest('split.js', {
runInNewContext,
template: `<html>` +
`<head>{{{ renderResourceHints() }}}</head>` +
`<head>{{{ renderResourceHints() }}}{{{ renderStyles() }}}</head>` +
`<body><!--vue-ssr-outlet-->{{{ renderScripts() }}}</body>` +
`</html>`,
inject: false
Expand All @@ -303,7 +306,8 @@ describe('SSR: template option', () => {

const customOutput =
`<html><head>${
context.renderResourceHints()
context.renderResourceHints() +
context.renderStyles()
}</head><body>${
res +
context.renderScripts()
Expand Down

0 comments on commit 2efc044

Please sign in to comment.