一个分包使用其他分包的自定义组件时,由于其他分包还未下载或注入,其他分包的组件处于不可用的状态。通过为其他分包的自定义组件设置 占位组件,我们可以先渲染占位组件作为替代,在分包下载完成后再进行替换 假如我们有两个分包A和B,如果A分包中页面需要引入B包中的组定义组件,我们可以在页面对应的配置文件pages.json文件中添加componentPlaceholder属性,但是对于A分包中的组件需要引入B包中的自定义组件,由于uniapp没有针对自定义组件创建配置文件,我们需要自定义webpack插件对编译完成的资源进行处理,注入componentPlaceholder属性,我们创建一个webpack插件,placeholder-plugin.js,代码如下:
const fs = require('fs')
const chalk = require('chalk')
const process = require('process')
const pluginId = 'component-placeholder-plugin'
const validateOptions = require('schema-utils')
const schemaPlaceholderPluginOption = require('./schemaPlaceholderPluginOption.json')
const schemaPlaceholderOptionChild = require('./schemaPlaceholderOptionChild.json')
class ComponentPlaceholder {
constructor(option) {
validateOptions(schemaPlaceholderPluginOption, option, '插件名称:' + pluginId)
this.option = option
}
apply(compiler) {
compiler.hooks.afterEmit.tapAsync(pluginId, (compiler, cb) => {
this.option.fileList.forEach((item) => {
try {
validateOptions(schemaPlaceholderOptionChild, item, '插件名称:' + pluginId)
} catch (e) {
console.error(chalk.red('插件名称:' + pluginId + '中的fileList字段中的子项校验失败,请检查'))
process.exit()
}
let exist = fs.existsSync(item.filePath)
if (exist) {
let data = this.getFileContent(item)
this.setFileContent(item.filePath, data)
}
})
cb()
})
}
getFileContent(item) {
let str = fs.readFileSync(item.filePath)
let data = JSON.parse(str)
if (data.componentPlaceholder) {
data.componentPlaceholder = { ...data.componentPlaceholder, ...item.componentPlaceholder }
} else {
data.componentPlaceholder = item.componentPlaceholder
}
return JSON.stringify(data)
}
setFileContent(filePath, data) {
try {
fs.writeFileSync(filePath, data)
} catch (e) {
console.log('目标文件:' + filePath + '更改失败')
}
}
}
module.exports = ComponentPlaceholder
vue.config.js中我们引入placeholder-plugin.js
const placeholderConfig = require('./loaders/placeholderConfig.js')
//
registerComponentPlaceholderPlugin(config, 'dist/dev/')
function registerComponentPlaceholderPlugin(config, targetDir) {
// 注意这里config是chainWebpack的返回的config, targetDir: 开发环境的目录,生产环境改成dist/build
const params = placeholderConfig('../' + targetDir)
config.plugin('component-placeholder-plugin').use(new ComponentPlaceholderPlugin({
fileList: [{
filePath: path.resolve(__dirname, targetDir + '/pages/list/index.json'),
componentPlaceholder: {
'area-com': 'view'
}
}]
})
)
}