From 354f0631f5e93f0116c62ed1128971443e8e2010 Mon Sep 17 00:00:00 2001 From: Blake Newman Date: Fri, 28 Apr 2017 11:40:58 +0100 Subject: [PATCH 1/2] [Fix] functional SFC style injection support --- lib/component-normalizer.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/component-normalizer.js b/lib/component-normalizer.js index 9a97239dd..05c7be82f 100644 --- a/lib/component-normalizer.js +++ b/lib/component-normalizer.js @@ -61,9 +61,18 @@ module.exports = function normalizeComponent ( hook = injectStyles } - if (hook) { + var existing = options.functional ? options.render : options.beforeCreate + + if (hook && options.functional && injectStyles) { + // inject styles for functioal component in vue file + options.render = function renderWithStyleInjection (h, context) { + hook(context) + return existing(h, context) + } + } + + if (hook && !options.functional) { // inject component registration as beforeCreate hook - var existing = options.beforeCreate options.beforeCreate = existing ? [].concat(existing, hook) : [hook] From b702b094f722eab53f1a6ce31c243d1f7dd865e9 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 2 May 2017 18:36:26 +0800 Subject: [PATCH 2/2] improvements for handling functional components with styles --- lib/component-normalizer.js | 35 +++++++++++--------- package.json | 6 ++-- test/fixtures/functional-style.vue | 12 +++++++ test/fixtures/ssr-style.js | 4 ++- test/fixtures/ssr-style.vue | 7 +++- test/test.js | 53 +++++++++++++++++++++--------- yarn.lock | 48 +++++++++++++++++---------- 7 files changed, 113 insertions(+), 52 deletions(-) create mode 100644 test/fixtures/functional-style.vue diff --git a/lib/component-normalizer.js b/lib/component-normalizer.js index 05c7be82f..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__ @@ -61,23 +64,25 @@ module.exports = function normalizeComponent ( hook = injectStyles } - var existing = options.functional ? options.render : options.beforeCreate - - if (hook && options.functional && injectStyles) { - // inject styles for functioal component in vue file - options.render = function renderWithStyleInjection (h, context) { - hook(context) - return existing(h, context) + if (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) + } } } - if (hook && !options.functional) { - // inject component registration as beforeCreate hook - options.beforeCreate = existing - ? [].concat(existing, hook) - : [hook] - } - return { esModule: esModule, exports: scriptExports, 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"