first commit

This commit is contained in:
2026-09-08 20:28:54 +08:00
commit 2ada8d3d5a
37380 changed files with 4886169 additions and 0 deletions
@@ -0,0 +1,20 @@
process.UNI_APIS = new Set()
module.exports = function ({
types: t
}) {
return {
visitor: {
MemberExpression (path, state) {
if (
t.isIdentifier(path.node.object) &&
(
path.node.object.name === 'uni' ||
path.node.object.name === 'wx'
)
) {
process.UNI_APIS.add(path.node.property.name || path.node.property.value)
}
}
}
}
}
@@ -0,0 +1,247 @@
const fs = require('fs')
const path = require('path')
const updateComponents = require('./component')
const tmpDir = path.resolve(__dirname, '../../.tmp')
function writeFileSync (filename, content) {
fs.writeFileSync(path.resolve(tmpDir, filename), content, 'utf8')
}
function parseImportPath (filepath) {
if (filepath.indexOf('/platforms') === 0) { // api,appComponents(h5),appMixins(h5),systemRoutes(h5)
return filepath.replace('/platforms/' + process.env.UNI_PLATFORM, 'uni-platform')
} else if (filepath.indexOf('/core/helpers') === 0) { // protocol
return filepath.replace('/core/helpers', 'uni-helpers')
} else if (filepath.indexOf('/core/view') === 0) { // subscribe
return filepath.replace('/core/view', 'uni-view')
} else if (filepath.indexOf('/core') === 0) { // api
return filepath.replace('/core', 'uni-core')
}
return filepath
}
function updateExportDefaultObject (paths, filename, isMulti = true, isExportArray = false) {
const imports = []
const exports = []
Object.keys(paths).forEach(name => {
if (isMulti) {
imports.push(`import {${name}} from '${parseImportPath(paths[name])}'`)
} else {
imports.push(`import ${name} from '${parseImportPath(paths[name])}'`)
}
exports.push(name)
})
let content = isExportArray ? 'export default []' : 'export default {}'
if (exports.length) {
if (isExportArray) {
content = `
${imports.join('\n')}
export default [
${exports.join(',\n')}
]
`
} else {
content = `
${imports.join('\n')}
export default {
${exports.join(',\n')}
}
`
}
}
writeFileSync(filename, content)
}
function updateApi (paths) {
return updateExportDefaultObject(paths, 'api.js')
}
function updateApiProtocol (paths) {
return updateExportDefaultObject(paths, 'protocol.js')
}
function updateApiSubscribe (paths) {
return updateExportDefaultObject(paths, 'subscribe.js')
}
function updateInvokeApi (paths) {
return updateExportDefaultObject(paths, 'invoke-api.js')
}
function updateAppComponents (paths) {
return updateExportDefaultObject(paths, 'app-components.js', false)
}
function updateCoreComponents (paths) {
const tags = process.UNI_TAGS || new Set()
Object.keys(paths).forEach(tag => tags.add(tag.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()))
updateComponents(tags)
}
function updateAppMixins (paths) {
return updateExportDefaultObject(paths, 'app-mixins.js', false, true)
}
function updateSystemRoutes (paths) {
return updateExportDefaultObject(paths, 'system-routes.js', false)
}
const isProtocol = filepath => {
return filepath.indexOf('/core/helpers/protocol') === 0
}
const isPlatformApi = filepath => {
return filepath.indexOf('/platforms/' + process.env.UNI_PLATFORM + '/service/api') === 0
}
const isAppComponents = filepath => {
return path.extname(filepath) === '.vue' &&
filepath.indexOf('/platforms/' + process.env.UNI_PLATFORM + '/components/app/') === 0
}
const isCoreComponents = filepath => {
return path.extname(filepath) === '.vue' &&
(filepath.indexOf('/core/view/components/') === 0 || filepath.indexOf('/platforms/' + process.env.UNI_PLATFORM +
'/view/components/') === 0)
}
const isAppMixins = filepath => {
return path.extname(filepath) === '.js' &&
filepath.indexOf('/platforms/' + process.env.UNI_PLATFORM + '/components/app/') === 0
}
const isSystemRoutes = filepath => {
return filepath.indexOf('/platforms/' + process.env.UNI_PLATFORM + '/components/system-routes') === 0
}
const isApiSubscribe = filepath => {
return filepath.indexOf('/core/view/bridge/subscribe/api') === 0
}
function parseDeps (apis, manifest) {
const apiPaths = Object.create(null)
const apiProtocolPaths = Object.create(null)
const invokeApiPaths = Object.create(null)
const appComponentsPaths = Object.create(null)
const coreComponentsPaths = Object.create(null)
const appMixinsPaths = Object.create(null)
const systemRoutesPaths = Object.create(null)
const apiSubscribePaths = Object.create(null)
const strategies = [{
test: isProtocol,
paths: apiProtocolPaths
}, {
test: isPlatformApi,
paths: apiPaths
}, {
test: isAppComponents,
paths: appComponentsPaths
}, {
test: isCoreComponents,
paths: coreComponentsPaths
}, {
test: isAppMixins,
paths: appMixinsPaths
}, {
test: isSystemRoutes,
paths: systemRoutesPaths
}, {
test: isApiSubscribe,
paths: apiSubscribePaths
}]
// 固定顺序,避免因顺序的变化导致内容变化,从而生成不同的 hash 文件名
const apiNames = [...apis].sort()
for (const name of apiNames) {
const options = manifest[name]
if (Array.isArray(options)) {
apiPaths[name] = options[0]
const deps = options[1]
if (!Array.isArray(deps) || !deps.length) {
continue
}
const isCoreApi = !isPlatformApi(options[0])
deps.forEach(dep => {
const filepath = dep[0]
const exports = dep[1]
if (isCoreApi && isPlatformApi(filepath)) { // invoke-api
invokeApiPaths[exports] = filepath
} else {
const strategy = strategies.find(strategy => {
return strategy.test(filepath)
})
if (strategy) {
strategy.paths[exports] = filepath
} else {
console.log('dep', name, dep)
console.warn(`${filepath} 未识别`)
}
}
})
} else {
// console.warn(`${process.env.UNI_PLATFORM} 平台不支持 uni.${name}`)
}
}
return {
apiPaths,
apiProtocolPaths,
invokeApiPaths,
appComponentsPaths,
coreComponentsPaths,
appMixinsPaths,
systemRoutesPaths,
apiSubscribePaths
}
}
module.exports = function updateApis (apis = new Set(), userApis = new Set()) {
if (!fs.existsSync(tmpDir)) {
fs.mkdirSync(tmpDir)
}
const manifest = require('@dcloudio/uni-' + process.env.UNI_PLATFORM + '/manifest.json')
// autoload
Object.keys(manifest).forEach(name => {
if (manifest[name][2]) {
apis.add(name)
}
})
apis = new Set([...apis, ...userApis])
if (process.UNI_TAGS) {
// TODO 临时硬编码
if (process.UNI_TAGS.has('map')) {
apis.add('getLocation')
apis.add('stopCompass')
apis.add('onCompassChange')
}
}
const {
apiPaths,
apiProtocolPaths,
invokeApiPaths,
apiSubscribePaths,
appComponentsPaths,
coreComponentsPaths,
appMixinsPaths,
systemRoutesPaths
} = parseDeps(apis, manifest)
updateApi(apiPaths)
updateApiProtocol(apiProtocolPaths)
updateApiSubscribe(apiSubscribePaths)
updateInvokeApi(invokeApiPaths)
updateAppComponents(appComponentsPaths)
updateCoreComponents(coreComponentsPaths)
updateAppMixins(appMixinsPaths)
updateSystemRoutes(systemRoutesPaths)
}
@@ -0,0 +1,58 @@
const fs = require('fs')
const path = require('path')
const {
camelize,
capitalize
} = require('./util')
const platformTags = ['map', 'video', 'web-view', 'cover-view', 'cover-image', 'picker', 'ad', 'view']
const autoloadTags = {
// input 在 pageHead 中有使用,resize-sensor 在很多组件中有使用,暂时直接加载
root: ['input', 'resize-sensor'],
other: {
picker: ['picker-view', 'picker-view-column']
}
}
module.exports = function updateComponents (tags) {
autoloadTags.root.forEach(tagName => {
tags.add(tagName)
})
Object.keys(autoloadTags.other).forEach(tagName => {
if (tags.has(tagName)) {
autoloadTags.other[tagName].forEach(tag => tags.add(tag))
}
})
tags = [...tags].sort() // 固定顺序,避免因顺序的变化导致内容变化,从而生成不同的 hash 文件名
const importsStr = tags.map(tagName => {
if (platformTags.indexOf(tagName) !== -1) {
return `import ${capitalize(camelize(tagName))} from 'uni-platform/view/components/${tagName}'`
}
return `import ${capitalize(camelize(tagName))} from 'uni-view/components/${tagName}'`
}).join('\n')
const componentsStr = tags.map(tagName => {
tagName = capitalize(camelize(tagName))
return `${tagName}.name = 'VUni${tagName}'
${tagName}.mixins = ${tagName}.mixins ? [].concat(baseMixin, ${tagName}.mixins) : [baseMixin]
${tagName}.mixins.push(animation)
Vue.component(${tagName}.name,${tagName})`
}).join('\n')
const content = `
import Vue from 'vue'
import baseMixin from 'uni-mixins/base'
import animation from 'uni-mixins/animation'
${importsStr}
${componentsStr}
`
const dir = path.resolve(__dirname, '../../.tmp')
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
fs.writeFileSync(path.resolve(dir, 'components.js'), content, 'utf8')
}
@@ -0,0 +1,42 @@
const {
info,
done
} = require('@vue/cli-shared-utils')
const updateComponents = require('./component')
const updateApis = require('./api')
class WebpackOptimizePlugin {
apply (compiler) {
let optimized = false
compiler.hooks.beforeCompile.tapPromise('WebpackOptimizePlugin', compilation => {
return new Promise((resolve, reject) => {
if (!optimized) {
updateComponents(new Set())
updateApis(new Set(), new Set())
}
resolve()
})
})
compiler.hooks.shouldEmit.tap('WebpackOptimizePlugin', compilation => {
return optimized
})
compiler.hooks.done.tapPromise('WebpackOptimizePlugin', compilation => {
return new Promise((resolve, reject) => {
if (!optimized) {
console.log()
info('Build optimizing...')
optimized = true
updateComponents(process.UNI_TAGS || new Set())
updateApis(process.UNI_APIS || new Set(), process.UNI_USER_APIS || new Set())
} else {
done('Build complete.')
process.exit(0)
}
resolve()
})
})
}
}
module.exports = WebpackOptimizePlugin
@@ -0,0 +1,22 @@
function cached (fn) {
const cache = Object.create(null)
return function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}
}
const camelizeRE = /-(\w)/g
const camelize = cached(function (str) {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
const capitalize = cached(function (str) {
return str.charAt(0).toUpperCase() + str.slice(1)
})
module.exports = {
camelize,
capitalize
}
@@ -0,0 +1,15 @@
const isWin = /^win/.test(process.platform)
const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path)
const src = require('@dcloudio/uni-h5/path').src
module.exports = function (content) {
this.cacheable && this.cacheable()
const resourcePath = normalizePath(this.resourcePath)
const sourcePath = normalizePath(src)
if (resourcePath.indexOf(sourcePath) === 0) {
return ''
}
return content
}