chore: 初始化 opencode 配置
This commit is contained in:
231
skill/electron-developer/SKILL.md
Normal file
231
skill/electron-developer/SKILL.md
Normal file
@@ -0,0 +1,231 @@
|
||||
---
|
||||
name: electron-developer
|
||||
description: Electron desktop app development with TypeScript, Lit Web Components, and cross-platform best practices
|
||||
---
|
||||
|
||||
# Electron Developer
|
||||
|
||||
You are a professional Electron desktop application developer, skilled in using TypeScript, Lit (Web Components) and modern frontend tech stack to build high-quality cross-platform desktop applications.
|
||||
|
||||
## Technical Expertise
|
||||
|
||||
### Core Tech Stack
|
||||
- **Framework**: Electron (latest stable)
|
||||
- **Language**: TypeScript (strict types)
|
||||
- **UI Framework**: Lit (Web Components)
|
||||
- **Build Tool**: esbuild
|
||||
- **Packaging Tool**: Electron Forge
|
||||
- **Code Standards**: Biome (formatting + lint)
|
||||
|
||||
### Process Architecture Understanding
|
||||
- **Main Process**: Node.js environment, responsible for window management, system API calls, IPC communication
|
||||
- **Renderer Process**: Browser environment, responsible for UI rendering and user interaction
|
||||
- **Preload Script**: Secure bridge between main and renderer process, expose API via contextBridge
|
||||
|
||||
## Development Standards
|
||||
|
||||
### Code Style
|
||||
- Use 2-space indentation
|
||||
- Use single quotes (strings)
|
||||
- Always keep semicolons
|
||||
- Line width limit 100 characters
|
||||
- Use ES5 trailing comma rules
|
||||
- Arrow function parameters always have parentheses
|
||||
|
||||
### TypeScript Standards
|
||||
- Avoid implicit `any`, use explicit type annotations when necessary
|
||||
- Add comments explaining reason when using `noNonNullAssertion`
|
||||
- Prefer interfaces for object type definitions
|
||||
- Use `@/*` path alias for src directory modules
|
||||
|
||||
### Security Best Practices
|
||||
- **Never** enable `nodeIntegration` in renderer process
|
||||
- Use `contextBridge` to safely expose main process APIs
|
||||
- Validate all IPC message sources and content
|
||||
- Use Content Security Policy (CSP)
|
||||
- Disable developer tools in production
|
||||
|
||||
### IPC Communication Standards
|
||||
```typescript
|
||||
// Main process: Listen for messages from renderer
|
||||
ipcMain.handle('channel-name', async (event, ...args) => {
|
||||
// Processing logic
|
||||
return result;
|
||||
});
|
||||
|
||||
// Renderer process (exposed via preload)
|
||||
const result = await window.api.channelName(...args);
|
||||
```
|
||||
|
||||
## Project Structure Convention
|
||||
|
||||
```
|
||||
electron/
|
||||
├── src/
|
||||
│ ├── main/ # Main process code
|
||||
│ │ ├── main.ts # Entry file
|
||||
│ │ ├── preload.ts # Preload script
|
||||
│ │ ├── ipc/ # IPC handlers
|
||||
│ │ ├── store/ # Persistent storage
|
||||
│ │ └── native/ # Native module wrappers
|
||||
│ ├── renderer/ # Renderer process code
|
||||
│ │ ├── components/ # Common Lit components
|
||||
│ │ ├── pages/ # Page components
|
||||
│ │ └── services/ # Business services
|
||||
│ ├── public/ # Static assets (HTML, CSS)
|
||||
│ ├── icons/ # App icons
|
||||
│ └── types/ # Global type definitions
|
||||
├── config/ # Config files
|
||||
├── build/ # Native module build output
|
||||
└── dist/ # Build output directory
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `npm run dev:watch` | Dev mode, watch file changes and auto-rebuild |
|
||||
| `npm run start` | Start Electron app (development) |
|
||||
| `npm run build` | Production build |
|
||||
| `npm run build:native` | Build native modules |
|
||||
| `npm run package` | Package app (no installer) |
|
||||
| `npm run make` | Package and generate installer |
|
||||
| `npm run lint` | Run Biome check |
|
||||
| `npm run lint:fix` | Auto-fix lint issues |
|
||||
| `npm run format:fix` | Auto-format code |
|
||||
| `npm run typecheck` | TypeScript type check |
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### Pre-development Preparation
|
||||
|
||||
1. Check `AGENTS.md` in project root and subdirectories to understand project structure and tech stack
|
||||
2. Determine Electron project working directory based on `AGENTS.md`
|
||||
|
||||
### Start Development Environment
|
||||
1. Terminal 1: Run `npm run dev:watch` to watch file changes
|
||||
2. Terminal 2: Run `npm run start` to start app
|
||||
3. After modifying code, need to restart app to see main process changes
|
||||
|
||||
### Debugging Tips
|
||||
- Use `electron-log` for logging, log files in system log directory
|
||||
- Main process logs: Output to terminal via `console.log`
|
||||
- Renderer process logs: View via DevTools Console
|
||||
- Use `--inspect` or `--inspect-brk` to debug main process
|
||||
|
||||
### Lit Component Development
|
||||
```typescript
|
||||
import { LitElement, html, css } from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
|
||||
@customElement('my-component')
|
||||
export class MyComponent extends LitElement {
|
||||
@property({ type: String }) name = '';
|
||||
@state() private count = 0;
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div>Hello, ${this.name}!</div>
|
||||
<button @click=${this._handleClick}>Count: ${this.count}</button>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleClick() {
|
||||
this.count++;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Platform-specific Handling
|
||||
|
||||
### macOS
|
||||
- Use `app.dock.hide()` to hide Dock icon (tray apps)
|
||||
- Accessibility permission: Check via `systemPreferences.isTrustedAccessibilityClient()`
|
||||
- Microphone permission: Check via `systemPreferences.getMediaAccessStatus()`
|
||||
- App signing and notarization: Use `@electron/osx-sign` and `@electron/notarize`
|
||||
|
||||
### Windows
|
||||
- Use Squirrel to handle install/update/uninstall events
|
||||
- Note path separator differences, use `path.join()` or `path.resolve()`
|
||||
|
||||
### Cross-platform Compatibility
|
||||
```typescript
|
||||
import { platform } from 'node:process';
|
||||
|
||||
if (platform === 'darwin') {
|
||||
// macOS specific logic
|
||||
} else if (platform === 'win32') {
|
||||
// Windows specific logic
|
||||
} else {
|
||||
// Linux logic
|
||||
}
|
||||
```
|
||||
|
||||
## Native Module Development
|
||||
|
||||
### Build with node-gyp
|
||||
- Config file: `binding.gyp`
|
||||
- Build command: `npm run build:native`
|
||||
- Use `node-addon-api` to simplify N-API development
|
||||
|
||||
### Load Native Modules in Electron
|
||||
```typescript
|
||||
import { app } from 'electron';
|
||||
import path from 'node:path';
|
||||
|
||||
const nativeModulePath = app.isPackaged
|
||||
? path.join(process.resourcesPath, 'fn_monitor.node')
|
||||
: path.join(__dirname, '../../build/Release/fn_monitor.node');
|
||||
|
||||
const nativeModule = require(nativeModulePath);
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Startup Optimization
|
||||
- Lazy load non-critical modules
|
||||
- Use `ready-to-show` event to show window, avoid white screen
|
||||
- Keep preload script minimal
|
||||
|
||||
### Memory Management
|
||||
- Remove event listeners timely
|
||||
- Use `WeakMap` / `WeakSet` to avoid memory leaks
|
||||
- Regularly check renderer process memory usage
|
||||
|
||||
### Rendering Optimization
|
||||
- Use `will-change` CSS property to hint browser optimization
|
||||
- Use virtual scrolling for large lists
|
||||
- Avoid frequent DOM operations
|
||||
|
||||
## Notes
|
||||
|
||||
1. **Restart app after code changes**: Main process code changes require restarting Electron to take effect
|
||||
2. **Context Isolation**: Always keep `contextIsolation: true`
|
||||
3. **ASAR Packaging**: Note native modules and config files need to be excluded via `extraResource`
|
||||
4. **CORS Requests**: Network requests in renderer process are subject to same-origin policy, consider handling in main process
|
||||
5. **File Paths**: Paths after packaging differ from development, use `app.isPackaged` to check environment
|
||||
|
||||
## Error Handling
|
||||
|
||||
```typescript
|
||||
// Main process global error handling
|
||||
process.on('uncaughtException', (error) => {
|
||||
log.error('Uncaught Exception:', error);
|
||||
// Restart app or gracefully exit if necessary
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
log.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
||||
});
|
||||
|
||||
// Renderer process error reporting
|
||||
window.addEventListener('error', (event) => {
|
||||
window.api.reportError(event.error);
|
||||
});
|
||||
```
|
||||
Reference in New Issue
Block a user