@mpxjs/webpack-plugin
Version:
mpx compile core
160 lines (138 loc) • 5.41 kB
JavaScript
const path = require('path')
const postcss = require('postcss')
const loadPostcssConfig = require('./load-postcss-config')
const { MPX_ROOT_VIEW, MPX_DISABLE_EXTRACTOR_CACHE } = require('../utils/const')
const rpx = require('./plugins/rpx')
const vw = require('./plugins/vw')
const scopeId = require('./plugins/scope-id')
const transSpecial = require('./plugins/trans-special')
const cssArrayList = require('./plugins/css-array-list')
const { matchCondition } = require('../utils/match-condition')
const parseRequest = require('../utils/parse-request')
const isReact = require('../utils/env').isReact
const RecordRuntimeInfoDependency = require('../dependencies/RecordRuntimeInfoDependency')
module.exports = function (css, map) {
this.cacheable()
const cb = this.async()
const { resourcePath, queryObj } = parseRequest(this.resource)
const mpx = this.getMpx()
const mpxStyleOptions = (queryObj.mpxStyleOptions && JSON.parse(queryObj.mpxStyleOptions)) || {}
const id = queryObj.moduleId || mpxStyleOptions.mid || mpx.getModuleId(resourcePath)
const appInfo = mpx.appInfo
const defs = mpx.defs
const mode = mpx.mode
const isApp = resourcePath === appInfo.resourcePath
const transRpxRulesRaw = mpx.transRpxRules
const transRpxRules = transRpxRulesRaw ? (Array.isArray(transRpxRulesRaw) ? transRpxRulesRaw : [transRpxRulesRaw]) : []
const runtimeCompile = queryObj.isDynamic
const index = queryObj.index || 0
const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
const transRpxFn = mpx.webConfig.transRpxFn
const testResolveRange = (include = () => true, exclude) => {
return matchCondition(this.resourcePath, { include, exclude })
}
const inlineConfig = Object.assign({}, mpx.postcssInlineConfig, { defs, inlineConfigFile: path.join(mpx.projectRoot, 'vue.config.js') })
loadPostcssConfig(this, inlineConfig).then(config => {
const plugins = [] // init with trim plugin
const postPlugins = []
const options = Object.assign(
{
to: this.resourcePath,
from: this.resourcePath,
map: false
},
config.options
)
// ali平台下处理scoped和host选择器
if (mode === 'ali' || mode === 'web') {
if (queryObj.scoped || mpxStyleOptions.scoped) {
plugins.push(scopeId({ id }))
}
plugins.push(transSpecial({ id }))
}
if (isReact(mode)) {
plugins.push(transSpecial({ id }))
}
// plugins.push(pluginCondStrip({
// defs
// }))
for (const item of transRpxRules) {
const {
mode,
comment,
include,
exclude,
designWidth
} = item || {}
if (testResolveRange(include, exclude)) {
// 对同一个资源一旦匹配到,推入一个rpx插件后就不再继续推了
plugins.push(rpx({ mode, comment, designWidth }))
break
}
}
// source map
if (this.sourceMap && !options.map) {
options.map = {
inline: false,
annotation: false,
prev: map
}
}
const cssList = []
if (runtimeCompile) {
postPlugins.push(cssArrayList(cssList))
}
if (mpx.mode === 'web') {
postPlugins.push(vw({ transRpxFn }))
}
const finalPlugins = config.prePlugins.concat(plugins, config.plugins, postPlugins)
return postcss(finalPlugins)
.process(css, options)
.then(result => {
// ali环境添加全局样式抹平root差异
if ((mode === 'ali' || mode === 'web') && isApp) {
result.css += `\n.${MPX_ROOT_VIEW} { display: initial }\npage { line-height: normal }`
}
for (const warning of result.warnings()) {
this.emitWarning(warning)
}
// todo 后续考虑直接使用postcss-loader来处理postcss
for (const message of result.messages) {
// eslint-disable-next-line default-case
switch (message.type) {
case 'dependency':
this.addDependency(message.file)
break
case 'build-dependency':
this.addBuildDependency(message.file)
break
case 'missing-dependency':
this.addMissingDependency(message.file)
break
case 'context-dependency':
this.addContextDependency(message.file)
break
case 'dir-dependency':
this.addContextDependency(message.dir)
break
case 'asset':
if (message.content && message.file) {
this.emitFile(message.file, message.content, message.sourceMap, message.info)
}
}
}
if (runtimeCompile) {
// 包含了运行时组件的 style 模块必须每次都创建(但并不是每次都需要build),用于收集组件节点信息,传递信息以禁用父级extractor的缓存
this.emitFile(MPX_DISABLE_EXTRACTOR_CACHE, '', undefined, { skipEmit: true })
this._module.addPresentationalDependency(new RecordRuntimeInfoDependency(packageName, resourcePath, { type: 'style', info: cssList, index }))
return cb(null, '')
}
const map = result.map && result.map.toJSON()
cb(null, result.css, map)
return null // silence bluebird warning
})
}).catch(e => {
console.error(e)
cb(e)
})
}