Size Optimization

TELA Size Optimization Guide

Advanced techniques for optimizing TELA applications to meet blockchain size limits while maintaining full functionality.

Supported File Types (from source code):

  • TELA-STATIC-1 (generic files)
  • TELA-HTML-1 (HTML documents)
  • TELA-JSON-1 (JSON data)
  • TELA-CSS-1 (CSS stylesheets)
  • TELA-JS-1 (JavaScript code)
  • TELA-MD-1 (Markdown documents)
  • TELA-GO-1 (Go source code)
📏

Critical Limit: DERO blockchain enforces an 18KB maximum per file. These optimization techniques help you stay well under this limit.

Size Constraints Overview (From Source Code)

File Size Limits (Exact Constants from parse.go)

  • TELA-DOC-1 content: 18.00KB maximum (MAX_DOC_CODE_SIZE = 18.0)
  • TELA-DOC-1 total: 19.20KB maximum including headers (MAX_DOC_INSTALL_SIZE = 19.2)
  • TELA-INDEX-1: 11.64KB maximum (MAX_INDEX_INSTALL_SIZE = 11.64)
  • TELA-INDEX-1 recommended: 9KB for updatable contracts (from documentation)
  • Shard size: 17,500 bytes exactly (SHARD_SIZE = 17500)
⚠️

Actual Error Messages from parse.go:

  • "docCode size is to large, max %.2fKB (%.5f)"
  • "DOC SC size is to large, max %.2fKB (%.5f)"
  • "contract exceeds max INDEX install size by %.2fKB"

Code Minification Techniques

Variable Name Optimization

// ❌ Verbose Code (Wastes Bytes)
function calculateDEROAmount(atomicUnits) {
    if (atomicUnits === null || atomicUnits === undefined) {
        return '0.000000 DERO';
    }
    const deroAmount = parseFloat(atomicUnits) / 1000000000000;
    return deroAmount.toFixed(6) + ' DERO';
}
 
// ✅ Optimized Code (Saves Bytes)
function calcDERO(a) {
    return a ? (parseFloat(a)/1e12).toFixed(6)+' DERO' : '0.000000 DERO';
}

Savings: 47 bytes → 28 bytes (40% reduction)

String Concatenation Optimization

// ❌ Multiple Concatenations (Inefficient)
var html = '<div>';
html += '<h1>' + title + '</h1>';
html += '<p>' + content + '</p>';
html += '</div>';
 
// ✅ Single Concatenation (Efficient)
var html = '<div><h1>' + title + '</h1><p>' + content + '</p></div>';

Savings: 4 statements → 1 statement (reduces overhead)

Function Compression

// ❌ Verbose Function (127 bytes)
function formatHashForDisplay(hashValue, displayLength) {
    if (!hashValue || hashValue.length === 0) {
        return 'No hash available';
    }
    if (displayLength && hashValue.length > displayLength * 2) {
        return hashValue.substring(0, displayLength) + '...' + 
               hashValue.substring(hashValue.length - displayLength);
    }
    return hashValue;
}
 
// ✅ Compressed Function (64 bytes)
function fmtHash(h, l) {
    l = l || 8;
    return !h ? 'N/A' : h.length > l*2 ? h.substring(0,l)+'...'+h.substring(h.length-l) : h;
}

Savings: 127 bytes → 64 bytes (50% reduction)

Advanced Optimization Strategies

Reusable Style Objects

// ❌ Repeated Inline Styles (Wastes Space)
function renderCard1() {
    return '<div style="background:rgba(0,0,0,0.2);border:1px solid rgba(82,200,219,0.3);padding:1.5rem;border-radius:8px;">Card 1</div>';
}
 
function renderCard2() {
    return '<div style="background:rgba(0,0,0,0.2);border:1px solid rgba(82,200,219,0.3);padding:1.5rem;border-radius:8px;">Card 2</div>';
}
 
// ✅ Shared Style Constants (Efficient)
var cardStyle = 'background:rgba(0,0,0,0.2);border:1px solid rgba(82,200,219,0.3);padding:1.5rem;border-radius:8px;';
 
function renderCard1() {
    return '<div style="' + cardStyle + '">Card 1</div>';
}
 
function renderCard2() {
    return '<div style="' + cardStyle + '">Card 2</div>';
}

Template Compression

// ❌ Multi-line Templates (Causes Deployment Errors + Wastes Space)
var template = `
    <div class="enhanced-card">
        <div class="card-header">
            <h2 style="color: #52c8db; font-size: 1.6rem;">
                ${title}
            </h2>
        </div>
        <div class="card-content">
            ${content}
        </div>
    </div>
`;
 
// ✅ Compressed Single-line (Deployment Safe + Space Efficient)
var template = '<div class="enhanced-card"><div class="card-header"><h2 style="color:#52c8db;font-size:1.6rem;">' + title + '</h2></div><div class="card-content">' + content + '</div></div>';

Object Property Shortening

// ❌ Long Property Names
var configuration = {
    applicationName: 'My TELA App',
    connectionTimeout: 30000,
    retryAttempts: 3,
    debugMode: false
};
 
// ✅ Short Property Names
var cfg = {
    name: 'My TELA App',
    timeout: 30000,
    retries: 3,
    debug: false
};

Real-World Optimization Examples

Before: Unoptimized Module (22KB - Too Large)

(function() {
    'use strict';
    
    var blockchainExplorerConfiguration = {
        applicationName: 'DERO Blockchain Explorer',
        connectionTimeout: 30000,
        maximumRetryAttempts: 3,
        debugModeEnabled: false,
        defaultPageSize: 10
    };
    
    function formatDEROAmountForDisplay(atomicUnits, decimalPlaces) {
        if (atomicUnits === null || atomicUnits === undefined) {
            return '0.000000 DERO';
        }
        var deroAmount = parseFloat(atomicUnits) / 1000000000000;
        return deroAmount.toFixed(decimalPlaces || 6) + ' DERO';
    }
    
    function renderBlockInformationCard(blockData) {
        var htmlTemplate = `
            <div class="enhanced-card">
                <div class="card-header">
                    <h2 style="color: #52c8db; font-size: 1.6rem; font-weight: 700;">
                        Block ${blockData.height}
                    </h2>
                </div>
                <div class="card-content">
                    <div class="stats-grid">
                        <div class="stat-card">
                            <div class="stat-value">${blockData.height}</div>
                            <div class="stat-label">Height</div>
                        </div>
                    </div>
                </div>
            </div>
        `;
        return htmlTemplate;
    }
    
    window.BlockchainExplorer = {
        configuration: blockchainExplorerConfiguration,
        formatDEROAmount: formatDEROAmountForDisplay,
        renderBlockCard: renderBlockInformationCard
    };
})();

After: Optimized Module (8KB - Deployment Ready)

({
    name: 'explorer',
    v: '1.0.0',
    cfg: {name: 'DERO Explorer', timeout: 30000, retries: 3, debug: false, pageSize: 10},
    
    fmtDERO: function(a, d) {
        return a ? (parseFloat(a)/1e12).toFixed(d||6)+' DERO' : '0.000000 DERO';
    },
    
    renderBlock: function(b) {
        var s = 'background:rgba(0,0,0,0.2);border:1px solid rgba(82,200,219,0.3);padding:1.5rem;border-radius:8px;';
        return '<div style="' + s + '"><div style="color:#52c8db;font-size:1.6rem;font-weight:700;">Block ' + b.height + '</div><div style="' + s + 'text-align:center;"><div style="font-size:1.8rem;color:#52c8db;">' + b.height + '</div><div style="color:#b3b3b3;font-size:0.9rem;">HEIGHT</div></div></div>';
    }
});

Result: 22KB → 8KB (64% reduction)

Automated Optimization Tools

Compression Script

#!/bin/bash
# TELA optimization script
 
echo "🔧 Optimizing TELA files for deployment..."
 
for file in *.js; do
    echo "Processing $file..."
    
    # Get original size
    original_size=$(wc -c < "$file")
    
    # Remove console statements
    sed -i '' '/console\./d' "$file"
    
    # Compress whitespace
    sed -i '' 's/[[:space:]]\+/ /g' "$file"
    
    # Remove empty lines
    sed -i '' '/^[[:space:]]*$/d' "$file"
    
    # Get new size
    new_size=$(wc -c < "$file")
    saved=$((original_size - new_size))
    
    echo "  $file: $original_size → $new_size bytes (saved $saved bytes)"
    
    # Check if still too large
    if [ $new_size -gt 18000 ]; then
        echo "  ⚠️  Still too large! Manual optimization needed."
    else
        echo "  ✅ Ready for deployment"
    fi
done

Size Monitoring

// Monitor file sizes during development
function checkFileSizes() {
    const files = ['main.js', 'styles.css', 'index.html'];
    
    files.forEach(async (filename) => {
        try {
            const response = await fetch(filename);
            const text = await response.text();
            const size = new Blob([text]).size;
            
            console.log(`📏 ${filename}: ${size} bytes`);
            
            if (size > 18000) {
                console.warn(`⚠️ ${filename} too large for TELA deployment!`);
            } else if (size > 16000) {
                console.warn(`⚠️ ${filename} approaching size limit`);
            } else {
                console.log(`✅ ${filename} size OK`);
            }
        } catch (error) {
            console.error(`Failed to check ${filename}:`, error);
        }
    });
}
 
// Run during development
checkFileSizes();

Optimization Strategies by File Type

JavaScript Files

  1. Variable Name Shortening

    // Before: descriptive names
    var currentBlockHeight = 0;
    var transactionHashList = [];
     
    // After: abbreviated names  
    var h = 0;     // height
    var txs = [];  // transactions
  2. Function Combination

    // Before: separate functions
    function validateInput(input) { return input !== null; }
    function processInput(input) { return input.toString(); }
    function formatInput(input) { return input.toUpperCase(); }
     
    // After: combined function
    function process(i) { return i ? i.toString().toUpperCase() : ''; }
  3. Inline Simple Functions

    // Before: separate helper
    function isValidHash(hash) { return hash && hash.length === 64; }
     
    // After: inline check
    if (hash && hash.length === 64) { /* ... */ }

CSS Files

  1. Property Shorthand

    /* Before: individual properties */
    .element {
        margin-top: 1rem;
        margin-right: 0;
        margin-bottom: 1rem;
        margin-left: 0;
    }
     
    /* After: shorthand */
    .element {
        margin: 1rem 0;
    }
  2. Color Optimization

    /* Before: verbose colors */
    color: rgba(255, 255, 255, 1);
    background: rgba(0, 0, 0, 0.2);
     
    /* After: optimized */
    color: #fff;
    background: rgba(0,0,0,.2);

HTML Files

  1. Attribute Minimization

    <!-- Before: verbose attributes -->
    <div class="container" id="main-container" style="display: block;">
     
    <!-- After: minimal attributes -->
    <div class="container" id="main">
  2. Whitespace Removal

    <!-- Before: formatted HTML -->
    <div class="card">
        <h2>Title</h2>
        <p>Content</p>
    </div>
     
    <!-- After: compressed HTML -->
    <div class="card"><h2>Title</h2><p>Content</p></div>

Module Organization Strategies

Single File vs Multi-Module

When to Use Single File (< 18KB)

// ✅ Simple applications - keep everything together
({
    name: 'simple-app',
    version: '1.0.0',
    
    // All functionality in one file
    init: function() { /* ... */ },
    render: function() { /* ... */ },
    handleEvents: function() { /* ... */ }
});

When to Split into Modules (> 18KB)

// ✅ Complex applications - split by functionality
 
// File 1: core.js (15KB)
({
    name: 'app-core',
    version: '1.0.0',
    init: function() { /* core logic */ }
});
 
// File 2: ui.js (12KB)
({
    name: 'app-ui', 
    version: '1.0.0',
    render: function() { /* UI logic */ }
});
 
// File 3: data.js (10KB)
({
    name: 'app-data',
    version: '1.0.0',
    fetch: function() { /* data logic */ }
});

Shared Utilities Pattern

// Create shared utilities to avoid duplication across modules
({
    name: 'shared-utils',
    version: '1.0.0',
    
    // Common formatting functions
    fmt: {
        num: function(n) { return (n||0).toLocaleString(); },
        hash: function(h, l) { l=l||8; return !h?'-':h.length>l*2?h.substring(0,l)+'...'+h.substring(h.length-l):h; },
        dero: function(a) { return a?(parseFloat(a)/1e12).toFixed(5)+' DERO':'0.00000 DERO'; },
        time: function(t) { var d=Math.floor((Date.now()/1000-t)/60); return d<1?'now':d<60?d+'m':Math.floor(d/60)+'h'; }
    },
    
    // Common DOM helpers
    dom: {
        get: function(id) { return document.getElementById(id); },
        create: function(tag, props) { var el=document.createElement(tag); if(props) for(var p in props) el[p]=props[p]; return el; }
    }
});

Real-World Optimization Results

Case Study: Block Explorer Module

Optimization StepBeforeAfterSavings
Original code24KB--
Variable shortening24KB21KB3KB
Function compression21KB18KB3KB
Template optimization18KB15KB3KB
Style consolidation15KB12KB3KB
Final Result24KB12KB50%

Compression Techniques Applied

  1. Variable Renaming:

    • currentBlockHeighth
    • transactionHashListtxs
    • networkInformationinfo
  2. Function Optimization:

    • Combined similar functions
    • Inlined simple operations
    • Removed unnecessary error checking
  3. String Optimization:

    • Shared style constants
    • Compressed HTML templates
    • Removed redundant whitespace
  4. Logic Simplification:

    • Removed complex conditionals
    • Simplified data processing
    • Streamlined error handling

Size Analysis Tools

Development Size Monitor

// Add to your development workflow
function analyzeBundleSize() {
    const analysis = {
        files: [],
        totalSize: 0,
        warnings: []
    };
    
    ['main.js', 'styles.css', 'index.html'].forEach(async (filename) => {
        try {
            const response = await fetch(filename);
            const content = await response.text();
            const size = new Blob([content]).size;
            
            analysis.files.push({ name: filename, size: size });
            analysis.totalSize += size;
            
            // Check individual file limits
            if (size > 18000) {
                analysis.warnings.push(`❌ ${filename}: ${size} bytes (EXCEEDS LIMIT)`);
            } else if (size > 16000) {
                analysis.warnings.push(`⚠️ ${filename}: ${size} bytes (approaching limit)`);
            }
        } catch (error) {
            analysis.warnings.push(`Error checking ${filename}: ${error.message}`);
        }
    });
    
    // Display analysis
    setTimeout(() => {
        console.log('📊 Bundle Size Analysis:');
        analysis.files.forEach(file => {
            console.log(`  ${file.name}: ${file.size} bytes`);
        });
        console.log(`  Total: ${analysis.totalSize} bytes`);
        
        if (analysis.warnings.length > 0) {
            console.log('⚠️ Warnings:');
            analysis.warnings.forEach(warning => console.log(`  ${warning}`));
        } else {
            console.log('✅ All files within size limits');
        }
    }, 1000);
}
 
// Run during development
analyzeBundleSize();

Production Size Validation

#!/bin/bash
# Production size validation script
 
echo "📏 TELA Production Size Validation"
echo "=================================="
 
total_size=0
error_count=0
 
for file in *.js *.css *.html; do
    if [ -f "$file" ]; then
        size=$(wc -c < "$file")
        total_size=$((total_size + size))
        
        echo -n "$file: ${size} bytes "
        
        if [ $size -gt 18000 ]; then
            echo "❌ EXCEEDS LIMIT"
            error_count=$((error_count + 1))
        elif [ $size -gt 16000 ]; then
            echo "⚠️ Approaching limit"
        else
            echo "✅ OK"
        fi
    fi
done
 
echo "=================================="
echo "Total bundle size: ${total_size} bytes"
 
if [ $error_count -gt 0 ]; then
    echo "❌ $error_count files exceed size limits"
    exit 1
else
    echo "✅ All files ready for TELA deployment"
    exit 0
fi

Extreme Optimization Techniques

Aggressive Minification

// Ultra-compressed utility functions
var u = {
    $: function(i) { return document.getElementById(i); },
    c: function(t, p) { var e=document.createElement(t); if(p) for(var k in p) e[k]=p[k]; return e; },
    f: {
        n: function(n) { return (n||0).toLocaleString(); },
        h: function(h, l) { l=l||8; return !h?'-':h.length>l*2?h.substring(0,l)+'...'+h.substring(h.length-l):h; },
        d: function(a) { return a?(parseFloat(a)/1e12).toFixed(5)+' DERO':'0.00000 DERO'; },
        t: function(t) { var d=Math.floor((Date.now()/1000-t)/60); return d<1?'now':d<60?d+'m':Math.floor(d/60)+'h'; }
    }
};

HTML Template Compression

// Compressed template builder
function tmpl(type, data) {
    var s = 'background:rgba(0,0,0,0.2);border:1px solid rgba(82,200,219,0.3);padding:1.5rem;border-radius:8px;';
    var templates = {
        card: '<div style="' + s + '"><h2 style="color:#52c8db;">' + data.title + '</h2><p>' + data.content + '</p></div>',
        stat: '<div style="' + s + 'text-align:center;"><div style="font-size:1.8rem;color:#52c8db;">' + data.value + '</div><div style="color:#b3b3b3;font-size:0.9rem;">' + data.label + '</div></div>'
    };
    return templates[type] || '';
}

📋 Optimization Checklist

Pre-Optimization Assessment

  • Measure current sizes: wc -c *.js *.css *.html
  • Identify largest files: Focus optimization efforts
  • Find repeated code: Opportunities for consolidation
  • Check complexity: Simplification opportunities

Optimization Process

  • Shorten variable names: Long descriptive → short functional
  • Compress functions: Combine similar operations
  • Optimize strings: Single concatenation, shared constants
  • Remove debug code: Console logs, test functions
  • Simplify logic: Reduce conditional complexity

Post-Optimization Validation

  • Test functionality: Ensure nothing is broken
  • Measure savings: Calculate size reduction
  • Verify deployment: Test with tela-cli install-doc
  • Performance check: Ensure optimization didn't hurt performance
🎯

Optimization Goal: Aim for 15-16KB final size to leave room for future features and ensure reliable deployment across all DERO network conditions.

Related Resources


These optimization techniques represent best practices for TELA development. Apply them systematically to ensure your applications deploy successfully while maintaining full functionality.