Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix: 输出 web externalClasses功能修复 #1661

Merged
merged 16 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions packages/webpack-plugin/lib/style-compiler/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ module.exports = function (css, map) {
const cb = this.async()
const { resourcePath, queryObj } = parseRequest(this.resource)
const mpx = this.getMpx()
const id = queryObj.moduleId || queryObj.mid || '_' + mpx.pathHash(resourcePath)
const mpxStyleOptions = (queryObj.mpxStyleOptions && JSON.parse(queryObj.mpxStyleOptions)) || {}
const id = queryObj.moduleId || mpxStyleOptions.mid || '_' + mpx.pathHash(resourcePath)
const appInfo = mpx.appInfo
const defs = mpx.defs
const mode = mpx.mode
Expand Down Expand Up @@ -46,14 +47,14 @@ module.exports = function (css, map) {
config.options
)
// ali平台下处理scoped和host选择器
if (mode === 'ali') {
if (queryObj.scoped) {
if (mode === 'ali' || mode === 'web') {
if (queryObj.scoped || mpxStyleOptions.scoped) {
plugins.push(scopeId({ id }))
}
plugins.push(transSpecial({ id }))
}

if (mode === 'web' || isReact(mode)) {
if (isReact(mode)) {
plugins.push(transSpecial({ id }))
}

Expand Down
127 changes: 55 additions & 72 deletions packages/webpack-plugin/lib/template-compiler/compiler.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const JSON5 = require('json5')
const he = require('he')
const config = require('../config')
const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID } = require('../utils/const')
const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID, PARENT_MODULE_ID } = require('../utils/const')
const normalize = require('../utils/normalize')
const { normalizeCondition } = require('../utils/match-condition')
const isValidIdentifierStr = require('../utils/is-valid-identifier-str')
Expand Down Expand Up @@ -2139,96 +2139,76 @@ function isComponentNode (el, options) {
return options.usingComponents.indexOf(el.tag) !== -1 || el.tag === 'component'
}

function processAliExternalClassesHack (el, options) {
function processExternalClasses (el, options) {
const isComponent = isComponentNode(el, options)
// 处理组件externalClass多层传递
const classLikeAttrNames = isComponent ? ['class'].concat(options.externalClasses) : ['class']

classLikeAttrNames.forEach((classLikeAttrName) => {
let classLikeAttrValue = getAndRemoveAttr(el, classLikeAttrName).val
const classLikeAttrValue = getAndRemoveAttr(el, classLikeAttrName).val
if (classLikeAttrValue) {
options.externalClasses.forEach((className) => {
const reg = new RegExp('\\b' + className + '\\b', 'g')
const replacement = dash2hump(className)
classLikeAttrValue = classLikeAttrValue.replace(reg, `{{${replacement}||''}}`)
})
addAttrs(el, [{
name: classLikeAttrName,
value: classLikeAttrValue
}])
if (mode === 'web') {
processWebClass(classLikeAttrName, classLikeAttrValue, el, options)
} else {
processAliClass(classLikeAttrName, classLikeAttrValue, el, options)
}
}
})

if (hasScoped && isComponent) {
options.externalClasses.forEach((className) => {
const externalClass = getAndRemoveAttr(el, className).val
if (externalClass) {
addAttrs(el, [{
name: className,
value: `${externalClass} ${moduleId}`
}])
}
})
}
}

// externalClasses只能模拟静态传递
function processWebExternalClassesHack (el, options) {
const staticClass = getAndRemoveAttr(el, 'class').val
if (staticClass) {
const classNames = staticClass.split(/\s+/)
const replacements = []
options.externalClasses.forEach((className) => {
const index = classNames.indexOf(className)
if (index > -1) {
replacements.push(`$attrs[${stringify(className)}]`)
classNames.splice(index, 1)
}
const needAddModuleId = options.externalClasses.some((className) => {
return el.attrsMap[className] || (mode === 'web' && el.attrsMap[':' + className])
})

if (classNames.length) {
if (needAddModuleId) {
addAttrs(el, [{
name: 'class',
value: classNames.join(' ')
name: PARENT_MODULE_ID,
value: `${moduleId}`
}])
}

if (replacements.length) {
}
function processWebClass (classLikeAttrName, classLikeAttrValue, el, options) {
let classNames = classLikeAttrValue.split(/\s+/)
let hasExternalClass = false
classNames = classNames.map((className) => {
if (options.externalClasses.includes(className)) {
hasExternalClass = true
return `($attrs[${stringify(className)}] || '')`
}
return stringify(className)
})
if (hasExternalClass) {
classNames.push(`($attrs[${stringify(PARENT_MODULE_ID)}] || '')`)
}
if (classLikeAttrName === 'class') {
const dynamicClass = getAndRemoveAttr(el, ':class').val
if (dynamicClass) replacements.push(dynamicClass)

if (dynamicClass) classNames.push(dynamicClass)
addAttrs(el, [{
name: ':class',
value: `[${replacements}]`
value: `[${classNames}]`
}])
} else {
Copy link
Collaborator

@hiyuki hiyuki Oct 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没必要拆这么开,

if(classLikeAttrName === 'class') {
      const dynamicClass = getAndRemoveAttr(el, ':class').val
      if (dynamicClass) classNames.push(dynamicClass)
      addAttrs(el, [{
        name: ':class',
        value: `[${classNames}]`
      }])
} else {
      addAttrs(el, [{
        name: ':' + classLikeAttrName,
        value: `[${classNames}].join(' ')`
      }])
}

addAttrs(el, [{
name: ':' + classLikeAttrName,
value: `[${classNames}].join(' ')`
}])
}
}

// 处理externalClasses多层透传
const isComponent = isComponentNode(el, options)
if (isComponent) {
options.externalClasses.forEach((classLikeAttrName) => {
const classLikeAttrValue = getAndRemoveAttr(el, classLikeAttrName).val
if (classLikeAttrValue) {
const classNames = classLikeAttrValue.split(/\s+/)
const replacements = []
options.externalClasses.forEach((className) => {
const index = classNames.indexOf(className)
if (index > -1) {
replacements.push(`$attrs[${stringify(className)}]`)
classNames.splice(index, 1)
}
})

if (classNames.length) {
replacements.unshift(stringify(classNames.join(' ')))
}

addAttrs(el, [{
name: ':' + classLikeAttrName,
value: `[${replacements}].join(' ')`
}])
}
function processAliClass (classLikeAttrName, classLikeAttrValue, el, options) {
let hasExternalClass = false
options.externalClasses.forEach((className) => {
const reg = new RegExp('\\b' + className + '\\b', 'g')
const replacementClassName = dash2hump(className)
if (classLikeAttrValue.includes(className)) hasExternalClass = true
classLikeAttrValue = classLikeAttrValue.replace(reg, `{{${replacementClassName} || ''}}`)
})
if (hasExternalClass) {
classLikeAttrValue += ` {{${PARENT_MODULE_ID} || ''}}`
}
addAttrs(el, [{
name: classLikeAttrName,
value: classLikeAttrValue
}])
}
}

Expand Down Expand Up @@ -2601,7 +2581,9 @@ function processElement (el, root, options, meta) {
processBuiltInComponents(el, meta)
// 预处理代码维度条件编译
processIfWeb(el)
processWebExternalClassesHack(el, options)
processScoped(el)
// processWebExternalClassesHack(el, options)
processExternalClasses(el, options)
processComponentGenericsWeb(el, options, meta)
return
}
Expand Down Expand Up @@ -2629,7 +2611,8 @@ function processElement (el, root, options, meta) {
}

if (transAli) {
processAliExternalClassesHack(el, options)
// processAliExternalClassesHack(el, options)
processExternalClasses(el, options)
}

processIf(el)
Expand Down
3 changes: 2 additions & 1 deletion packages/webpack-plugin/lib/utils/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ module.exports = {
RESOLVE_IGNORED_ERR: new Error('Resolve ignored!'),
JSON_JS_EXT: '.json.js',
MPX_ROOT_VIEW: 'mpx-root-view', // 根节点类名
MPX_APP_MODULE_ID: 'mpx-app-scope' // app文件moduleId
MPX_APP_MODULE_ID: 'mpx-app-scope', // app文件moduleId
PARENT_MODULE_ID: '__pid'
}
8 changes: 6 additions & 2 deletions packages/webpack-plugin/lib/web/processStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ module.exports = function (styles, options, callback) {
attrs (style) {
const attrs = Object.assign({}, style.attrs)
if (options.autoScope) attrs.scoped = true
// query中包含module字符串会被新版vue-cli中的默认rules当做css-module处理
attrs.mid = options.moduleId
attrs.mpxStyleOptions = JSON.stringify({
scoped: attrs.scoped,
// query中包含module字符串会被新版vue-cli中的默认rules当做css-module处理
mid: options.moduleId
})
delete attrs.scoped
return attrs
}
})
Expand Down
5 changes: 2 additions & 3 deletions packages/webpack-plugin/lib/web/processTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { matchCondition } = require('../utils/match-condition')

module.exports = function (template, {
loaderContext,
// hasScoped,
hasScoped,
hasComment,
isNative,
srcMode,
Expand Down Expand Up @@ -83,8 +83,7 @@ module.exports = function (template, {
defs,
decodeHTMLText,
externalClasses,
// todo 后续输出web也采用mpx的scoped处理
hasScoped: false,
hasScoped,
moduleId,
filePath: resourcePath,
i18n: null,
Expand Down
Loading