Built-in Babel plugins that provide Taro-specific transformations including component optimization, configuration cleanup, and platform-specific code generation.
Plugin that removes definePageConfig function calls from source files while preserving them in configuration files.
/**
* Plugin for removing definePageConfig calls from source files
* @param {Object} babel - Babel instance with types and utilities
* @returns {BabelPlugin} Plugin configuration with visitor pattern
*/
function removeDefineConfigPlugin(babel) { ... }
interface BabelPlugin {
name: string;
visitor: VisitorConfig;
}
interface VisitorConfig {
CallExpression: (nodePath: NodePath, state: PluginState) => void;
}
interface PluginState {
filename: string;
}Plugin Behavior:
definePageConfig from source filesdefinePageConfig calls in .config.(t|j)sx? files/src/ directoryUsage Examples:
// Input: src/pages/index.tsx
definePageConfig({
navigationBarTitleText: 'Home'
});
export default function Index() {
return <View>Hello</View>;
}
// Output: src/pages/index.tsx (definePageConfig call removed)
export default function Index() {
return <View>Hello</View>;
}
// Input: src/pages/index.config.ts (preserved)
definePageConfig({
navigationBarTitleText: 'Home'
});Advanced plugin that transforms Taro List/ListItem components to ScrollView/ListBuilder/View components for WeChat mini-program compatibility.
/**
* Plugin for transforming Taro List/ListItem components
* @param {Object} api - Babel API with helper utilities and type checkers
* @returns {ComponentTransformPlugin} Component transformation plugin
*/
function transformTaroComponentsPlugin(api) { ... }
interface ComponentTransformPlugin {
name: 'plugin:transform-taro-components';
visitor: ComponentVisitor;
}
interface ComponentVisitor {
Program: ProgramVisitor;
ImportDeclaration: (path: NodePath) => void;
JSXElement: (path: NodePath) => void;
}
interface ProgramVisitor {
exit: (path: NodePath) => void;
}Component Mappings:
<List> → <ScrollView type="custom"><ListBuilder><ListItem> → <View>Constants:
const COMPONENT_LIST = 'List';
const COMPONENT_LIST_ITEM = 'ListItem';
const COMPONENT_LIST_BUILDER = 'ListBuilder';
const COMPONENT_SCROLL_VIEW = 'ScrollView';
const COMPONENT_VIEW = 'View';
const TARO_COMPONENTS = '@tarojs/components';
const SCROLL_VIEW_PROPS = [
'scrollX', 'scrollY', 'scrollTop', 'upperThresholdCount',
'lowerThresholdCount', 'scrollIntoView', 'enableBackToTop',
'showScrollbar', 'onScroll', 'onScrollStart', 'onScrollEnd',
'onScrollToUpper', 'onScrollToLower', 'compileMode',
'className', 'cacheExtent', 'style', 'id', 'key'
];
const LIST_BUILDER_PROPS = [
'padding', 'type', 'list', 'childCount', 'childHeight',
'onItemBuild', 'onItemDispose'
];Usage Examples:
// Input JSX
import { List, ListItem, ScrollView } from '@tarojs/components';
function MyList({ items }) {
return (
<List padding={10} list={items} onItemBuild={(item) => item}>
<ListItem key={item.id}>
{item.name}
</ListItem>
</List>
);
}
// Output JSX (transformed)
import { ScrollView, ListBuilder, View } from '@tarojs/components';
function MyList({ items }) {
return (
<ScrollView type="custom" className="list-container">
<ListBuilder padding={10} list={items} onItemBuild={(item) => item}>
<View key={item.id}>
{item.name}
</View>
</ListBuilder>
</ScrollView>
);
}Tracks and processes component imports for transformation.
/**
* Component import tracking system
* Maintains map of imported components and their local names
*/
interface ComponentImportTracker {
/** Map of component names to import information */
componentImports: Map<string, ComponentImport>;
/** Check if component is imported from target source */
hasTargetTaroComponent: (componentName: string) => boolean;
/** Filter attributes based on allowed props */
pickAttrs: (attrs: JSXAttribute[], props: string[]) => JSXAttribute[];
}
interface ComponentImport {
/** Source package name */
source: string;
/** Original imported name */
importedName: string;
/** Local name (after aliasing) */
localName: string;
}Handles the actual JSX element transformation with proper attribute filtering.
/**
* JSX transformation utilities
* @param {JSXElement} element - JSX element to transform
* @param {ComponentImportTracker} tracker - Component import tracker
* @returns {JSXElement} Transformed JSX element
*/
interface JSXTransformer {
/** Transform List component to ScrollView + ListBuilder */
transformList: (element: JSXElement) => JSXElement;
/** Transform ListItem component to View */
transformListItem: (element: JSXElement) => JSXElement;
/** Create JSX opening element */
createOpeningElement: (name: string, attrs: JSXAttribute[]) => JSXOpeningElement;
/** Create JSX closing element */
createClosingElement: (name: string) => JSXClosingElement;
}
interface JSXAttribute {
name: {
name: string;
};
value?: JSXAttributeValue;
}
interface JSXAttributeValue {
type: 'StringLiteral' | 'JSXExpressionContainer';
value?: string;
expression?: Expression;
}Handles import declaration reconstruction after component transformation.
/**
* Program exit processing for import reconstruction
* Rebuilds @tarojs/components import statements after transformation
*/
interface ImportReconstructor {
/** Rebuild component imports after transformation */
reconstructImports: (programPath: NodePath) => void;
/** Remove original List/ListItem from imports */
filterOriginalComponents: (specifiers: ImportSpecifier[]) => ImportSpecifier[];
/** Add required components for transformation */
addRequiredComponents: (specifiers: ImportSpecifier[]) => ImportSpecifier[];
}The transform plugin is specifically designed for WeChat mini-program environments where List components need to be converted to ScrollView for compatibility.
// Activation condition
if (isReact && process.env.TARO_ENV === 'weapp') {
plugins.unshift(require('./transform-taro-components'));
}| Original Component | Target Component | Platform | Props Handling |
|---|---|---|---|
<List> | <ScrollView><ListBuilder> | WeChat MP | Props filtered and distributed |
<ListItem> | <View> | WeChat MP | All props preserved |
// Validates that components are imported from correct source
if (componentImports.has(target) && componentImports.get(target).source === TARO_COMPONENTS) {
// Proceed with transformation
}// Ensures proper JSX structure before transformation
if (api.types.isJSXIdentifier(openingElement.name)) {
const componentName = openingElement.name.name;
// Transform if conditions are met
}interface NodePath {
node: Node;
replaceWith: (node: Node) => void;
remove: () => void;
}
interface ImportSpecifier {
imported?: {
name: string;
};
local: {
name: string;
};
}
interface JSXElement {
openingElement: JSXOpeningElement;
closingElement?: JSXClosingElement;
children: JSXChild[];
selfClosing?: boolean;
}
interface JSXOpeningElement {
name: JSXIdentifier;
attributes: JSXAttribute[];
selfClosing: boolean;
}