@@ -12,7 +12,6 @@ const styleCompilerPath = normalize.lib('style-compiler/index')
1212const templateCompilerPath = normalize . lib ( 'template-compiler/index' )
1313const templatePreprocessorPath = normalize . lib ( 'template-compiler/preprocessor' )
1414const componentNormalizerPath = normalize . lib ( 'runtime/component-normalizer' )
15- const componentNormalizerESMPath = normalize . lib ( 'runtime/component-normalizer.esm' )
1615
1716// dep loaders
1817const styleLoaderPath = normalize . dep ( 'vue-style-loader' )
@@ -64,6 +63,10 @@ module.exports = function (content) {
6463 query
6564 )
6665
66+ // shadow mode is an internal option
67+ // enabled via vue-cli's --target web-component
68+ const isShadowMode = ! ! options . shadowMode
69+
6770 // disable esModule in inject mode
6871 // because import/export must be top-level
6972 if ( query . inject ) {
@@ -167,11 +170,12 @@ module.exports = function (content) {
167170 // add requires for styles
168171 let cssModules
169172 if ( parts . styles . length ) {
170- let styleInjectionCode = 'function injectStyle (ssrContext) {\n'
173+ const needsLazyInjection = isServer || isShadowMode
174+ let styleInjectionCode = 'function injectStyle (context) {\n'
171175 if ( needsHotReload ) {
172176 styleInjectionCode += ` if (disposed) return\n`
173177 }
174- if ( isServer ) {
178+ if ( needsLazyInjection ) {
175179 styleInjectionCode += `var i\n`
176180 }
177181 parts . styles . forEach ( ( style , i ) => {
@@ -182,11 +186,11 @@ module.exports = function (content) {
182186
183187 const hasStyleLoader = requireString . indexOf ( 'style-loader' ) > - 1
184188 const hasVueStyleLoader = requireString . indexOf ( 'vue-style-loader' ) > - 1
185- // vue-style-loader exposes inject functions during SSR so they are
186- // always called
189+ // vue-style-loader exposes inject functions in SSR or shadow mode so they
190+ // are always called
187191 const invokeStyle =
188- isServer && hasVueStyleLoader
189- ? code => `;(i=${ code } ,i.__inject__&&i.__inject__(ssrContext ),i)\n`
192+ needsLazyInjection && hasVueStyleLoader
193+ ? code => `;(i=${ code } ,i.__inject__&&i.__inject__(context ),i)\n`
190194 : code => ` ${ code } \n`
191195
192196 const moduleName = style . module === true ? '$style' : style . module
@@ -261,16 +265,16 @@ module.exports = function (content) {
261265 // scopeId,
262266 // moduleIdentifier (server only)
263267 // )
268+ const componentNormalizerRequest = loaderUtils . stringifyRequest (
269+ loaderContext ,
270+ '!' + componentNormalizerPath
271+ )
264272 if ( ! options . esModule ) {
265273 output +=
266- 'var normalizeComponent = require(' +
267- loaderUtils . stringifyRequest ( loaderContext , '!' + componentNormalizerPath ) +
268- ')\n'
274+ `var normalizeComponent = require(${ componentNormalizerRequest } ).default\n`
269275 } else {
270276 output +=
271- `import normalizeComponent from ` +
272- loaderUtils . stringifyRequest ( loaderContext , '!' + componentNormalizerESMPath ) +
273- '\n'
277+ `import normalizeComponent from ${ componentNormalizerRequest } \n`
274278 }
275279
276280 // <script>
@@ -332,10 +336,13 @@ module.exports = function (content) {
332336 '\n'
333337
334338 // style
339+ // the injection function is passed to the normalizer and injected into
340+ // component lifecycle hooks. In shadow mode, we expose the inject function
341+ // directly on the component's options so we don't pass it here.
335342 output += '/* styles */\n'
336343 output +=
337344 'var __vue_styles__ = ' +
338- ( parts . styles . length ? 'injectStyle' : 'null' ) +
345+ ( parts . styles . length && ! isShadowMode ? 'injectStyle' : 'null' ) +
339346 '\n'
340347
341348 // scopeId
@@ -363,6 +370,21 @@ module.exports = function (content) {
363370 ' __vue_module_identifier__\n' +
364371 ')\n'
365372
373+ // expose style injection on options
374+ // this will be used by vue-cli's web component entry
375+ if ( isShadowMode ) {
376+ // the shadow inject id will be the module id of the entry Vue component,
377+ // which is the frist Vue component encountered in this compilation
378+ let shadowInjectId = process . env . VUE_SHADOW_INJECT_ID
379+ if ( ! shadowInjectId ) {
380+ shadowInjectId = process . env . VUE_SHADOW_INJECT_ID =
381+ `__vue_shadow_injector__${ moduleId . replace ( `data-v-` , '' ) } `
382+ }
383+ output +=
384+ `var shadowInjectId = Component.options.__shadowInjectId = '${ shadowInjectId } '\n` +
385+ `;(window[shadowInjectId] || (window[shadowInjectId] = [])).push(injectStyle)\n`
386+ }
387+
366388 // development-only code
367389 if ( ! isProduction ) {
368390 // add filename in dev
0 commit comments