Rome JavaScript 工具链示例
Rome JavaScript 工具链示例,包括配置、代码检查、格式化、打包和项目管理
💻 Rome 基础设置 json
🟢 simple
⭐
JavaScript/TypeScript 项目的完整 Rome 工具链设置,包含配置和基本使用
⏱️ 20 min
🏷️ rome, setup, toolchain, configuration
Prerequisites:
Node.js, npm/yarn, Basic JavaScript/TypeScript
// Rome Basic Setup and Configuration
// Rome is an all-in-one JavaScript toolchain
// 1. Installation
// npm install --save-dev rome
// Or: yarn add --dev rome
// Or: pnpm add -D rome
// 2. Initialize Rome in your project
// npx rome init
// 3. rome.json - Main Rome Configuration
{
"$schema": "https://json.schemastore.org/rome",
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentSize": 2,
"lineWidth": 80,
"lineEnding": "lf",
"quoteStyle": "single",
"quoteProperties": "asNeeded",
"trailingComma": "es5",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false,
"jsxQuoteStyle": "double",
"quoteProperties": "preserve"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingComma": "es5",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false
}
},
"typescript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingComma": "es5",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false
}
},
"json": {
"formatter": {
"indentSize": 2,
"lineWidth": 80
}
},
"files": {
"ignore": [
"node_modules/**",
"dist/**",
"build/**",
"*.min.js",
"*.min.css"
]
}
}
// 4. package.json Scripts Integration
{
"name": "my-rome-project",
"version": "1.0.0",
"scripts": {
"lint": "rome check",
"lint:fix": "rome check --apply",
"format": "rome format",
"format:write": "rome format --write",
"ci": "rome ci",
"benchmark": "rome ci --max-diagnostics 50"
},
"devDependencies": {
"rome": "^12.1.0"
}
}
// 5. Example JavaScript File (src/index.js)
import { calculateTotal } from './utils.js';
import './styles.css';
const products = [
{ id: 1, name: 'Laptop', price: 999.99, category: 'electronics' },
{ id: 2, name: 'Mouse', price: 29.99, category: 'electronics' },
{ id: 3, name: 'Keyboard', price: 79.99, category: 'electronics' }
];
function displayProducts() {
const container = document.getElementById('products');
if (!container) {
console.error('Products container not found');
return;
}
const total = calculateTotal(products);
products.forEach(product => {
const element = document.createElement('div');
element.className = 'product-card';
element.innerHTML = `
<h3>${product.name}</h3>
<p>Price: $${product.price.toFixed(2)}</p>
<p>Category: ${product.category}</p>
`;
container.appendChild(element);
});
const totalElement = document.createElement('div');
totalElement.className = 'total';
totalElement.innerHTML = `Total: $${total.toFixed(2)}`;
container.appendChild(totalElement);
}
// Initialize the application
document.addEventListener('DOMContentLoaded', displayProducts);
export { displayProducts, products };
// 6. Example TypeScript File (src/types.ts)
export interface Product {
id: number;
name: string;
price: number;
category: string;
}
export interface CartItem extends Product {
quantity: number;
}
export interface User {
id: string;
name: string;
email: string;
preferences: UserPreferences;
}
export interface UserPreferences {
theme: 'light' | 'dark';
language: string;
notifications: boolean;
}
// 7. Example Utility File (src/utils.js)
export function calculateTotal(products) {
return products.reduce((total, product) => total + product.price, 0);
}
export function formatCurrency(amount, currency = 'USD') {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency
}).format(amount);
}
export function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
// 8. Example CSS File (src/styles.css)
.product-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
margin: 16px;
max-width: 300px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.product-card h3 {
margin: 0 0 8px 0;
color: #333;
}
.product-card p {
margin: 4px 0;
color: #666;
}
.total {
font-size: 18px;
font-weight: bold;
color: #007bff;
margin-top: 16px;
text-align: right;
}
// 9. Rome Ignore File (.romeignore)
# Build outputs
dist/
build/
out/
# Dependencies
node_modules/
# Environment files
.env
.env.local
.env.*.local
# IDE files
.vscode/
.idea/
# OS files
.DS_Store
Thumbs.db
# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Coverage directory used by tools like istanbul
coverage/
# Temporary folders
tmp/
temp/
// 10. Example Test File (tests/utils.test.js)
import { calculateTotal, formatCurrency, debounce } from '../src/utils.js';
describe('Utils', () => {
const products = [
{ id: 1, name: 'Laptop', price: 999.99 },
{ id: 2, name: 'Mouse', price: 29.99 }
];
test('calculateTotal should sum product prices correctly', () => {
const total = calculateTotal(products);
expect(total).toBe(1029.98);
});
test('formatCurrency should format numbers as currency', () => {
expect(formatCurrency(1234.56)).toBe('$1,234.56');
expect(formatCurrency(1234.56, 'EUR')).toBe('€1,234.56');
});
test('debounce should delay function execution', (done) => {
let called = false;
const debouncedFn = debounce(() => {
called = true;
done();
}, 100);
debouncedFn();
expect(called).toBe(false);
});
});
// 11. Project Structure
my-rome-project/
├── src/
│ ├── index.js
│ ├── utils.js
│ ├── types.ts
│ └── styles.css
├── tests/
│ └── utils.test.js
├── public/
│ └── index.html
├── rome.json
├── .romeignore
├── package.json
└── README.md
// 12. Basic HTML File (public/index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rome Example Project</title>
<link rel="stylesheet" href="../src/styles.css">
</head>
<body>
<div class="container">
<h1>Product Catalog</h1>
<div id="products">
<!-- Products will be inserted here by JavaScript -->
</div>
</div>
<script type="module" src="../src/index.js"></script>
</body>
</html>
// 13. Rome CLI Commands Usage
/*
# Check files for linting and formatting issues
npx rome check
# Auto-fix linting issues
npx rome check --apply
# Format files
npx rome format
# Format and write changes to files
npx rome format --write
# Run CI checks (fails if any issues found)
npx rome ci
# Check specific file or directory
npx rome check src/
npx rome check src/index.js
# Format specific file
npx rome format src/utils.js
# Generate configuration file
npx rome init
# Show Rome version
npx rome --version
# Get help
npx rome --help
npx rome check --help
*/
export default { products, calculateTotal, formatCurrency, debounce };
💻 Rome 高级配置 json
🟡 intermediate
⭐⭐⭐⭐
高级 Rome 配置,包括自定义规则、覆盖、性能设置和工作区管理
⏱️ 45 min
🏷️ rome, advanced, configuration, performance
Prerequisites:
Rome basics, JavaScript/TypeScript, CI/CD concepts
// Rome Advanced Configuration Examples
// Advanced configuration patterns for complex projects
// 1. Advanced rome.json Configuration
{
"$schema": "https://json.schemastore.org/rome",
"organizeImports": {
"enabled": true
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentSize": 2,
"lineWidth": 100,
"lineEnding": "lf",
"quoteStyle": "single",
"quoteProperties": "asNeeded",
"trailingComma": "es5",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false,
"jsxQuoteStyle": "double",
"attributePosition": "auto",
"htmlWhitespaceSensitivity": "css",
"vueIndentScriptAndStyle": false,
"proseWrap": "preserve",
"ignore": ["src/generated/**", "**/*.min.js"]
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
// Custom rule configurations
"complexity": {
"noExtraBooleanCast": "error",
"noMultipleSpacesInRegularExpressionLiterals": "error",
"noUselessCatch": "error",
"noWith": "error"
},
"correctness": {
"noUnusedVariables": "error",
"noUndeclaredVariables": "error",
"noUnreachable": "error",
"noUnreachableSuper": "error",
"noConstantCondition": "warn"
},
"security": {
"noGlobalEval": "error",
"noImpliedEval": "error",
"noNewSymbol": "error"
},
"style": {
"noArguments": "error",
"noVar": "error",
"useConst": "error",
"useShorthandArrayType": "error",
"useSingleVarDeclarator": "error",
"noNegationElse": "error",
"useTemplate": "error",
"noCommaOperator": "error"
},
"suspicious": {
"noArrayIndexKey": "warn",
"noAsyncPromiseExecutor": "error",
"noCatchAssign": "error",
"noClassAssign": "error",
"noCompareNegZero": "error",
"noControlCharactersInRegex": "error",
"noDebugger": "error",
"noDuplicateCase": "error",
"noDuplicateClassMembers": "error",
"noDuplicateObjectKeys": "error",
"noDuplicateParameters": "error",
"noEmptyBlockStatements": "error",
"noExplicitAny": "warn",
"noFallthroughSwitchClause": "error",
"noFunctionAssign": "error",
"noGlobalObjectCalls": "error",
"noImportAssign": "error",
"noMisleadingCharacterClass": "error",
"noPrototypeBuiltins": "error",
"noRedeclare": "error",
"noShadowRestrictedNames": "error",
"noUnsafeNegation": "error",
"useGetterReturn": "error",
"useValidTypeof": "error"
},
"nursery": {
"noDuplicateJsxProps": "error",
"noExcessiveNestedTestSuites": "warn",
"noEmptyPattern": "error",
"noImportAssignment": "error",
"noStaticOnlyClass": "error",
"noThisInStatic": "error",
"noUselessFragments": "error",
"useAwait": "error",
"useConsistentArrayType": "error",
"useDefaultParameterLast": "error",
"useEarlyReturn": "error",
"useFlatMap": "error",
"useForOf": "error",
"useImportExtensions": "error",
"useLiteralKeys": "error",
"useNumericLiterals": "error",
"useOptionalChain": "error",
"useRegexLiterals": "error",
"useShorthandAssign": "error",
"useSimplifiedLogicExpression": "error",
"useSortedClasses": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingComma": "es5",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false,
"attributePosition": "auto"
},
"globals": [
"window",
"document",
"console",
"process",
"Buffer"
]
},
"typescript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"trailingComma": "es5",
"semicolons": "asNeeded",
"arrowParentheses": "asNeeded",
"bracketSpacing": true,
"bracketSameLine": false
}
},
"json": {
"formatter": {
"indentSize": 2,
"lineWidth": 100,
"trailingComma": "none"
},
"parser": {
"allowComments": true,
"allowTrailingCommas": true
}
},
"css": {
"formatter": {
"enabled": true,
"indentSize": 2,
"lineWidth": 80
}
},
"files": {
"include": ["src/**/*", "tests/**/*"],
"exclude": [
"node_modules/**",
"dist/**",
"build/**",
"coverage/**",
"*.min.js",
"*.min.css",
"src/generated/**",
"**/*.d.ts"
],
"ignore": [
"vendor/**",
"third-party/**",
"**/*.bundle.js"
]
}
}
// 2. Workspace Configuration for Monorepos
// rome.json (Root)
{
"$schema": "https://json.schemastore.org/rome",
"workspace": {
"enabled": true
},
"files": {
"ignore": [
"node_modules/**",
"dist/**",
"build/**",
"*.d.ts"
]
}
}
// packages/frontend/rome.json
{
"$schema": "https://json.schemastore.org/rome",
"extends": "../rome.json",
"linter": {
"rules": {
"style": {
"noVar": "off"
}
}
},
"javascript": {
"globals": [
"window",
"document",
"console"
]
}
}
// packages/backend/rome.json
{
"$schema": "https://json.schemastore.org/rome",
"extends": "../rome.json",
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "error"
}
}
},
"javascript": {
"globals": [
"process",
"Buffer",
"console",
"global"
]
}
}
// 3. Environment-Specific Configurations
// rome.production.json
{
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "error",
"noDebugger": "error"
},
"correctness": {
"noUnusedVariables": "error"
}
}
}
}
// rome.development.json
{
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off",
"noDebugger": "off"
},
"correctness": {
"noUnusedVariables": "warn"
}
}
},
"formatter": {
"lineWidth": 120
}
}
// 4. Custom Rule Presets
// rome.rules.preset.js
export default {
linter: {
rules: {
// Custom strict preset
complexity: {
noExtraBooleanCast: "error",
noMultipleSpacesInRegularExpressionLiterals: "error",
noUselessCatch: "error"
},
style: {
noVar: "error",
useConst: "error",
useShorthandArrayType: "error"
},
security: {
noGlobalEval: "error",
noImpliedEval: "error"
}
}
}
}
// 5. Performance-Optimized Configuration
{
"$schema": "https://json.schemastore.org/rome",
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentSize": 2,
"lineWidth": 100
},
"linter": {
"enabled": true,
"rules": {
"recommended": false, // Disable recommended rules for performance
"correctness": {
"noUnusedVariables": "error",
"noUndeclaredVariables": "error"
},
"style": {
"useConst": "error",
"noVar": "error"
}
}
},
"files": {
"maxSize": 1000000, // 1MB file size limit
"ignoreUnknown": true, // Ignore unknown file types for performance
"ignore": [
"node_modules/**",
"dist/**",
"build/**",
"*.min.js",
"large-files/**"
]
}
}
// 6. Language-Specific Overrides
{
"linter": {
"rules": {
"style": {
"noVar": "error"
}
}
},
"javascript": {
"linter": {
"rules": {
"style": {
"noVar": "off" // Allow var in legacy JavaScript files
}
}
}
},
"typescript": {
"linter": {
"rules": {
"style": {
"noVar": "error", // Enforce no var in TypeScript
"useConst": "error"
},
"suspicious": {
"noExplicitAny": "warn" // Warn about any types
}
}
}
},
"json": {
"linter": {
"rules": {
"correctness": {
"noDuplicateKeys": "error"
}
}
}
},
"css": {
"linter": {
"rules": {
"nursery": {
"useValidCssValues": "error"
}
}
}
}
}
// 7. File-Specific Configuration
{
"files": {
"include": ["**/*.js", "**/*.ts", "**/*.jsx", "**/*.tsx"]
},
"overrides": [
{
"include": ["**/*.test.js", "**/*.test.ts", "**/*.spec.js", "**/*.spec.ts"],
"linter": {
"rules": {
"suspicious": {
"noExplicitAny": "off" // Allow any in tests
},
"style": {
"useConst": "off" // Allow let in tests for reassignments
}
}
}
},
{
"include": ["**/*.config.js", "**/*.config.ts"],
"linter": {
"rules": {
"suspicious": {
"noGlobalEval": "off" // Allow eval in config files
}
}
}
},
{
"include": ["**/stories/**/*"],
"linter": {
"rules": {
"suspicious": {
"noConsoleLog": "off" // Allow console.log in stories
}
}
}
},
{
"include": ["**/vendor/**/*"],
"linter": {
"enabled": false // Disable linting for vendor files
}
}
]
}
// 8. Integration with CI/CD
// .github/workflows/rome.yml
name: Rome CI
on: [push, pull_request]
jobs:
rome:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Rome check
run: npx rome ci
- name: Format check
run: npx rome ci --max-diagnostics 50
// 9. Pre-commit Hooks with Husky
// package.json
{
"scripts": {
"lint": "rome check",
"lint:fix": "rome check --apply",
"format": "rome format",
"format:write": "rome format --write",
"prepare": "husky install"
},
"devDependencies": {
"rome": "^12.1.0",
"husky": "^8.0.3",
"lint-staged": "^13.2.0"
},
"lint-staged": {
"*.{js,jsx,ts,tsx,json,css}": [
"rome check --apply",
"rome format --write"
]
}
}
// .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
// 10. Custom Rome Scripts
// scripts/rome-ci.js
const { execSync } = require('child_process');
const path = require('path');
function runRomeCI() {
try {
console.log('🔍 Running Rome CI checks...');
// Check for linting issues
execSync('npx rome check', { stdio: 'inherit' });
// Check formatting
execSync('npx rome format --write', { stdio: 'inherit' });
// Run Rome CI command (fails if issues found)
execSync('npx rome ci', { stdio: 'inherit' });
console.log('✅ All Rome checks passed!');
} catch (error) {
console.error('❌ Rome CI checks failed');
process.exit(1);
}
}
if (require.main === module) {
runRomeCI();
}
module.exports = { runRomeCI };
// 11. Performance Monitoring
// scripts/rome-performance.js
const { performance } = require('perf_hooks');
const { execSync } = require('child_process');
function measureRomePerformance() {
console.log('📊 Measuring Rome performance...');
const files = ['src/**/*.js', 'src/**/*.ts'];
// Measure formatting performance
const formatStart = performance.now();
execSync(`npx rome format ${files.join(' ')}`, { stdio: 'pipe' });
const formatEnd = performance.now();
// Measure linting performance
const lintStart = performance.now();
execSync(`npx rome check ${files.join(' ')}`, { stdio: 'pipe' });
const lintEnd = performance.now();
const formatTime = formatEnd - formatStart;
const lintTime = lintEnd - lintStart;
console.log(`📈 Performance Results:`);
console.log(` Formatting: ${formatTime.toFixed(2)}ms`);
console.log(` Linting: ${lintTime.toFixed(2)}ms`);
console.log(` Total: ${(formatTime + lintTime).toFixed(2)}ms`);
return {
formatTime,
lintTime,
totalTime: formatTime + lintTime
};
}
if (require.main === module) {
measureRomePerformance();
}
module.exports = { measureRomePerformance };
💻 Rome 集成模式 javascript
🔴 complex
⭐⭐⭐⭐⭐
Rome 与 IDE、构建工具、测试框架和开发工作流的集成模式
⏱️ 60 min
🏷️ rome, integration, workflow, development
Prerequisites:
Rome basics, JavaScript/TypeScript, CI/CD, IDEs, Testing frameworks
// Rome Integration Patterns with Development Tools
// Comprehensive integration examples for modern development workflows
// 1. VS Code Integration
// .vscode/settings.json
{
"editor.defaultFormatter": "rome.rome",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.rome": true
},
"editor.inlayHints.enabled": true,
"typescript.preferences.importModuleSpecifier": "relative",
"javascript.suggest.autoImports": true,
"typescript.suggest.autoImports": true,
"emmet.includeLanguages": {
"javascript": "javascriptreact",
"typescript": "typescriptreact"
},
"[javascript]": {
"editor.defaultFormatter": "rome.rome"
},
"[typescript]": {
"editor.defaultFormatter": "rome.rome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "rome.rome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "rome.rome"
},
"[json]": {
"editor.defaultFormatter": "rome.rome"
},
"[css]": {
"editor.defaultFormatter": "rome.rome"
}
}
// .vscode/extensions.json
{
"recommendations": [
"rome.rome",
"bradlc.vscode-tailwindcss",
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-next",
"formulahendry.auto-rename-tag",
"christian-kohler.path-intellisense",
"ms-vscode.vscode-json"
]
}
// .vscode/tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Rome: Check",
"type": "shell",
"command": "npx",
"args": ["rome", "check"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
}
},
{
"label": "Rome: Format",
"type": "shell",
"command": "npx",
"args": ["rome", "format", "--write"],
"group": "build",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
}
},
{
"label": "Rome: CI",
"type": "shell",
"command": "npx",
"args": ["rome", "ci"],
"group": "test",
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
}
}
]
}
// 2. Webpack Integration
// webpack.config.js
const { execSync } = require('child_process');
module.exports = (env, argv) => {
const isDevelopment = !argv.mode || argv.mode === 'development';
// Run Rome on watch mode in development
if (isDevelopment && env.watch !== false) {
console.log('🔍 Running Rome in watch mode...');
// Run Rome check in background
const romeProcess = require('child_process').spawn('npx', ['rome', 'check', '--watch'], {
stdio: 'inherit',
detached: true
});
romeProcess.unref();
}
return {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
module: {
rules: [
{
test: /\\.[jt]sx?$/,
exclude: /node_modules/,
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
decorators: true
},
transform: {
react: {
runtime: 'automatic'
}
},
target: 'es2020'
}
}
}
},
{
test: /\\.css$/i,
type: 'asset/resource'
}
]
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: {
'@': path.resolve(__dirname, 'src')
}
},
plugins: [
{
apply: (compiler) => {
if (compiler.hooks) {
// Run Rome formatter before emitting files
compiler.hooks.emit.tapAsync('RomeFormatter', async (compilation) => {
console.log('🎨 Running Rome formatter on output...');
// You would implement actual Rome API usage here
// This is a conceptual example
});
}
}
}
],
devServer: {
static: {
directory: path.join(__dirname, 'public')
},
port: 3000,
hot: true,
client: {
overlay: true
}
},
mode: argv.mode || 'development',
devtool: isDevelopment ? 'eval-source-map' : 'source-map'
};
};
// 3. Vite Integration
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { execSync } from 'child_process';
// Custom Vite plugin for Rome integration
function romePlugin() {
return {
name: 'rome-plugin',
configureServer(server) {
server.ws.on('rome:check', () => {
try {
const result = execSync('npx rome check', { encoding: 'utf8' });
server.ws.send({
type: 'rome:result',
data: { success: true, result }
});
} catch (error) {
server.ws.send({
type: 'rome:result',
data: { success: false, error: error.message }
});
}
});
server.ws.on('rome:format', () => {
try {
execSync('npx rome format --write', { encoding: 'utf8' });
server.ws.send({
type: 'rome:result',
data: { success: true, action: 'formatted' }
});
} catch (error) {
server.ws.send({
type: 'rome:result',
data: { success: false, error: error.message }
});
}
});
},
buildStart() {
console.log('🔍 Running Rome check before build...');
try {
execSync('npx rome check', { stdio: 'inherit' });
} catch (error) {
console.error('❌ Rome check failed, aborting build');
process.exit(1);
}
}
};
}
export default defineConfig({
plugins: [
react(),
romePlugin()
],
build: {
minify: 'terser',
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash', 'axios']
}
}
}
},
server: {
port: 3000,
open: true
},
optimizeDeps: {
include: ['react', 'react-dom']
}
});
// 4. Jest Integration
// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
moduleNameMapping: {
'^@/(.*)$': '<rootDir>/src/$1'
},
transform: {
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest'
},
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/index.tsx'
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
},
testMatch: [
'<rootDir>/src/**/__tests__/**/*.(js|jsx|ts|tsx)',
'<rootDir>/src/**/*.(test|spec).(js|jsx|ts|tsx)'
],
transformIgnorePatterns: [
'node_modules/(?!(rome)/)'
]
};
// setupTests.ts
import '@testing-library/jest-dom';
// Mock console methods for cleaner test output
global.console = {
...console,
log: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn()
};
// Custom Jest matcher for Rome compliance
expect.extend({
toComplyWithRome(received) {
try {
require('child_process').execSync(`npx rome check ${received}`, { encoding: 'utf8' });
return {
message: () => `expected ${received} not to comply with Rome rules`,
pass: true
};
} catch (error) {
return {
message: () => `expected ${received} to comply with Rome rules`,
pass: false
};
}
}
});
declare global {
namespace jest {
interface Matchers<R> {
toComplyWithRome(): R;
}
}
}
// 5. Cypress Integration
// cypress/support/e2e.js
import '@testing-library/cypress/add-commands';
// Rome compliance command
Cypress.Commands.add('checkRomeCompliance', (filePath) => {
cy.task('checkRome', { filePath }).then((result) => {
if (!result.success) {
cy.log('❌ Rome check failed:', result.errors);
} else {
cy.log('✅ Rome check passed');
}
return result;
});
});
// cypress/plugins/index.js
module.exports = (on, config) => {
on('task', {
checkRome({ filePath }) {
try {
const { execSync } = require('child_process');
const result = execSync(`npx rome check ${filePath}`, { encoding: 'utf8' });
return { success: true, result };
} catch (error) {
return { success: false, error: error.message };
}
},
formatRome({ filePath }) {
try {
const { execSync } = require('child_process');
execSync(`npx rome format --write ${filePath}`, { encoding: 'utf8' });
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
});
};
// 6. Storybook Integration
// .storybook/main.ts
import type { StorybookConfig } from '@storybook/react-vite';
const config: StorybookConfig = {
stories: ['../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-essentials',
'@storybook/addon-interactions'
],
framework: {
name: '@storybook/react-vite',
options: {}
},
viteFinal: async (config) => {
// Add Rome integration
config.server = {
...config.server,
fs: {
allow: ['..']
}
};
// Custom plugin for Rome
config.plugins = config.plugins || [];
config.plugins.push({
name: 'rome-storybook',
configureServer(server) {
server.ws.on('rome:check', () => {
try {
const { execSync } = require('child_process');
const result = execSync('npx rome check', { encoding: 'utf8' });
server.ws.send({
type: 'rome:result',
data: { success: true, result }
});
} catch (error) {
server.ws.send({
type: 'rome:result',
data: { success: false, error: error.message }
});
}
});
}
});
return config;
}
};
export default config;
// 7. GitHub Actions Advanced Workflow
// .github/workflows/rome-advanced.yml
name: Rome Advanced CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
rome:
name: Rome Checks
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Cache Rome cache
uses: actions/cache@v3
with:
path: ~/.cache/rome
key: ${{ runner.os }}-rome-${{ hashFiles('**/rome.json') }}
restore-keys: |
${{ runner.os }}-rome-
- name: Run Rome check
run: npx rome ci --max-diagnostics 50
- name: Check formatting
run: npx rome format --write
- name: Upload coverage reports
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
rome-performance:
name: Rome Performance
runs-on: ubuntu-latest
needs: rome
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Measure Rome performance
run: |
echo "📊 Measuring Rome performance..."
time npx rome check src/ > /dev/null
time npx rome format src/ > /dev/null
rome-benchmarks:
name: Rome Benchmarks
runs-on: ubuntu-latest
needs: rome
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run Rome benchmarks
run: |
echo "🏃 Running Rome benchmarks..."
npx rome ci --max-diagnostics 100 > rome-report.txt
echo "::set-output name=report::$(cat rome-report.txt)"
- name: Upload benchmark results
uses: actions/upload-artifact@v3
with:
name: rome-benchmark-report
path: rome-report.txt
// 8. Development Workflow Integration
// scripts/dev-workflow.js
const { execSync, spawn } = require('child_process');
const chokidar = require('chokidar');
const path = require('path');
class RomeDevWorkflow {
constructor() {
this.watcher = null;
this.romeProcess = null;
}
start() {
console.log('🚀 Starting Rome development workflow...');
// Initial Rome check
this.runRomeCheck();
// Start file watcher
this.startWatcher();
// Start Rome daemon
this.startRomeDaemon();
console.log('✅ Rome development workflow started');
console.log('📝 Rome will auto-check and format on file changes');
}
runRomeCheck() {
try {
console.log('🔍 Running Rome check...');
execSync('npx rome check', { stdio: 'inherit' });
} catch (error) {
console.log('⚠️ Rome check found issues');
}
}
runRomeFormat() {
try {
console.log('🎨 Running Rome format...');
execSync('npx rome format --write', { stdio: 'inherit' });
} catch (error) {
console.log('❌ Rome format failed:', error.message);
}
}
startWatcher() {
const watchPatterns = [
'src/**/*.{js,jsx,ts,tsx,json,css}',
'tests/**/*.{js,jsx,ts,tsx}',
'*.config.{js,ts,json}'
];
this.watcher = chokidar.watch(watchPatterns, {
ignored: ['node_modules/**', 'dist/**', '.git/**'],
persistent: true
});
// Debounce file changes
let timeout;
this.watcher.on('change', (filePath) => {
console.log(`📝 File changed: ${filePath}`);
clearTimeout(timeout);
timeout = setTimeout(() => {
this.runRomeCheck();
}, 500);
});
this.watcher.on('add', (filePath) => {
console.log(`➕ File added: ${filePath}`);
setTimeout(() => {
this.runRomeFormat();
}, 100);
});
}
startRomeDaemon() {
this.romeProcess = spawn('npx', ['rome', 'check', '--watch'], {
stdio: 'inherit',
detached: true
});
this.romeProcess.unref();
}
stop() {
console.log('🛑 Stopping Rome development workflow...');
if (this.watcher) {
this.watcher.close();
}
if (this.romeProcess) {
this.romeProcess.kill();
}
console.log('✅ Rome development workflow stopped');
}
}
// CLI usage
if (require.main === module) {
const workflow = new RomeDevWorkflow();
workflow.start();
// Handle graceful shutdown
process.on('SIGINT', () => {
workflow.stop();
process.exit(0);
});
process.on('SIGTERM', () => {
workflow.stop();
process.exit(0);
});
}
module.exports = RomeDevWorkflow;
// 9. Custom Rome Extensions
// rome.plugins/my-plugin.js
export default {
name: 'my-rome-plugin',
rules: {
customRule: {
level: 'error',
options: {
customOption: 'default'
}
}
},
// Custom formatter
format: {
formatWithErrors: false,
indentSize: 2
}
};
// 10. Team Collaboration Setup
// rome.team.json
{
"extends": "./rome.json",
"linter": {
"rules": {
"style": {
"noVar": "error",
"useConst": "error"
}
}
},
"files": {
"include": ["team/**/*.js", "team/**/*.ts"],
"ignore": ["team/vendor/**/*"]
}
}
export { RomeDevWorkflow };