diff --git a/build/build.js b/build/build.js index 59d4eead5dca755ad90a0db2b38080b4315d742c..94f46eac1bc4e1c7517e62ad7f7b4436afff9d8e 100644 --- a/build/build.js +++ b/build/build.js @@ -26,7 +26,10 @@ service.run('build', { formats: process.env.UNI_WATCH === 'true' ? 'umd' : 'umd-min', entry: './lib/' + process.env.UNI_PLATFORM + '/main.js' }).then(function () { - generateApiManifest(process.UNI_SERVICE_API_MANIFEST) + generateApiManifest( + JSON.parse(JSON.stringify(process.UNI_SERVICE_API_MANIFEST)), + JSON.parse(JSON.stringify(process.UNI_SERVICE_API_PROTOCOL)) + ) }).catch(err => { error(err) process.exit(1) diff --git a/build/manifest.js b/build/manifest.js index eaa266c364b2b5549c484fc10e02b54dc13fccc2..2c680612b4dd182381101cd45746732e9c08bcbe 100644 --- a/build/manifest.js +++ b/build/manifest.js @@ -3,10 +3,68 @@ const path = require('path') const apis = require('../src/core/helpers/apis') -function parseApiManifestDeps (manifest) { +const AUTO_LOADS = [ + 'upx2px', + 'canIUse', + + 'getSystemInfo', + 'getSystemInfoSync', + + 'navigateTo', + 'redirectTo', + 'switchTab', + 'reLaunch', + 'navigateBack' +] + +const TOAST_DEPS = [ + ['/platforms/h5/components/app/popup/toast.vue', 'Toast'], + ['/platforms/h5/components/app/popup/mixins/toast.js', 'ToastMixin'] +] + +// TODO 暂不考虑 head,tabBar 的动态拆分 +const DEPS = { + 'chooseLocation': [ + ['/platforms/h5/components/system-routes/choose-location/index.vue', 'ChooseLocation'] + ], + 'openLocation': [ + ['/platforms/h5/components/system-routes/open-location/index.vue', 'OpenLocation'] + ], + 'previewImage': [ + ['/platforms/h5/components/system-routes/preview-image/index.vue', 'PreviewImage'] + ], + 'showToast': TOAST_DEPS, + 'hideToast': TOAST_DEPS, + 'showLoading': TOAST_DEPS, + 'hideLoading': TOAST_DEPS, + 'showModal': [ + ['/platforms/h5/components/app/popup/modal.vue', 'Modal'], + ['/platforms/h5/components/app/popup/mixins/modal.js', 'ModalMixin'] + ], + 'showActionSheet': [ + ['/platforms/h5/components/app/popup/actionSheet.vue', 'Modal'], + ['/platforms/h5/components/app/popup/mixins/action-sheet.js', 'ActionSheetMixin'] + ] +} + +// 检查依赖文件是否存在 +Object.keys(DEPS).reduce(function (depFiles, name) { + DEPS[name].forEach(function (dep) { + depFiles.add(dep[0]) + }) + return depFiles +}, new Set()).forEach(file => { + if (!fs.existsSync(path.join(__dirname, '../src', file))) { + console.warn(file + ' 不存在') + process.exit(0) + } +}) + +function parseApiManifestDeps (manifest, protocol) { + // 解析 platform 依赖 Object.keys(manifest).forEach(name => { const deps = manifest[name][1] - if (deps && deps.length) { + if (deps.length) { deps.forEach(dep => { if (manifest[dep[1]]) { dep[0] = manifest[dep[1]][0] @@ -16,11 +74,36 @@ function parseApiManifestDeps (manifest) { }) } }) + // 解析 protocol 依赖 + Object.keys(manifest).forEach(name => { + const deps = manifest[name][1] + if (protocol[name]) { + deps.push([protocol[name], name]) + } else { + console.warn(`${name} 缺少 protocol`) + } + }) + // 追加默认依赖 + Object.keys(DEPS).forEach(name => { + if (manifest[name]) { + manifest[name][1].push(...DEPS[name]) + } else { + console.warn(`缺少 ${name}`) + } + }) + // 设置自动加载标记 + AUTO_LOADS.forEach(name => { + if (manifest[name]) { + manifest[name][2] = true + } else { + console.warn(`缺少 ${name}`) + } + }) } module.exports = { - generateApiManifest (manifest) { - parseApiManifestDeps(manifest) + generateApiManifest (manifest, protocol) { + parseApiManifestDeps(manifest, protocol) const manifestJson = Object.create(null) const todoApis = [] @@ -33,13 +116,14 @@ module.exports = { }) if (todoApis.length) { + console.log('\n') console.warn(`${process.env.UNI_PLATFORM} 平台缺少以下 API 实现`) todoApis.forEach(name => { console.warn(name) }) } - fs.writeFileSync(path.resolve(__dirname, '../packages/uni-h5/manifest.json'), + fs.writeFileSync(path.resolve(__dirname, '../packages/uni-' + process.env.UNI_PLATFORM + '/manifest.json'), JSON.stringify(manifestJson, null, 4) ) } diff --git a/lib/babel-plugin-uni-api/index.js b/lib/babel-plugin-uni-api/index.js index f1bfd768c1af8b6490046c128a115a81e4e494f9..80c49abd411a460e571c30c3aad441edb934c524 100644 --- a/lib/babel-plugin-uni-api/index.js +++ b/lib/babel-plugin-uni-api/index.js @@ -9,12 +9,75 @@ function resolve(...args) { } const srcPath = resolve('../../src/') +const protocolPath = resolve('../../src/core/helpers/protocol') const coreApiPath = resolve('../../src/core/service/api') const platformApiPath = resolve('../../src/platforms/' + process.env.UNI_PLATFORM + '/service/api') const apis = require('../../src/core/helpers/apis') process.UNI_SERVICE_API_MANIFEST = Object.create(null) +process.UNI_SERVICE_API_PROTOCOL = Object.create(null) + +function parseProtocolExport({ + file, + exports +}) { + const filepath = file.replace(srcPath, '') + exports.forEach(exportName => { + if (process.UNI_SERVICE_API_PROTOCOL[exportName]) { + console.warn(`API[${exportName}] 冲突:`) + console.warn(process.UNI_SERVICE_API_PROTOCOL[exportName]) + console.warn(filepath) + } else { + process.UNI_SERVICE_API_PROTOCOL[exportName] = filepath + } + }) +} + +function parseApiExport({ + file, + methods, + exports, + isPlatform +}) { + const deps = [] + methods && methods.forEach(method => { + deps.push(['', method]) + }) + const filepath = file.replace(srcPath, '') + exports.forEach(exportName => { + if (process.UNI_SERVICE_API_MANIFEST[exportName]) { + console.warn('\n') + console.warn(`API[${exportName}] 冲突:`) + console.warn(process.UNI_SERVICE_API_MANIFEST[exportName][0]) + console.warn(filepath) + if (isPlatform) { // 优先使用 platform + process.UNI_SERVICE_API_MANIFEST[exportName] = [filepath, deps] + console.warn(`优先使用` + filepath) + } + } else { + process.UNI_SERVICE_API_MANIFEST[exportName] = [filepath, deps] + } + }) +} + +function parseExports(node, t, file) { + if (t.isFunctionDeclaration(node)) { + return [node.id.name] + } else if ( + t.isVariableDeclaration(node) && + node.declarations.length === 1 + ) { + return [node.declarations[0].id.name] + } else if (Array.isArray(node) && node.length) { + return node.map(specifier => { + return specifier.exported.name + }) + } else { + console.warn('\n') + console.warn(`${file} 解析 export 失败`, node) + } +} module.exports = function({ types: t @@ -26,33 +89,19 @@ module.exports = function({ state.file.opts.file = normalizePath(state.file.opts.filename) state.file.opts.isCore = state.file.opts.file.indexOf(coreApiPath) === 0 state.file.opts.isPlatform = state.file.opts.file.indexOf(platformApiPath) === 0 + state.file.opts.isProtocol = state.file.opts.file.indexOf(protocolPath) === 0 }, exit(path, state) { const { - file, - methods, exports, - isPlatform + isProtocol } = state.file.opts if (exports && exports.length) { - const deps = [] - methods && methods.forEach(method => { - deps.push(['', method]) - }) - const filepath = file.replace(srcPath, '') - exports.forEach(exportName => { - if (process.UNI_SERVICE_API_MANIFEST[exportName]) { - console.warn(`API[${exportName}] 冲突:`) - console.warn(process.UNI_SERVICE_API_MANIFEST[exportName][0]) - console.warn(filepath) - if (isPlatform) { // 优先使用 platform - process.UNI_SERVICE_API_MANIFEST[exportName] = [filepath, deps] - console.warn(`优先使用` + filepath) - } - } else { - process.UNI_SERVICE_API_MANIFEST[exportName] = [filepath, deps] - } - }) + if (isProtocol) { + parseProtocolExport(state.file.opts) + } else { + parseApiExport(state.file.opts) + } } } }, @@ -60,10 +109,14 @@ module.exports = function({ const { file, isCore, - isPlatform + isPlatform, + isProtocol } = state.file.opts - if ((isCore || isPlatform) && t.isFunctionDeclaration(path.node.declaration)) { - (state.file.opts.exports || (state.file.opts.exports = [])).push(path.node.declaration.id.name) + if (isCore || isPlatform || isProtocol) { + const exports = parseExports(path.node.declaration || path.node.specifiers, t, file) + if (Array.isArray(exports)) { + (state.file.opts.exports || (state.file.opts.exports = [])).push(...exports) + } } }, CallExpression(path, state) { diff --git a/src/core/helpers/apis.js b/src/core/helpers/apis.js index dea6cf9bf692f7ef4784296a4276db70b67bda0a..7cdec791090ae72d83f15dd6a71d95f30edb819e 100644 --- a/src/core/helpers/apis.js +++ b/src/core/helpers/apis.js @@ -1,6 +1,8 @@ const base = [ 'base64ToArrayBuffer', - 'arrayBufferToBase64' + 'arrayBufferToBase64', + 'addInterceptor', + 'removeInterceptor' ] const network = [