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,66 @@
const path = require('path')
const t = require('@babel/types')
const babelTraverse = require('@babel/traverse').default
const {
parseComponents
} = require('./util')
const uniI18n = require('@dcloudio/uni-cli-i18n')
module.exports = function (ast, state = {}) {
const imports = []
let nodePath = false
try {
babelTraverse(ast, {
CallExpression (path) {
const callee = path.node.callee
if (!callee.object || !callee.property) {
return
}
const objectName = callee.object.name
const propertyName = callee.property.name
if (
propertyName === 'component' &&
(objectName === 'Vue' || objectName === 'app')
) {
const args = path.node.arguments
const nameNode = args[0]
const valueNode = args[1]
nodePath = path
if (!t.isStringLiteral(nameNode)) {
throw new Error(
uniI18n.__('mpLoader.firstParameterNeedStaticString', {
0: objectName + '.component()'
})
)
}
if (!t.isIdentifier(valueNode)) {
throw new Error(
uniI18n.__('mpLoader.requireTwoParameter', {
0: objectName + '.component()'
})
)
}
imports.push({
name: nameNode.value,
value: valueNode.name
})
}
}
})
if (imports.length) {
state.components = parseComponents(imports, nodePath)
} else {
state.components = []
}
} catch (e) {
if (state.filename) {
console.error('at ' + require('@dcloudio/uni-cli-shared').normalizePath(path.relative(process.env.UNI_INPUT_DIR, state.filename)) + ':1')
}
throw e
}
return {
ast,
state
}
}
@@ -0,0 +1,25 @@
module.exports = function ({
types: t
}) {
return {
visitor: {
MemberExpression (path, state) {
if (
t.isIdentifier(path.node.property) &&
path.node.property.name === '$mount' &&
!path.node.$createApp
) {
path.node.$createApp = true
path.get('object').replaceWith(
t.callExpression(
t.identifier('createApp'),
[
path.node.object
]
)
)
}
}
}
}
}
@@ -0,0 +1,57 @@
const t = require('@babel/types')
const babelTemplate = require('@babel/template').default
// const buildDynamicImport = babelTemplate(`var IMPORT_NAME = ()=>import(IMPORT_SOURCE)`, {
// preserveComments: true,
// plugins: [
// 'dynamicImport'
// ]
// })
// 已废弃,@vue/cli-plugin-babel@4 增加了 dynamic import 转换
// var test = ()=>import(/* webpackChunkName: "components/test" */'../../components/test')
// function getDynamicImport (name, source, chunkName) {
// const stringLiteral = t.stringLiteral(source)
// const dynamicImportComment = {
// type: 'CommentBlock',
// value: `webpackChunkName: "${chunkName}"`
// }
// stringLiteral.leadingComments = [dynamicImportComment]
// return buildDynamicImport({
// IMPORT_NAME: t.identifier(name),
// IMPORT_SOURCE: stringLiteral
// })
// }
// var test = function(resolve) {require.ensure([], () => resolve(require('../../components/test')),'components/test')}
const buildRequireEnsure = babelTemplate(
'var IMPORT_NAME = function(){require.ensure([],()=>resolve(require(IMPORT_SOURCE)),CHUNK_NAME)}'
)
function getRequireEnsure (name, source, chunkName) {
return buildRequireEnsure({
IMPORT_NAME: t.identifier(name),
IMPORT_SOURCE: t.stringLiteral(source),
CHUNK_NAME: t.stringLiteral(chunkName)
})
}
module.exports = function ({
types: t
}) {
return {
visitor: {
ImportDeclaration (path, state) {
const dynamicImport = state.opts.dynamicImports[path.node.source.value]
if (dynamicImport) {
path.insertBefore(
getRequireEnsure(
path.node.specifiers[0].local.name,
dynamicImport.source,
dynamicImport.chunkName
)
)
path.remove()
}
}
}
}
}
@@ -0,0 +1,198 @@
const path = require('path')
const t = require('@babel/types')
const babelTraverse = require('@babel/traverse').default
const {
parseComponents
} = require('./util')
function handleObjectExpression (declaration, path, state) {
if (state.options) { // name,inheritAttrs,props
Object.keys(state.options).forEach(name => {
const optionProperty = declaration.properties.filter(prop => {
return t.isObjectProperty(prop) &&
t.isIdentifier(prop.key) &&
prop.key.name === name
})[0]
if (optionProperty) {
if (name === 'props') {
if (t.isArrayExpression(optionProperty.value)) {
state.options[name] = JSON.stringify(optionProperty.value.elements.filter(element => t.isStringLiteral(
element)).map(({
value
}) => value))
} else if (t.isObjectExpression(optionProperty.value)) {
const props = []
optionProperty.value.properties.forEach(({
key
}) => {
if (t.isIdentifier(key)) {
props.push(key.name)
} else if (t.isStringLiteral(key)) {
props.push(key.value)
}
})
state.options[name] = JSON.stringify(props)
}
} else if (t.isStringLiteral(optionProperty.value)) {
state.options[name] = JSON.stringify(optionProperty.value.value)
} else {
state.options[name] = optionProperty.value.value
}
}
})
}
const componentsProperty = declaration.properties.filter(prop => {
return t.isObjectProperty(prop) &&
t.isIdentifier(prop.key) &&
prop.key.name === 'components'
})[0]
if (componentsProperty && t.isObjectExpression(componentsProperty.value)) {
handleComponentsObjectExpression(componentsProperty.value, path, state)
}
}
function handleComponentsObjectExpression (componentsObjExpr, path, state, prepend) {
const properties = componentsObjExpr.properties
.filter(prop => t.isObjectProperty(prop) && t.isIdentifier(prop.value))
const components = parseComponents(properties.map(prop => {
return {
name: prop.key.name || prop.key.value,
value: prop.value.name
}
}), path)
state.components = prepend ? components.concat(state.components) : components
}
function handleIdentifier ({
name
}, path, state) {
// 仅做有限查找
for (let i = path.container.length; i > 0; i--) {
const node = path.container[i - 1]
let declarations = []
if (t.isExpressionStatement(node)) {
declarations = [node]
} else if (t.isVariableDeclaration(node)) {
declarations = node.declarations
}
for (let i = declarations.length; i > 0; i--) {
let declaration = declarations[i - 1]
let identifier
if (t.isVariableDeclarator(declaration)) {
identifier = declaration.id
declaration = declaration.init
} else if (t.isExpressionStatement(declaration) && t.isAssignmentExpression(declaration.expression)) {
identifier = declaration.expression.left
declaration = declaration.expression.right
}
// __sfc_main.components = Object.assign({CustomButton}, __sfc_main.components);
if (t.isMemberExpression(identifier) && identifier.object.name === name && identifier.property.name === 'components' && t.isCallExpression(declaration) && declaration.arguments.length === 2 && t.isObjectExpression(declaration.arguments[0])) {
handleComponentsObjectExpression(declaration.arguments[0], path, state, true)
return
}
if (identifier.name === name) {
if (t.isCallExpression(declaration) &&
t.isMemberExpression(declaration.callee) &&
declaration.arguments.length === 1) {
declaration = declaration.arguments[0]
}
if (t.isObjectExpression(declaration)) {
handleObjectExpression(declaration, path, state)
}
return
}
}
}
}
module.exports = function (ast, state = {
type: 'Component',
components: [],
options: {}
}) {
try {
babelTraverse(ast, {
CallExpression (path) {
const callee = path.node.callee
const args = path.node.arguments
const objExpr = args[0]
if (
t.isIdentifier(callee) &&
callee.name === 'defineComponent' &&
args.length === 1 &&
t.isObjectExpression(objExpr)
) {
handleObjectExpression(objExpr, path, state)
}
},
AssignmentExpression (path) {
const leftExpression = path.node.left
const rightExpression = path.node.right
if ( // global['__wxVueOptions'] = {'van-button':VanButton}
t.isMemberExpression(leftExpression) &&
t.isObjectExpression(rightExpression) &&
leftExpression.object.name === 'global' &&
leftExpression.property.value === '__wxVueOptions'
) {
handleObjectExpression(rightExpression, path, state)
}
if ( // exports.default.components = Object.assign({'van-button': VanButton}, exports.default.components || {})
t.isMemberExpression(leftExpression) &&
t.isCallExpression(rightExpression) &&
leftExpression.property.name === 'components' &&
t.isMemberExpression(leftExpression.object) &&
leftExpression.object.object.name === 'exports' &&
leftExpression.object.property.name === 'default' &&
rightExpression.arguments.length === 2 &&
t.isObjectExpression(rightExpression.arguments[0])
) {
handleComponentsObjectExpression(rightExpression.arguments[0], path, state, true)
}
},
ExportDefaultDeclaration (path) {
const declaration = path.node.declaration
if (t.isObjectExpression(declaration)) { // export default {components:{}}
handleObjectExpression(declaration, path, state)
} else if (t.isIdentifier(declaration)) {
handleIdentifier(declaration, path, state)
} else if (t.isCallExpression(declaration) &&
t.isMemberExpression(declaration.callee) &&
declaration.arguments.length === 1) { // export default Vue.extend({components:{}})
if (declaration.callee.object.name === 'Vue' && declaration.callee.property.name ===
'extend') {
const argument = declaration.arguments[0]
if (t.isObjectExpression(argument)) {
handleObjectExpression(argument, path, state)
} else if (t.isIdentifier(argument)) {
handleIdentifier(argument, path, state)
}
}
} else if (t.isClassDeclaration(declaration) &&
declaration.decorators &&
declaration.decorators.length
) { // export default @Component({components:{}}) class MyComponent extend Vue
const componentDecorator = declaration.decorators[0]
if (t.isCallExpression(componentDecorator.expression)) {
const args = componentDecorator.expression.arguments
if (args && args.length && t.isObjectExpression(args[0])) {
handleObjectExpression(args[0], path, state)
}
}
}
}
})
} catch (e) {
if (state.filename) {
console.error('at ' + require('@dcloudio/uni-cli-shared').normalizePath(path.relative(process.env.UNI_INPUT_DIR, state.filename)) + ':1')
}
throw e
}
return {
ast,
state
}
}
+88
View File
@@ -0,0 +1,88 @@
const t = require('@babel/types')
const uniI18n = require('@dcloudio/uni-cli-i18n')
const hyphenateRE = /\B([A-Z])/g
function cached (fn) {
const cache = Object.create(null)
return function cachedFn (str) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}
}
const hyphenate = cached((str) => {
return str.replace(hyphenateRE, '-$1').toLowerCase()
})
function findImportDeclaration (identifierName, path) {
const binding = path.scope.getBinding(identifierName)
if (!binding) {
return
}
if (t.isImportDeclaration(binding.path.parent)) {
return binding.path.parentPath
}
}
function parseComponents (names, path) {
const components = []
const dynamicImportMap = new Map()
names.forEach(({
name,
value
}) => {
const importDeclaration = findImportDeclaration(value, path)
if (!importDeclaration) {
throw new Error(uniI18n.__('mpLoader.componentReferenceErrorOnlySupportImport', {
0: name
}))
}
let source = importDeclaration.node.source.value
if (process.UNI_LIBRARIES && process.UNI_LIBRARIES.includes(source)) {
const componentName = hyphenate(name)
source = source + '/lib/' + componentName + '/' + componentName
}
const dynamicImportArray = dynamicImportMap.get(importDeclaration) || []
dynamicImportArray.push({
name,
value,
source
})
dynamicImportMap.set(importDeclaration, dynamicImportArray)
})
const importDeclarations = dynamicImportMap.keys()
for (const importDeclaration of importDeclarations) {
const dynamicImportArray = dynamicImportMap.get(importDeclaration)
dynamicImportArray.forEach((dynamicImport) => {
components.push(dynamicImport)
})
importDeclaration.remove()
}
return components
}
function findBabelLoader (loaders) {
return loaders.find(loader => loader.path.indexOf('babel-loader') !== -1)
}
const babelPluginDynamicImport = require.resolve('./plugin-dynamic-import')
function addDynamicImport (babelLoader, resourcePath, dynamicImports) {
babelLoader.options = babelLoader.options || {}
if (!babelLoader.options.plugins) {
babelLoader.options.plugins = []
}
babelLoader.options.plugins.push([babelPluginDynamicImport, {
resourcePath,
dynamicImports
}])
}
module.exports = {
addDynamicImport,
findBabelLoader,
parseComponents
}