Skip to content

@xcons/cli-thingsboard - Widget Build Kılavuzu

Bu dokümantasyon, XCONS ThingsBoard CLI ile widget projelerini derleme işlemlerini detaylı olarak açıklar.

Widget Build Komutu

bash
xcons-thingsboard widget build [source] [options]

Parametreler

  • source (isteğe bağlı): Widget proje dizini. Belirtilmezse mevcut dizin kullanılır.

Seçenekler

  • -p, --production: Üretim için optimize edilmiş derleme
  • -d, --debug: Detaylı debug çıktısı ile derleme

Temel Kullanım

Geliştirme Derlemesi

bash
# Mevcut dizinde widget'ı derle
xcons-thingsboard widget build

# Belirli dizindeki widget'ı derle
xcons-thingsboard widget build ./my-widget

# Debug bilgilerini göstererek derle
xcons-thingsboard widget build --debug

Üretim Derlemesi

bash
# Üretim için optimize edilmiş derleme
xcons-thingsboard widget build --production

# Belirli dizin için üretim derlemesi
xcons-thingsboard widget build ./my-widget --production

# Üretim derlemesi debug ile
xcons-thingsboard widget build --production --debug

XCONS Build Engine

XCONS CLI, dahili build engine kullanır ve otomatik optimizasyon sağlar.

Build Pipeline

  1. Proje Validasyonu: .xcon/config.json kontrolü
  2. TypeScript Derleme: Decorator desteği ile
  3. Template İşleme: HTML template'lerin çıkarılması
  4. CSS İşleme: Style dosyalarının işlenmesi
  5. External Kütüphaneler: Harici bağımlılık yönetimi
  6. ThingsBoard Wrapper: Otomatik entegrasyon wrapper'ı
  7. Optimizasyon: Kod minifikasyonu ve sıkıştırma

Build Çıktıları

Derleme sonucunda dist/ dizininde şu dosyalar oluşur:

dist/
├── widget.js                 # Ana widget kodu (minified)
├── widget.template.html       # HTML template
├── widget.styles.css          # CSS stilleri
├── widget.metadata.json       # Widget meta verileri
└── widget.resources.json      # Harici kaynak bilgileri (varsa)

Build Konfigürasyonu

.xcon/config.json Build Ayarları

json
{
  "build": {
    "entry": "index.ts",
    "sourceRoot": "src",
    "outputFilename": "widget.js",
    "outputPath": "dist",
    "tsConfig": "tsconfig.json",
    "externals": {
      "chart.js": "Chart",
      "lodash": "_",
      "moment": "moment"
    }
  }
}

Alan Açıklamaları:

  • entry: Ana TypeScript dosyası
  • sourceRoot: Kaynak kod dizini
  • outputFilename: Çıktı JS dosya adı
  • outputPath: Çıktı dizini
  • tsConfig: TypeScript konfigürasyon dosyası
  • externals: Harici kütüphane eşlemeleri

TypeScript Konfigürasyonu

json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": false,
    "declaration": false,
    "outDir": "./dist",
    "rootDir": "./src",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "module": "CommonJS",
    "sourceMap": false
  }
}

Widget Kaynak Kodları

Ana Widget Dosyası (src/index.ts)

typescript
import { Widget, property, computed } from '@xcons/widget';

@Widget({
    widgetName: 'Temperature Monitor',
    widgetDescription: 'Real-time temperature monitoring widget',
    widgetVersion: '1.0.0',
    templateUrl: './index.html',
    styleUrls: ['./style.css'],
    resources: [
        {
            type: 'js',
            url: 'https://cdn.jsdelivr.net/npm/chart.js',
            name: 'Chart.js Library'
        }
    ],
    selector: 'tb-temperature-monitor'
})
export default class TemperatureMonitor {
    @property()
    public data: any[] = [];

    @property()
    public temperature: number = 0;

    @property()
    public isLoading: boolean = false;

    @computed()
    get temperatureStatus(): string {
        if (this.temperature < 20) return 'Cold';
        if (this.temperature > 30) return 'Hot';
        return 'Normal';
    }

    onInit() {
        console.log('Temperature Monitor initialized');
        this.initializeChart();
    }

    onDataUpdated() {
        this.processData();
        this.updateChart();
    }

    private initializeChart() {
        // Chart.js başlatma kodu
    }

    private processData() {
        if (this.data.length > 0) {
            const latest = this.data[this.data.length - 1];
            this.temperature = latest.temperature || 0;
        }
    }

    private updateChart() {
        // Chart güncelleme kodu
    }

    onDestroy() {
        console.log('Temperature Monitor destroyed');
    }
}

HTML Template (src/index.html)

html
<div class="temperature-widget">
    <div class="header">
        <h3 x:text="'Temperature Monitor'"></h3>
        <div class="status" x:text="temperatureStatus" x:class:cold="temperature < 20" x:class:hot="temperature > 30"></div>
    </div>
    
    <div class="content">
        <div class="current-temp">
            <span class="value" x:text="temperature"></span>
            <span class="unit">°C</span>
        </div>
        
        <div class="chart-container">
            <canvas id="temperatureChart"></canvas>
        </div>
    </div>
    
    <div class="footer" x:show="isLoading">
        <span>Loading...</span>
    </div>
</div>

CSS Stilleri (src/style.css)

css
.temperature-widget {
    padding: 16px;
    height: 100%;
    display: flex;
    flex-direction: column;
    font-family: 'Roboto', sans-serif;
}

.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 16px;
}

.header h3 {
    margin: 0;
    color: #333;
    font-size: 18px;
    font-weight: 500;
}

.status {
    padding: 4px 12px;
    border-radius: 16px;
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    background-color: #4caf50;
    color: white;
}

.status.cold {
    background-color: #2196f3;
}

.status.hot {
    background-color: #f44336;
}

.content {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.current-temp {
    text-align: center;
    margin-bottom: 24px;
}

.current-temp .value {
    font-size: 48px;
    font-weight: 300;
    color: #333;
}

.current-temp .unit {
    font-size: 18px;
    color: #666;
    margin-left: 4px;
}

.chart-container {
    flex: 1;
    position: relative;
}

.footer {
    text-align: center;
    padding: 8px;
    color: #666;
    font-size: 14px;
}

Build Süreçleri

Geliştirme Build

bash
xcons-thingsboard widget build --debug

Çıktı Örneği:

[BUILD] Starting widget build process...
[BUILD] Project information:
[BUILD] Widget Type: timeseries
[BUILD] Provider: thingsboard
[BUILD] Entry: src/index.ts
[BUILD] Output: dist/widget.js
[DEBUG] Project validation passed
Reading project configuration...
Processing widget...
[WIDGET] Processing widget file: /project/src/index.ts
[WIDGET] No externals configuration found
[PACK] Checking dependencies...
[PACK] All dependencies are already installed
[PACK] build successful
[PACK] Compiled 1 assets
[PACK] processed 3 TypeScript modules
[WIDGET] Applying ThingsBoard wrapper to built widget...
Writing resource files...
Build completed successfully!
Output: /project/dist/widget.js (45.23 KB)
Build time: 1247ms

Üretim Build

bash
xcons-thingsboard widget build --production

Özellikler:

  • Kod minifikasyonu
  • Dead code elimination
  • Sıkıştırma optimizasyonu
  • Source map üretimi (opsiyonel)
  • Console.log temizleme

Harici Kütüphane Yönetimi

Externals Konfigürasyonu

json
{
  "build": {
    "externals": {
      "chart.js": "Chart",
      "lodash": "_",
      "moment": "moment",
      "jquery": "$",
      "d3": "d3"
    }
  }
}

Widget'ta Kütüphane Tanımlama

typescript
@Widget({
    resources: [
        {
            type: 'js',
            url: 'https://cdn.jsdelivr.net/npm/chart.js@4.0.0/dist/chart.min.js',
            name: 'Chart.js Library',
            order: 1
        },
        {
            type: 'css',
            url: 'https://cdn.jsdelivr.net/npm/chart.js@4.0.0/dist/chart.min.css',
            name: 'Chart.js Styles',
            order: 2
        }
    ]
})

Otomatik XCONS Kütüphaneleri

Build süreci otomatik olarak şu kütüphaneleri ekler:

typescript
// Otomatik eklenen kaynaklar
resources: [
    {
        name: 'XCONS Common Library',
        type: 'js',
        url: 'https://unpkg.com/@xcons/common@latest/core.js',
        order: 1
    },
    {
        name: 'XCONS Widget Core Library', 
        type: 'js',
        url: 'https://unpkg.com/@xcons/widget@latest/core.js',
        order: 2
    }
]

Build Optimizasyonları

Üretim Optimizasyonları

bash
xcons-thingsboard widget build --production

Uygulanan Optimizasyonlar:

  • Terser Minification: Kod sıkıştırma
  • Dead Code Elimination: Kullanılmayan kod temizleme
  • Tree Shaking: Kullanılmayan import'ların temizlenmesi
  • Console.log Removal: Production'da console çıktılarını kaldırma
  • CSS Minification: Stil dosyalarının sıkıştırılması
  • HTML Minification: Template dosyalarının optimize edilmesi

Dosya Boyutu Optimizasyonu

json
{
  "build": {
    "externals": {
      "chart.js": "Chart",
      "lodash": "_"
    }
  }
}

Bu ayar ile:

  • chart.js (700KB) → Bundle'a dahil edilmez, CDN'den yüklenir
  • lodash (530KB) → Bundle'a dahil edilmez, CDN'den yüklenir
  • Toplam tasarruf: ~1.2MB

Debug ve Troubleshooting

Debug Modu

bash
xcons-thingsboard widget build --debug

Debug Çıktısı İçerir:

  • Proje validasyon detayları
  • TypeScript derleme adımları
  • External kütüphane yönetimi
  • Template ve CSS işleme
  • Dosya boyutu bilgileri
  • Build süre analizi

Yaygın Build Hataları

1. Eksik .xcon/config.json

Hata:

Error: .xcon/config.json not found

Çözüm:

bash
# Widget projesi değil, yeni widget oluşturun
xcons-thingsboard widget create my-widget

2. TypeScript Derleme Hatası

Hata:

[PACK] TypeScript compilation error: Cannot find module '@xcons/widget'

Çözüm:

bash
# Bağımlılıkları yükleyin
npm install

# Veya eksik paketi yükleyin
npm install @xcons/widget

3. External Kütüphane Hatası

Hata:

[PACK] External modules processed: 0
Module not found: chart.js

Çözüm:

json
// .xcon/config.json
{
  "build": {
    "externals": {
      "chart.js": "Chart"
    }
  }
}

Widget decorator'da:

typescript
@Widget({
    resources: [
        {
            type: 'js',
            url: 'https://cdn.jsdelivr.net/npm/chart.js',
            name: 'Chart.js Library'
        }
    ]
})

4. Template/CSS Bulunamadı

Hata:

[TEMPLATE] Template file not found: ./index.html

Çözüm:

bash
# Dosyaların varlığını kontrol edin
ls -la src/
# index.ts, index.html, style.css olmalı

# Decorator'da doğru yolu belirtin
@Widget({
    templateUrl: './index.html',
    styleUrls: ['./style.css']
})

Build Performance

Build Süresi Analizi

bash
# Time analizi ile
time xcons-thingsboard widget build --production

Memory Usage

bash
# Memory limit artırma
NODE_OPTIONS="--max-old-space-size=4096" xcons-thingsboard widget build --production

Cache Temizleme

bash
# NPM cache temizle
npm cache clean --force

# Node modules'u yeniden yükle
rm -rf node_modules
npm install

Build Scripts

Package.json Scripts

json
{
  "scripts": {
    "build": "xcons-thingsboard widget build",
    "build:prod": "xcons-thingsboard widget build --production",
    "build:debug": "xcons-thingsboard widget build --debug",
    "build:watch": "nodemon --exec \"xcons-thingsboard widget build --debug\" --watch src --ext ts,html,css",
    "clean": "rm -rf dist",
    "prebuild": "npm run clean"
  }
}

Watch Mode (Manuel)

bash
# Nodemon ile otomatik build
npm install -g nodemon

# Watch komutu
nodemon --exec "xcons-thingsboard widget build --debug" --watch src --ext ts,html,css

Continuous Integration

GitHub Actions

yaml
name: Widget Build

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    
    strategy:
      matrix:
        node-version: [18.x, 20.x]
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm install
    
    - name: Build widget
      run: npx @xcons/cli-thingsboard widget build --production
    
    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: widget-build-${{ matrix.node-version }}
        path: dist/

Jenkins Pipeline

groovy
pipeline {
    agent any
    
    tools {
        nodejs '18'
    }
    
    stages {
        stage('Install Dependencies') {
            steps {
                sh 'npm install'
            }
        }
        
        stage('Build Widget') {
            steps {
                sh 'npx @xcons/cli-thingsboard widget build --production'
            }
        }
        
        stage('Test Build') {
            steps {
                sh 'test -f dist/widget.js'
                sh 'test -f dist/widget.metadata.json'
            }
        }
        
        stage('Archive Artifacts') {
            steps {
                archiveArtifacts artifacts: 'dist/**/*', fingerprint: true
            }
        }
    }
}

Sonraki Adımlar

Build işlemi tamamlandıktan sonra:

  1. Widget Kurulum - Widget'ı ThingsBoard'a yükleme
  2. Widget Listeleme - Sunucudaki widget'ları görüntüleme
  3. Widget Silme - Widget'ları sunucudan kaldırma

Build işlemi tamamlandı. Widget'ınız ThingsBoard'a yüklenmeye hazır!