cnf
2025-05-10 386fa0eca75ddc88165f9b73038f2a2239e1072e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const { attrsToQuery } = require('./utils')
const hotReloadAPIPath = JSON.stringify(require.resolve('vue-hot-reload-api'))
const nonWhitespaceRE = /\S+/
 
module.exports = function genStyleInjectionCode (
  loaderContext,
  styles,
  id,
  resourcePath,
  stringifyRequest,
  needsHotReload,
  needsExplicitInjection, // fixed by xxxxxx nvue 时,指定了 target 为 node,激活 needsExplicitInjection
  platform
) {
  let styleImportsCode = ``
  let styleInjectionCode = ``
  let cssModulesHotReloadCode = ``
 
  let hasCSSModules = false
  const cssModuleNames = new Map()
 
  function genStyleRequest (style, i) {
    const src = style.src || resourcePath
    const attrsQuery = attrsToQuery(style.attrs, 'css')
    const inheritQuery = `&${loaderContext.resourceQuery.slice(1)}`
    // make sure to only pass id when necessary so that we don't inject
    // duplicate tags when multiple components import the same css file
    const idQuery = style.scoped ? `&id=${id}` : ``
    const query = `?vue&type=style&index=${i}${idQuery}${attrsQuery}${inheritQuery}`
    return stringifyRequest(src + query)
  }
 
  function genCSSModulesCode (style, request, i) {
    hasCSSModules = true
 
    const moduleName = style.module === true ? '$style' : style.module
    if (cssModuleNames.has(moduleName)) {
      loaderContext.emitError(`CSS module name ${moduleName} is not unique!`)
    }
    cssModuleNames.set(moduleName, true)
 
    // `(vue-)style-loader` exports the name-to-hash map directly
    // `css-loader` exports it in `.locals`
    const locals = `(style${i}.locals || style${i})`
    const name = JSON.stringify(moduleName)
 
    if (!needsHotReload) {
      styleInjectionCode += `this[${name}] = ${locals}\n`
    } else {
      styleInjectionCode += `
        cssModules[${name}] = ${locals}
        Object.defineProperty(this, ${name}, {
          configurable: true,
          get: function () {
            return cssModules[${name}]
          }
        })
      `
      cssModulesHotReloadCode += `
        module.hot && module.hot.accept([${request}], function () {
          var oldLocals = cssModules[${name}]
          if (oldLocals) {
            var newLocals = require(${request})
            if (JSON.stringify(newLocals) !== JSON.stringify(oldLocals)) {
              cssModules[${name}] = newLocals
              require(${hotReloadAPIPath}).rerender("${id}")
            }
          }
        })
      `
    }
  }
 
  // empty styles: with no `src` specified or only contains whitespaces
  const isNotEmptyStyle = style => style.src || nonWhitespaceRE.test(style.content)
  // explicit injection is needed in SSR (for critical CSS collection)
  // or in Shadow Mode (for injection into shadow root)
  // In these modes, vue-style-loader exports objects with the __inject__
  // method; otherwise we simply import the styles.
  if (!needsExplicitInjection) {
    styles.forEach((style, i) => {
      // do not generate requests for empty styles
      if (isNotEmptyStyle(style)) {
        const request = genStyleRequest(style, i)
        styleImportsCode += `import style${i} from ${request}\n`
        if (style.module) genCSSModulesCode(style, request, i)
      }
    })
  } else { // fixed by xxxxxx (app-plus v3 view style and app-nvue style)
    if (platform === 'app-vue') {
      styles.forEach((style, i) => {
        if (isNotEmptyStyle(style)) {
          const request = genStyleRequest(style, i)
          styleInjectionCode += (
            `var style${i} = require(${request})\n` +
            `if (style${i}.__inject__) style${i}.__inject__(context)\n`
          )
          if (style.module) genCSSModulesCode(style, request, i)
        }
      })
    } else {
      styleInjectionCode = `if(!this.options.style){
          this.options.style = {}
      }
      if(Vue.prototype.__merge_style && Vue.prototype.__$appStyle__){
        Vue.prototype.__merge_style(Vue.prototype.__$appStyle__, this.options.style)
      }
      `
      styles.forEach((style, i) => {
        if (isNotEmptyStyle(style)) {
          const request = genStyleRequest(style, i)
          styleInjectionCode += (
            `if(Vue.prototype.__merge_style){
                Vue.prototype.__merge_style(require(${request}).default, this.options.style)
            }else{
                Object.assign(this.options.style,require(${request}).default)
            }\n`//fixed by xxxxxx 简单处理,与 weex-vue-loader 保持一致
            //`var style${i} = require(${request})\n` +
            //`if (style${i}.__inject__) style${i}.__inject__(context)\n`
          )
          if (style.module) genCSSModulesCode(style, request, i)
        }
      })
    }
  }
 
  if (!needsExplicitInjection && !hasCSSModules) {
    return styleImportsCode
  }
 
  return `
${styleImportsCode}
${hasCSSModules && needsHotReload ? `var cssModules = {}` : ``}
${needsHotReload ? `var disposed = false` : ``}
 
function injectStyles (context) {
  ${needsHotReload ? `if (disposed) return` : ``}
  ${styleInjectionCode}
}
 
${needsHotReload ? `
  module.hot && module.hot.dispose(function (data) {
    disposed = true
  })
` : ``}
 
${cssModulesHotReloadCode}
  `.trim()
}