const fs = require('fs')
|
const fsExtra = require('fs-extra')
|
const path = require('path')
|
const merge = require('merge')
|
|
const {
|
normalizePath,
|
getFlexDirection
|
} = require('@dcloudio/uni-cli-shared')
|
const {
|
getTheme,
|
hasTheme,
|
parseTheme
|
} = require('@dcloudio/uni-cli-shared/lib/theme')
|
const {
|
compileI18nJsonStr
|
} = require('@dcloudio/uni-i18n')
|
const {
|
initI18nOptions
|
} = require('@dcloudio/uni-cli-shared/lib/i18n')
|
const {
|
hasOwn,
|
parseStyle
|
} = require('../../util')
|
|
const wxPageOrientationMapping = {
|
auto: [
|
'portrait-primary',
|
'portrait-secondary',
|
'landscape-primary',
|
'landscape-secondary'
|
],
|
portrait: ['portrait-primary', 'portrait-secondary'],
|
landscape: ['landscape-primary', 'landscape-secondary']
|
}
|
|
function parseConfig (appJson) {
|
return {
|
name: 'app-config.js',
|
content: `__registerConfig(${JSON.stringify(appJson)});`
|
}
|
}
|
|
const _toString = Object.prototype.toString
|
|
function isPlainObject (obj) {
|
return _toString.call(obj) === '[object Object]'
|
}
|
|
function normalizeNetworkTimeout (appJson) {
|
if (!isPlainObject(appJson.networkTimeout)) {
|
appJson.networkTimeout = {
|
request: 60000,
|
connectSocket: 60000,
|
uploadFile: 60000,
|
downloadFile: 60000
|
}
|
} else {
|
if (typeof appJson.networkTimeout.request === 'undefined') {
|
appJson.networkTimeout.request = 60000
|
}
|
if (typeof appJson.networkTimeout.connectSocket === 'undefined') {
|
appJson.networkTimeout.connectSocket = 60000
|
}
|
if (typeof appJson.networkTimeout.uploadFile === 'undefined') {
|
appJson.networkTimeout.uploadFile = 60000
|
}
|
if (typeof appJson.networkTimeout.downloadFile === 'undefined') {
|
appJson.networkTimeout.downloadFile = 60000
|
}
|
}
|
}
|
|
function updateFileFlag (appJson) {
|
// 已经不再根据文件识别,理论可废弃此处的逻辑
|
if (process.env.UNI_USING_V3 || process.env.UNI_USING_V3_NATIVE) {
|
return
|
}
|
const nvueCompilerFilePath = path.resolve(
|
process.env.UNI_OUTPUT_DIR,
|
'__uniappnvuecompiler.js'
|
)
|
const nvueCompilerExists = fs.existsSync(nvueCompilerFilePath)
|
|
if (appJson.nvueCompiler === 'uni-app') {
|
if (!nvueCompilerExists) {
|
fsExtra.outputFile(nvueCompilerFilePath, '')
|
}
|
} else {
|
if (nvueCompilerExists) {
|
fs.unlinkSync(nvueCompilerFilePath)
|
}
|
}
|
|
const rendererFilePath = path.resolve(
|
process.env.UNI_OUTPUT_DIR,
|
'__uniapprenderer.js'
|
)
|
const rendererExists = fs.existsSync(rendererFilePath)
|
|
if (appJson.renderer === 'native') {
|
if (!rendererExists) {
|
fsExtra.outputFile(rendererFilePath, '')
|
}
|
} else {
|
if (rendererExists) {
|
fs.unlinkSync(rendererFilePath)
|
}
|
}
|
}
|
|
function _initTheme (appJson, userManifestJson) {
|
const manifestJson = userManifestJson[process.env.UNI_PLATFORM] || {}
|
appJson.darkmode = manifestJson.darkmode || false
|
const themeLocation = manifestJson.themeLocation || 'theme.json'
|
if (themeLocation && hasTheme(themeLocation)) {
|
appJson.themeConfig = getTheme()
|
}
|
return appJson
|
}
|
|
module.exports = function (pagesJson, userManifestJson, isAppView) {
|
const {
|
app
|
} = require('../mp')(pagesJson, userManifestJson)
|
|
const manifest = {
|
name: 'manifest'
|
}
|
|
const appJson = app.content
|
|
_initTheme(appJson, userManifestJson)
|
|
const parsedThemeAppJsonWindow = parseTheme(appJson.window)
|
|
const navigationBarTextStyle =
|
(pagesJson.pages[0].style && pagesJson.pages[0].style.navigationBarTextStyle) ||
|
(pagesJson.globalStyle && pagesJson.globalStyle.navigationBarTextStyle) ||
|
'black'
|
const navigationBarBackgroundColor = (parsedThemeAppJsonWindow && parsedThemeAppJsonWindow.navigationBarBackgroundColor) || '#000000'
|
|
const TABBAR_HEIGHT = 50
|
|
let manifestJson = JSON.parse(
|
fs.readFileSync(path.resolve(__dirname, './manifest.json'), 'utf8')
|
)
|
|
// 状态栏
|
manifestJson.plus.statusbar = {
|
immersed: 'supportedDevice',
|
style: navigationBarTextStyle === 'white' ? 'light' : 'dark',
|
background: navigationBarBackgroundColor
|
}
|
// 用户配置覆盖默认配置
|
manifestJson = merge.recursive(
|
true,
|
manifestJson, {
|
id: userManifestJson.appid || '',
|
name: userManifestJson.name || '',
|
description: userManifestJson.description || '',
|
version: {
|
name: userManifestJson.versionName,
|
code: userManifestJson.versionCode
|
},
|
locale: userManifestJson.locale,
|
uniStatistics: userManifestJson.uniStatistics
|
}, {
|
plus: userManifestJson['app-plus']
|
}
|
)
|
|
initUniStatistics(manifestJson)
|
|
const splashscreenOptions =
|
userManifestJson['app-plus'] && userManifestJson['app-plus'].splashscreen
|
|
const hasAlwaysShowBeforeRender =
|
splashscreenOptions &&
|
hasOwn(splashscreenOptions, 'alwaysShowBeforeRender')
|
|
// 转换为老版本配置
|
if (manifestJson.plus.modules) {
|
manifestJson.permissions = manifestJson.plus.modules
|
delete manifestJson.plus.modules
|
}
|
|
const distribute = manifestJson.plus.distribute
|
|
if (distribute) {
|
if (distribute.android) {
|
manifestJson.plus.distribute.google = distribute.android
|
delete manifestJson.plus.distribute.android
|
}
|
if (distribute.ios) {
|
manifestJson.plus.distribute.apple = distribute.ios
|
delete manifestJson.plus.distribute.ios
|
}
|
if (distribute.sdkConfigs) {
|
manifestJson.plus.distribute.plugins = distribute.sdkConfigs
|
delete manifestJson.plus.distribute.sdkConfigs
|
}
|
if (manifestJson.plus.darkmode) {
|
if (!(distribute.google || (distribute.google = {})).defaultNightMode) {
|
distribute.google.defaultNightMode = 'auto'
|
}
|
|
if (!(distribute.apple || (distribute.apple = {})).UIUserInterfaceStyle) {
|
distribute.apple.UIUserInterfaceStyle = 'Automatic'
|
}
|
}
|
}
|
|
// 屏幕启动方向
|
if (manifestJson.plus.screenOrientation) {
|
// app平台优先使用 manifest 配置
|
manifestJson.screenOrientation = manifestJson.plus.screenOrientation
|
delete manifestJson.plus.screenOrientation
|
} else if (appJson.window && appJson.window.pageOrientation) {
|
// 兼容微信小程序
|
const pageOrientationValue =
|
wxPageOrientationMapping[appJson.window.pageOrientation]
|
if (pageOrientationValue) {
|
manifestJson.screenOrientation = pageOrientationValue
|
}
|
}
|
|
// 全屏配置
|
manifestJson.fullscreen = manifestJson.plus.fullscreen
|
|
// 地图坐标系
|
if (manifestJson.permissions && manifestJson.permissions.Maps) {
|
manifestJson.permissions.Maps.coordType = 'gcj02'
|
}
|
|
if (!manifestJson.permissions) {
|
manifestJson.permissions = {}
|
}
|
|
const nvuePages = process.env.UNI_USING_V3_NATIVE
|
? pagesJson.pages
|
: pagesJson.nvue && pagesJson.nvue.pages
|
|
if (nvuePages && nvuePages.length) {
|
const pages = {}
|
nvuePages.forEach(({
|
path,
|
style
|
}) => {
|
pages[path] = {
|
window: parseStyle(style),
|
nvue: true
|
}
|
})
|
|
appJson.nvue = {
|
pages
|
}
|
|
if (process.env.UNI_USING_V3_NATIVE) {
|
appJson.nvue.entryPagePath = nvuePages[0]
|
} else if (pagesJson.nvue.entryPagePath) {
|
appJson.nvue.entryPagePath = pagesJson.nvue.entryPagePath
|
}
|
|
// nvue 权限
|
manifestJson.permissions.UniNView = {
|
description: 'UniNView原生渲染'
|
}
|
} else if (process.env.UNI_USING_V8) {
|
// nvue 权限
|
manifestJson.permissions.UniNView = {
|
description: 'UniNView原生渲染'
|
}
|
}
|
|
// 启动页面配置
|
if (process.env.NODE_ENV === 'development') {
|
const condition = pagesJson.condition
|
if (condition && Array.isArray(condition.list) && condition.list.length) {
|
const list = condition.list
|
let current = parseInt(condition.current) || 0
|
if (current < 0) {
|
current = 0
|
}
|
if (current >= list.length) {
|
current = 0
|
}
|
manifestJson.plus.arguments = JSON.stringify(list[current])
|
}
|
}
|
|
// 允许内联播放视频
|
manifestJson.plus.allowsInlineMediaPlayback = true
|
|
const addRenderAlways = function () {
|
// "render": "always"
|
if (!manifestJson.plus.launchwebview) {
|
manifestJson.plus.launchwebview = {
|
render: 'always'
|
}
|
} else if (!manifestJson.plus.launchwebview.render) {
|
manifestJson.plus.launchwebview.render = 'always'
|
}
|
}
|
|
if (appJson.tabBar && appJson.tabBar.list && appJson.tabBar.list.length) {
|
// 安全区配置 仅包含 tabBar 的时候才配置
|
if (!manifestJson.plus.safearea) {
|
manifestJson.plus.safearea = {
|
background: parseTheme(appJson.tabBar).backgroundColor || '#FFFFFF',
|
bottom: {
|
offset: 'auto'
|
}
|
}
|
}
|
if (!process.env.UNI_USING_COMPONENTS) {
|
// 非自定义组件模式下,仍旧添加 render always
|
addRenderAlways()
|
}
|
} else {
|
addRenderAlways()
|
}
|
|
let flexDir = false
|
|
if (process.env.UNI_USING_NVUE_COMPILER) {
|
appJson.nvueCompiler = 'uni-app'
|
flexDir = getFlexDirection(manifestJson.plus)
|
} else {
|
appJson.nvueCompiler = 'weex'
|
}
|
|
appJson.nvueStyleCompiler = process.env.UNI_USING_NVUE_STYLE_COMPILER
|
? 'uni-app'
|
: 'weex'
|
|
if (manifestJson.plus.renderer === 'native') {
|
appJson.renderer = 'native'
|
} else {
|
appJson.renderer = 'auto'
|
}
|
|
updateFileFlag(appJson)
|
|
appJson.splashscreen = {
|
alwaysShowBeforeRender: false, // 是否启用白屏检测 关闭 splash
|
autoclose: false // 是否 uni-app 框架关闭 splash
|
}
|
|
// 强制白屏检测
|
if (manifestJson.plus.splashscreen) {
|
if (
|
!hasAlwaysShowBeforeRender &&
|
manifestJson.plus.splashscreen.autoclose === false
|
) {
|
// 兼容旧版本仅配置了 autoclose 为 false
|
manifestJson.plus.splashscreen.alwaysShowBeforeRender = false
|
}
|
if (manifestJson.plus.splashscreen.alwaysShowBeforeRender) {
|
// 白屏检测
|
if (!manifestJson.plus.splashscreen.target) {
|
manifestJson.plus.splashscreen.target = 'id:1'
|
}
|
manifestJson.plus.splashscreen.autoclose = true
|
manifestJson.plus.splashscreen.delay = 0
|
|
appJson.splashscreen.alwaysShowBeforeRender = true
|
} else {
|
// 不启用白屏检测
|
delete manifestJson.plus.splashscreen.target
|
|
if (manifestJson.plus.splashscreen.autoclose) {
|
// 启用 uni-app 框架关闭 splash
|
manifestJson.plus.splashscreen.autoclose = false // 原 5+ autoclose 改为 false
|
appJson.splashscreen.autoclose = true
|
}
|
}
|
delete manifestJson.plus.splashscreen.alwaysShowBeforeRender
|
}
|
|
appJson.appname = manifestJson.name
|
|
if (!manifestJson.plus.distribute) {
|
manifestJson.plus.distribute = {
|
plugins: {}
|
}
|
}
|
|
if (!manifestJson.plus.distribute.plugins) {
|
manifestJson.plus.distribute.plugins = {}
|
}
|
|
// 录音支持 mp3
|
manifestJson.plus.distribute.plugins.audio = {
|
mp3: {
|
description: 'Android平台录音支持MP3格式文件'
|
}
|
}
|
|
// 有效值为 close,none
|
if (!['close', 'none'].includes(manifestJson.plus.popGesture + '')) {
|
manifestJson.plus.popGesture = 'close'
|
}
|
|
// 检查原生混淆选项
|
const confusion = manifestJson.plus.confusion
|
if (confusion && confusion.resources) {
|
const resources = {}
|
const nvuePages = (appJson.nvue && appJson.nvue.pages) || {}
|
for (const key in confusion.resources) {
|
if (path.extname(key) === '.js') {
|
// 支持 js 混淆,过滤掉
|
// 静态 js 文件
|
if (
|
key.indexOf('hybrid/html') === 0 ||
|
key.indexOf('static/') === 0 ||
|
key.indexOf('/static/') !== -1
|
) {
|
resources[key] = confusion.resources[key]
|
}
|
continue
|
}
|
if (!/\.nvue$/.test(key)) {
|
throw new Error(`原生混淆仅支持 nvue 页面,错误的页面路径:${key}`)
|
} else {
|
resources[key.replace(/\.nvue$/, '.js')] = confusion.resources[key]
|
}
|
if (
|
!Object.keys(nvuePages).find(path => {
|
const subNVues = nvuePages[path].window.subNVues || []
|
// TODO
|
return (
|
path.replace(/\.html$/, '.nvue') === key ||
|
path.replace(/\.html$/, '.nvue') + '.nvue' === key ||
|
subNVues.find(({
|
path
|
}) => path === key.replace(/\.nvue$/, ''))
|
)
|
}) &&
|
!pagesJson.pages.find(({
|
style = {}
|
}) => {
|
style = Object.assign(style, style['app-plus'])
|
const subNVues = style.subNVues || []
|
return subNVues.find(
|
({
|
path
|
}) => path === key.replace(/\.nvue$/, '')
|
)
|
})
|
) {
|
throw new Error(`原生混淆页面未在项目内使用,错误的页面路径:${key}`)
|
}
|
}
|
confusion.resources = resources
|
}
|
|
// uni-app
|
const uniApp = require('../../../package.json')['uni-app']
|
manifestJson.plus['uni-app'] = uniApp
|
// 控制页类型
|
const control =
|
process.env.UNI_USING_V3 || process.env.UNI_USING_V3_NATIVE
|
? 'uni-v3'
|
: process.env.UNI_USING_V8
|
? 'v8'
|
: 'webview'
|
|
manifestJson.plus['uni-app'].control = control
|
manifestJson.plus['uni-app'].nvueCompiler = appJson.nvueCompiler
|
// v3 + native 时强制 auto
|
manifestJson.plus['uni-app'].renderer = process.env.UNI_USING_V3_NATIVE
|
? 'auto'
|
: appJson.renderer
|
|
if (flexDir) {
|
manifestJson.plus['uni-app'].nvue = {
|
'flex-direction': flexDir
|
}
|
}
|
|
// 检查 webview 版本 || 下载 X5 后启动
|
const plusWebview = manifestJson.plus.webView
|
if (plusWebview) {
|
manifestJson.plus['uni-app'].webView = plusWebview
|
delete manifestJson.plus.webView
|
}
|
|
// 记录编译器版本号
|
appJson.compilerVersion = uniApp.compilerVersion
|
|
if (process.env.UNI_USING_V8) {
|
let entryPagePath = appJson.pages[0]
|
let conditionPagePath = false
|
if (manifestJson.plus.arguments) {
|
try {
|
const args = JSON.parse(manifestJson.plus.arguments)
|
if (args && (args.path || args.pathName)) {
|
entryPagePath = conditionPagePath = args.path || args.pathName
|
}
|
} catch (e) { }
|
}
|
|
let isNVueEntryPage = appJson.nvue && appJson.nvue.entryPagePath
|
conditionPagePath =
|
process.env.UNI_CLI_LAUNCH_PAGE_PATH || conditionPagePath
|
if (conditionPagePath && appJson.nvue) {
|
isNVueEntryPage = `${conditionPagePath}.html` in appJson.nvue.pages
|
}
|
manifestJson.plus.useragent.value = 'uni-app'
|
manifestJson.launch_path = '__uniappview.html'
|
Object.assign(manifestJson.plus.launchwebview, {
|
id: '1',
|
kernel: 'WKWebview',
|
'uni-app': 'auto'
|
})
|
if (process.env.UNI_USING_NATIVE) {
|
appJson.entryPagePath = appJson.nvue.entryPagePath
|
// networkTimeout
|
normalizeNetworkTimeout(appJson)
|
appJson.page = Object.create(null)
|
appJson.pages = Object.keys(appJson.nvue.pages).map(pagePath => {
|
const newPagePath = pagePath.replace('.html', '')
|
appJson.page[newPagePath] = {
|
window: appJson.nvue.pages[pagePath].window,
|
nvue: true
|
}
|
return newPagePath
|
})
|
|
delete appJson.nvue
|
|
delete manifestJson.plus.launchwebview.kernel
|
manifestJson.launch_path = ''
|
Object.assign(manifestJson.plus.launchwebview, {
|
uniNView: {
|
path: appJson.entryPagePath
|
}
|
})
|
} else if (isNVueEntryPage) {
|
// 非纯 nvue 项目首页为 nvue 页面
|
manifestJson.plus.launchwebview.id = '2'
|
manifestJson.plus.launchwebview.render = 'always'
|
}
|
// 带 tab
|
if (
|
pagesJson.tabBar &&
|
pagesJson.tabBar.list &&
|
pagesJson.tabBar.list.length
|
) {
|
const tabBar = (manifestJson.plus.tabBar = Object.assign({},
|
parseTheme(pagesJson.tabBar)
|
))
|
const borderStyles = {
|
black: 'rgba(0,0,0,0.4)',
|
white: 'rgba(255,255,255,0.4)'
|
}
|
let borderStyle = tabBar.borderStyle
|
if (!borderStyle) {
|
borderStyle = 'black'
|
}
|
if (borderStyle in borderStyles) {
|
tabBar.borderStyle = borderStyles[borderStyle]
|
}
|
if (!tabBar.selectedColor) {
|
tabBar.selectedColor = '#0062cc'
|
}
|
tabBar.height = `${parseFloat(tabBar.height) || TABBAR_HEIGHT}px`
|
// 非纯 nvue 项目首页为 nvue 页面
|
if (!process.env.UNI_USING_NATIVE && isNVueEntryPage) {
|
manifestJson.plus.launchwebview.id = '2'
|
} else {
|
// 首页是 tabBar 页面
|
const item = tabBar.list.find(
|
page =>
|
page.pagePath ===
|
(process.env.UNI_USING_NATIVE
|
? appJson.entryPagePath
|
: entryPagePath)
|
)
|
if (item) {
|
tabBar.child = ['lauchwebview']
|
tabBar.selected = tabBar.list.indexOf(item)
|
}
|
}
|
|
const i18nOptions = initI18nOptions(
|
process.env.UNI_PLATFORM,
|
process.env.UNI_INPUT_DIR,
|
true,
|
true
|
)
|
if (i18nOptions) {
|
manifestJson = JSON.parse(
|
compileI18nJsonStr(JSON.stringify(manifestJson), i18nOptions)
|
)
|
manifestJson.fallbackLocale = i18nOptions.locale
|
}
|
}
|
}
|
|
if (!process.env.UNI_USING_COMPONENTS) {
|
manifestJson.plus.launchwebview.kernel = 'UIWebview'
|
}
|
|
manifest.content = manifestJson
|
|
const subPackages = []
|
// 分包合并
|
if (appJson.subPackages && appJson.subPackages.length) {
|
appJson.subPackages.forEach(subPackage => {
|
if (subPackage.pages && subPackage.pages.length) {
|
subPackage.pages.forEach(page => {
|
appJson.pages.push(normalizePath(path.join(subPackage.root, page)))
|
})
|
subPackages.push({
|
root: subPackage.root
|
})
|
}
|
})
|
}
|
|
delete appJson.subPackages
|
|
// TODO 处理纯原生
|
if (process.env.UNI_USING_NATIVE) {
|
manifest.name = 'manifest.json'
|
manifest.content = JSON.stringify(manifest.content)
|
return [manifest, parseConfig(appJson)]
|
}
|
|
if (process.env.UNI_USING_V3 || process.env.UNI_USING_V3_NATIVE) {
|
if (process.env.UNI_USING_V3 && process.env.UNI_OPT_SUBPACKAGES) {
|
appJson.subPackages = subPackages
|
}
|
return require('./index.v3')(
|
appJson,
|
manifestJson, {
|
manifest,
|
pagesJson,
|
normalizeNetworkTimeout
|
},
|
isAppView
|
)
|
}
|
return [app, manifest]
|
}
|
|
function initUniStatistics (manifestJson) {
|
// 根节点配置了统计
|
if (manifestJson.uniStatistics) {
|
manifestJson.plus.uniStatistics = merge.recursive(
|
true,
|
manifestJson.uniStatistics,
|
manifestJson.plus.uniStatistics
|
)
|
delete manifestJson.uniStatistics
|
}
|
if (!process.env.UNI_CLOUD_PROVIDER) {
|
return
|
}
|
let spaces = []
|
try {
|
spaces = JSON.parse(process.env.UNI_CLOUD_PROVIDER)
|
} catch (e) { }
|
if (!Array.isArray(spaces) || !spaces.length) {
|
return
|
}
|
const space = spaces[0]
|
if (!space) {
|
return
|
}
|
const uniStatistics = manifestJson.plus && manifestJson.plus.uniStatistics
|
if (!uniStatistics) {
|
return
|
}
|
if (uniStatistics.version === 2 || uniStatistics.version === '2') {
|
if (uniStatistics.uniCloud && uniStatistics.uniCloud.spaceId) {
|
return
|
}
|
uniStatistics.uniCloud = {
|
provider: space.provider,
|
spaceId: space.spaceId,
|
clientSecret: space.clientSecret,
|
endpoint: space.endpoint
|
}
|
}
|
}
|