diff --git a/lib/component-normalizer.js b/lib/component-normalizer.js
index 9a97239dd..12f2db170 100644
--- a/lib/component-normalizer.js
+++ b/lib/component-normalizer.js
@@ -40,7 +40,10 @@ module.exports = function normalizeComponent (
if (moduleIdentifier) { // server build
hook = function (context) {
// 2.3 injection
- context = context || (this.$vnode && this.$vnode.ssrContext)
+ context =
+ context || // cached call
+ (this.$vnode && this.$vnode.ssrContext) || // stateful
+ (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional
// 2.2 with runInNewContext: true
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {
context = __VUE_SSR_CONTEXT__
@@ -62,11 +65,22 @@ module.exports = function normalizeComponent (
}
if (hook) {
- // inject component registration as beforeCreate hook
- var existing = options.beforeCreate
- options.beforeCreate = existing
- ? [].concat(existing, hook)
- : [hook]
+ var functional = options.functional
+ var existing = functional
+ ? options.render
+ : options.beforeCreate
+ if (!functional) {
+ // inject component registration as beforeCreate hook
+ options.beforeCreate = existing
+ ? [].concat(existing, hook)
+ : [hook]
+ } else {
+ // register for functioal component in vue file
+ options.render = function renderWithStyleInjection (h, context) {
+ hook.call(context)
+ return existing(h, context)
+ }
+ }
}
return {
diff --git a/package.json b/package.json
index 3070c1760..7a4723a80 100644
--- a/package.json
+++ b/package.json
@@ -78,9 +78,9 @@
"stylus-loader": "^2.0.0",
"sugarss": "^0.2.0",
"url-loader": "^0.5.7",
- "vue": "^2.3.0-beta.1",
- "vue-server-renderer": "^2.3.0-beta.1",
- "vue-template-compiler": "^2.3.0-beta.1",
+ "vue": "^2.3.2",
+ "vue-server-renderer": "^2.3.2",
+ "vue-template-compiler": "^2.3.2",
"webpack": "^2.2.0"
}
}
diff --git a/test/fixtures/functional-style.vue b/test/fixtures/functional-style.vue
new file mode 100644
index 000000000..70f575f43
--- /dev/null
+++ b/test/fixtures/functional-style.vue
@@ -0,0 +1,12 @@
+
+
+
diff --git a/test/fixtures/ssr-style.js b/test/fixtures/ssr-style.js
index 35f445ce3..38dc1d7f8 100644
--- a/test/fixtures/ssr-style.js
+++ b/test/fixtures/ssr-style.js
@@ -1,4 +1,6 @@
var Vue = require('vue')
var App = require('./ssr-style.vue')
-module.exports = new Vue(App)
+module.exports = () => new Vue({
+ render: h => h(App)
+})
diff --git a/test/fixtures/ssr-style.vue b/test/fixtures/ssr-style.vue
index 059d4bf6d..55d15f674 100644
--- a/test/fixtures/ssr-style.vue
+++ b/test/fixtures/ssr-style.vue
@@ -2,14 +2,19 @@
Hello
+
diff --git a/test/test.js b/test/test.js
index 9ca17de66..5b9989995 100644
--- a/test/test.js
+++ b/test/test.js
@@ -84,29 +84,30 @@ function test (options, assert) {
}
function mockRender (options, data) {
+ function h (tag, data, children) {
+ if (Array.isArray(data)) {
+ children = data
+ data = null
+ }
+ return {
+ tag: tag,
+ data: data,
+ children: children
+ }
+ }
return options.render.call(Object.assign({
_v (val) {
return val
},
_self: {},
- $createElement (tag, data, children) {
- if (Array.isArray(data)) {
- children = data
- data = null
- }
- return {
- tag: tag,
- data: data,
- children: children
- }
- },
+ $createElement: h,
_m (index) {
return options.staticRenderFns[index].call(this)
},
_s (str) {
return String(str)
}
- }, data))
+ }, data), h)
}
function interopDefault (module) {
@@ -611,24 +612,28 @@ describe('vue-loader', function () {
}
}, code => {
const renderer = SSR.createBundleRenderer(code, {
- basedir: __dirname
+ basedir: __dirname,
+ runInNewContext: 'once'
})
const context = {
_registeredComponents: new Set()
}
renderer.renderToString(context, (err, res) => {
if (err) return done(err)
- expect(res).to.contain('server-rendered')
+ expect(res).to.contain('data-server-rendered')
expect(res).to.contain('Hello
')
expect(res).to.contain('Hello from Component A!')
+ expect(res).to.contain('functional
')
// from main component
expect(context.styles).to.contain('h1 { color: green;')
// from imported child component
expect(context.styles).to.contain('comp-a h2 {\n color: #f00;')
// from imported css file
expect(context.styles).to.contain('h1 { color: red;')
+ // from imported functional component
+ expect(context.styles).to.contain('.foo { color: red;')
// collect component identifiers during render
- expect(Array.from(context._registeredComponents).length).to.equal(2)
+ expect(Array.from(context._registeredComponents).length).to.equal(3)
done()
})
})
@@ -834,4 +839,22 @@ describe('vue-loader', function () {
done()
})
})
+
+ it('functional component with styles', done => {
+ test({
+ entry: './test/fixtures/functional-style.vue'
+ }, (window, module, rawModule) => {
+ expect(module.functional).to.equal(true)
+ var vnode = mockRender(module)
+ // hi
+ expect(vnode.tag).to.equal('div')
+ expect(vnode.data.class).to.equal('foo')
+ expect(vnode.children[0]).to.equal('functional')
+
+ var style = window.document.querySelector('style').textContent
+ style = normalizeNewline(style)
+ expect(style).to.contain('.foo { color: red;\n}')
+ done()
+ })
+ })
})
diff --git a/yarn.lock b/yarn.lock
index 42144c822..7d191b3fa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2497,6 +2497,10 @@ lodash._isiterateecall@^3.0.0:
version "3.0.9"
resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
+lodash._reinterpolate@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
+
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
@@ -2533,6 +2537,19 @@ lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+lodash.template@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0"
+ dependencies:
+ lodash._reinterpolate "~3.0.0"
+ lodash.templatesettings "^4.0.0"
+
+lodash.templatesettings@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316"
+ dependencies:
+ lodash._reinterpolate "~3.0.0"
+
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -4137,21 +4154,18 @@ vue-hot-reload-api@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.1.0.tgz#9ca58a6e0df9078554ce1708688b6578754d86de"
-vue-server-renderer@^2.3.0:
- version "2.2.6"
- resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.2.6.tgz#0a20535544b6948bca076380d058e19bb1304eef"
+vue-server-renderer@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.3.2.tgz#01bfde9c524ef041873f1e2d18f9356c620b4f8c"
dependencies:
- de-indent "^1.0.2"
+ chalk "^1.1.3"
+ hash-sum "^1.0.2"
he "^1.1.0"
+ lodash.template "^4.4.0"
+ lodash.uniq "^4.5.0"
resolve "^1.2.0"
- source-map "0.5.6"
- vue-ssr-html-stream "^2.1.0"
-
-vue-ssr-html-stream@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/vue-ssr-html-stream/-/vue-ssr-html-stream-2.2.0.tgz#56d78b96c9c172b43749a324c156e888aca96d92"
- dependencies:
serialize-javascript "^1.3.0"
+ source-map "0.5.6"
vue-style-loader@^3.0.0:
version "3.0.1"
@@ -4160,9 +4174,9 @@ vue-style-loader@^3.0.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
-vue-template-compiler@^2.3.0:
- version "2.2.6"
- resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.2.6.tgz#2e2928daf0cd0feca9dfc35a9729adeae173ec68"
+vue-template-compiler@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.3.2.tgz#d48a7f53df5f497033827182ceb4f0d340803017"
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@@ -4171,9 +4185,9 @@ vue-template-es2015-compiler@^1.2.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.5.2.tgz#a0a6c50c941d2a4abda963f2f42c337ac450ee95"
-vue@^2.3.0:
- version "2.2.6"
- resolved "https://registry.yarnpkg.com/vue/-/vue-2.2.6.tgz#451714b394dd6d4eae7b773c40c2034a59621aed"
+vue@^2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-2.3.2.tgz#9e52aae3593480be235ff227557837e69f98203a"
watchpack@^1.3.1:
version "1.3.1"