The Stencil CLI is the primary entry point for developers interacting with Stencil. It provides a comprehensive command-line interface for building, serving, testing, and managing Stencil projects.
Location: src/cli/
graph TD
Entry[bin/stencil] --> CLI[cli/index.ts]
CLI --> Parser[Parse Arguments]
Parser --> Config[Load Config]
Config --> Task[Task Runner]
Task --> Build[Build Task]
Task --> Serve[Serve Task]
Task --> Test[Test Task]
Task --> Generate[Generate Task]
Task --> Docs[Docs Task]
Build --> Compiler[Compiler Core]
Serve --> DevServer[Dev Server]
Test --> TestRunner[Test Runner]
The Node.js executable that bootstraps the CLI:
#!/usr/bin/env node
'use strict';
require('../cli/index.js').run(process.argv.slice(2));The main CLI orchestrator that:
- Parses command-line arguments
- Loads configuration
- Executes appropriate tasks
- Handles errors and exits
Key function: run(args: string[])
Parses command-line arguments into structured flags:
interface ConfigFlags {
task?: TaskCommand;
args?: string[];
knownArgs?: string[];
unknownArgs?: string[];
// Build flags
build?: boolean;
cache?: boolean;
ci?: boolean;
debug?: boolean;
dev?: boolean;
docs?: boolean;
es5?: boolean;
log?: boolean;
prerender?: boolean;
prod?: boolean;
serve?: boolean;
watch?: boolean;
// Paths
config?: string;
root?: string;
// Dev server
address?: string;
port?: number;
}Responsible for finding and loading the Stencil configuration:
-
Search Order:
- Explicit
--configpath stencil.config.tsin current directorystencil.config.jsin current directory- Walk up directory tree
- Explicit
-
Config Validation:
- TypeScript compilation
- Schema validation
- Default values
- Path resolution
Tasks are the core operations that Stencil can perform:
Compiles the project:
export const taskBuild = async (
coreCompiler: CoreCompiler,
config: ValidatedConfig
) => {
if (config.flags.watch) {
await taskWatch(coreCompiler, config);
return;
}
const compiler = await coreCompiler.createCompiler(config);
const results = await compiler.build();
if (results.hasError) {
process.exit(1);
}
};Continuous build with file watching:
- Creates compiler in watch mode
- Optionally starts dev server
- Monitors file changes
- Triggers rebuilds
Starts the development server:
- HTTP server for static files
- WebSocket server for HMR
- Automatic browser refresh
- Error overlay
Scaffolds new components:
stencil generate my-componentCreates:
- Component TypeScript file
- Stylesheet
- E2E test
- Unit test
Generates documentation:
- JSON output for tooling
- Markdown for repositories
- Custom formats via plugins
Anonymous usage tracking for improving Stencil:
- Command usage
- Build times
- Error types (not content)
- System info (OS, Node version)
- Project size metrics
- No personal information
- No source code
- No file paths
- Opt-out via
--no-telemetry
export const telemetry = async (
config: Config,
action: TelemetryAction
) => {
if (config.telemetry === false) {
return;
}
const data = {
action,
version: config.version,
node: process.version,
platform: process.platform,
// ... other metrics
};
await sendTelemetry(data);
};Checks for Stencil updates:
- Check Frequency: Once per day
- Version Comparison: SemVer comparison
- Update Notification: Non-blocking message
- Cache Location:
~/.stencil/version-cache.json
process.on('SIGINT', () => {
config.logger.info('Exiting...');
destroy();
});0: Success1: General error2: Invalid configuration3: Build error
The CLI includes a sophisticated logging system:
- Debug: Verbose internal details
- Info: General information
- Warn: Potential issues
- Error: Actual problems
- Colored output
- Timestamps
- Log filtering
- File output option
- Parse: Command-line arguments
- Load: Configuration file
- Validate: Merged configuration
- Initialize: Compiler instance
- Execute: Task logic
- Report: Results and diagnostics
- Exit: With appropriate code
try {
await runTask(config);
} catch (e) {
if (shouldIgnoreError(e)) {
return;
}
config.logger.error(e);
process.exit(1);
}Priority order (highest to lowest):
- CLI flags
- Environment variables
- Config file
- Defaults
npm test src/cliTest full CLI commands:
describe('cli', () => {
it('should build project', async () => {
const { exitCode, output } = await runCLI(['build']);
expect(exitCode).toBe(0);
expect(output).toContain('build finished');
});
});# Test locally
node bin/stencil build --dev
# Test with npm link
npm link
cd /path/to/test/project
stencil buildstencil build --debugEnables:
- Verbose logging
- Source maps
- Non-minified output
- Performance timing
node --inspect bin/stencil buildConnect Chrome DevTools for debugging.
Problem: CLI can't find stencil.config.ts
Solution:
- Check file exists
- Verify working directory
- Use
--configflag
Problem: Config file has TypeScript errors
Solution:
- Ensure TypeScript is installed
- Check for syntax errors
- Verify imports
Problem: Can't write to output directory
Solution:
- Check file permissions
- Run as appropriate user
- Clear output directory
- Plugin System: Allow CLI extensions
- Interactive Mode: Guided setup
- Performance: Faster startup time
- Diagnostics: Better error messages
- Customization: User-defined tasks