A Parcel transformer plugin that transforms JavaScript code using Babel with automatic configuration discovery and intelligent defaults for modern JavaScript, TypeScript, JSX, and Flow.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Core Babel 7 processing functionality that performs the actual code transformation with comprehensive AST management, source mapping, and performance optimization.
Main function that performs Babel transformation using @babel/core with full configuration and AST management.
/**
* Performs Babel 7 transformation on JavaScript/TypeScript/JSX assets
* Handles AST processing, plugin configuration, and performance tracing
* Modifies the asset's AST in place rather than returning it
* @param opts - Transformation options
* @returns Promise that resolves when transformation is complete (returns undefined)
*/
async function babel7(opts: Babel7TransformOptions): Promise<void>;
interface Babel7TransformOptions {
asset: MutableAsset; // The asset being transformed
options: PluginOptions; // Parcel plugin options
logger: PluginLogger; // Logger for warnings and errors
babelOptions: any; // Babel configuration object
additionalPlugins?: Array<any>; // Extra plugins from asset metadata
tracer: PluginTracer; // Performance tracing utility
}The function assembles a comprehensive Babel configuration from multiple sources:
// Configuration structure passed to @babel/core
interface BabelTransformConfig {
plugins: Array<any>; // Combined plugins array
presets: Array<any>; // Babel presets
code: false; // Disable code generation
ast: true; // Enable AST output
filename: string; // Source file path
babelrc: false; // Disable .babelrc loading
configFile: false; // Disable babel.config.* loading
parserOpts: ParserOptions; // Parser configuration
caller: CallerOptions; // Caller identification
wrapPluginVisitorMethod?: Function; // Performance tracing wrapper
}
interface ParserOptions {
sourceFilename: string; // Relative source filename
allowReturnOutsideFunction: true; // Allow top-level returns
strictMode: false; // Disable strict mode enforcement
sourceType: 'module'; // Always treat as ES module
plugins: Array<string>; // Syntax plugins to enable
}
interface CallerOptions {
name: 'parcel'; // Identifies Parcel as caller
version: string; // Transformer version
targets: string; // JSON stringified targets
outputFormat: string; // Output format (esm, cjs, etc.)
}The function handles two different processing modes based on asset state:
// Mode 1: Transform from existing AST
const result = await babelCore.transformFromAstAsync(
ast.program, // Existing AST program
asset.isASTDirty() ? undefined : await asset.getCode(), // Code if AST is clean
config // Babel configuration
);
// Mode 2: Transform from source code
const result = await babelCore.transformAsync(
await asset.getCode(), // Source code string
config // Babel configuration
);When transforming from source code, the function remaps AST locations using existing source maps:
/**
* Remaps AST node locations using source map for accurate debugging
* Applied when transforming from source code rather than existing AST
*/
if (res.ast && !ast) {
let map = await asset.getMap();
if (map) {
remapAstLocations(babelCore.types, res.ast, map);
}
}Processes external dependencies declared by Babel plugins:
// External dependency processing
if (res.externalDependencies) {
for (let filePath of res.externalDependencies) {
if (!path.isAbsolute(filePath)) {
// Warn about non-absolute dependencies
logger.warn({
message: `Ignoring non-absolute Babel external dependency: ${filePath}`,
hints: ['Please report this to the corresponding Babel plugin and/or to Parcel.']
});
} else {
// Track file changes/creation for cache invalidation
if (await options.inputFS.exists(filePath)) {
asset.invalidateOnFileChange(filePath);
} else {
asset.invalidateOnFileCreate({ filePath });
}
}
}
}Integrates with Parcel's performance tracing system to monitor plugin execution:
/**
* Wraps Babel plugin visitor methods for performance measurement
* Only active when tracer.enabled is true
*/
config.wrapPluginVisitorMethod = (
key: string, // Plugin identifier
nodeType: string, // AST node type being visited
fn: Function // Original visitor function
) => {
return function() {
const measurement = tracer.createMeasurement(
key.startsWith(options.projectRoot)
? path.relative(options.projectRoot, key)
: key,
nodeType,
path.relative(options.projectRoot, asset.filePath)
);
fn.apply(this, arguments);
measurement && measurement.end();
};
};Automatically configures essential syntax plugins for modern JavaScript:
const defaultSyntaxPlugins = [
'classProperties', // class field declarations
'classPrivateProperties', // private class fields
'classPrivateMethods', // private class methods
'exportDefaultFrom' // export { default } from 'module'
// 'topLevelAwait' - commented out, conditionally enabled
];
// Combined with config-specific syntax plugins
const allSyntaxPlugins = [
...(babelOptions.config.parserOpts?.plugins ?? []),
...(babelOptions.syntaxPlugins ?? []),
...defaultSyntaxPlugins
];Sets the transformed AST on the asset with proper metadata:
/**
* Sets the transformed AST on the asset
* Includes version information for AST reuse optimization
*/
if (res.ast) {
asset.setAST({
type: 'babel', // AST type identifier
version: '7.0.0', // Babel version for compatibility
program: res.ast // Transformed AST program
});
}Usage Example:
// Internal usage during transformation
const transformedAST = await babel7({
asset: jsAsset,
options: pluginOptions,
logger: parcelLogger,
babelOptions: {
config: {
presets: [['@babel/preset-env', { targets: { node: '16' } }]],
plugins: ['@babel/plugin-proposal-class-properties']
},
targets: { node: '16.0.0' },
syntaxPlugins: ['jsx']
},
additionalPlugins: [],
tracer: performanceTracer
});
// AST is set on the asset and returned for further processing
console.log('Transformation complete:', transformedAST !== null);The function handles automatic installation and resolution of Babel dependencies:
Install with Tessl CLI
npx tessl i tessl/npm-parcel--transformer-babel