‘liusuyi’
2023-08-09 161b9318e345c8a0c9cdc133b33a1c759495f323
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
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,
  isProduction
) {
  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 not src importing so that we don't inject
    // duplicate tags when multiple components import the same css file
    const idQuery = !style.src || style.scoped ? `&id=${id}` : ``
    const prodQuery = isProduction ? `&prod` : ``
    const query = `?vue&type=style&index=${i}${idQuery}${prodQuery}${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 {
    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)
      }
    })
  }
 
  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()
}