CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-requirejs

A command line tool for running JavaScript scripts that use the Asynchronous Module Definition API (AMD) for declaring and using JavaScript modules and regular JavaScript script files.

Pending
Overview
Eval results
Files

plugins.mddocs/

Plugin System

RequireJS provides an extensible plugin system that allows loading and processing non-JavaScript resources such as text files, CSS, HTML templates, and other custom content types. Plugins transform resources during both development and build processes.

Plugin Interface

All RequireJS plugins must implement a standardized interface for loading and processing resources.

Core Plugin Methods

load()

Main method for loading and processing resources.

load(name, require, onload, config)

Parameters:

  • name (String) - Resource name/path (without plugin prefix)
  • require (Function) - Local require function for loading dependencies
  • onload (Function) - Callback to call when resource is loaded
  • config (Object) - RequireJS configuration object

Usage Example:

define({
    load: function(name, require, onload, config) {
        // Load and process the resource
        const url = require.toUrl(name + '.txt');
        
        // Fetch the resource
        fetch(url).then(function(response) {
            return response.text();
        }).then(function(text) {
            // Process the text and return result
            onload(text.toUpperCase());
        }).catch(function(error) {
            onload.error(error);
        });
    }
});

write() (Build Support)

Optional method for writing optimized resources during build process.

write(pluginName, moduleName, write, config)

Parameters:

  • pluginName (String) - Name of the plugin
  • moduleName (String) - Name of the resource being processed
  • write (Function) - Function to call to write optimized content
  • config (Object) - Build configuration object

Usage Example:

define({
    // Store processed content during build
    buildMap: {},
    
    load: function(name, require, onload, config) {
        // Load and process resource
        const processedContent = processResource(name);
        
        // Store for build if needed
        if (config.isBuild) {
            this.buildMap[name] = processedContent;
        }
        
        onload(processedContent);
    },
    
    write: function(pluginName, moduleName, write, config) {
        if (this.buildMap.hasOwnProperty(moduleName)) {
            const content = this.buildMap[moduleName];
            // Write as optimized module
            write.asModule(pluginName + "!" + moduleName, 
                "define(function() { return " + JSON.stringify(content) + "; });");
        }
    }
});

normalize() (Optional)

Normalize resource names for consistent handling.

normalize(name, normalize)

Parameters:

  • name (String) - Resource name to normalize
  • normalize (Function) - Normalization function provided by RequireJS

Returns: Normalized resource name

Usage Example:

define({
    normalize: function(name, normalize) {
        // Remove file extension if present
        if (name.substr(name.length - 4) === '.txt') {
            name = name.substr(0, name.length - 4);
        }
        
        // Use RequireJS normalization
        return normalize(name);
    }
});

Plugin Usage

Loading Resources with Plugins

Use the plugin syntax pluginName!resourceName to load resources:

// Load text file using text plugin
require(['text!templates/header.html'], function(headerHtml) {
    document.getElementById('header').innerHTML = headerHtml;
});

// Load multiple resources
require(['text!data.json', 'text!template.html'], function(jsonText, templateHtml) {
    const data = JSON.parse(jsonText);
    // Use data and template
});

// Use in module definitions
define(['text!config.json'], function(configText) {
    const config = JSON.parse(configText);
    return {
        apiUrl: config.apiUrl,
        version: config.version
    };
});

Plugin Configuration

Configure plugin-specific options through RequireJS configuration:

requirejs.config({
    // Plugin-specific configuration
    text: {
        useXhr: function() {
            // Force XHR usage in all environments
            return true;
        }
    },
    
    // Custom plugin configuration
    myPlugin: {
        processingOptions: {
            minify: true,
            stripComments: false
        }
    }
});

Built-in Plugin Examples

Text Plugin Pattern

A typical implementation for loading text resources:

define(['module'], function(module) {
    'use strict';
    
    var fetchText = function(url, callback) {
        // Environment-specific text fetching
        if (typeof window !== 'undefined') {
            // Browser implementation
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    callback(xhr.responseText);
                }
            };
            xhr.send(null);
        } else if (typeof process !== 'undefined') {
            // Node.js implementation
            var fs = require.nodeRequire('fs');
            callback(fs.readFileSync(url, 'utf8'));
        }
    };
    
    var buildMap = {};
    
    return {
        load: function(name, req, onload, config) {
            var url = req.toUrl(name);
            
            fetchText(url, function(text) {
                // Store for build optimization
                if (config.isBuild) {
                    buildMap[name] = text;
                }
                
                onload(text);
            });
        },
        
        write: function(pluginName, moduleName, write, config) {
            if (buildMap.hasOwnProperty(moduleName)) {
                var text = buildMap[moduleName];
                write.asModule(pluginName + "!" + moduleName,
                    "define(function() { return " + JSON.stringify(text) + "; });");
            }
        },
        
        version: '1.0.0'
    };
});

JSON Plugin Example

define({
    load: function(name, req, onload, config) {
        req(['text!' + name + '.json'], function(text) {
            try {
                onload(JSON.parse(text));
            } catch (e) {
                onload.error(new Error('Invalid JSON in ' + name + ': ' + e.message));
            }
        });
    }
});

CSS Plugin Example

define({
    load: function(name, req, onload, config) {
        var url = req.toUrl(name + '.css');
        
        if (typeof window !== 'undefined') {
            // Browser: inject CSS via link tag
            var link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = url;
            link.onload = function() { onload(true); };
            document.head.appendChild(link);
        } else {
            // Node.js: just signal completion
            onload(true);
        }
    }
});

Advanced Plugin Features

Conditional Resource Loading

define({
    load: function(name, req, onload, config) {
        // Check environment or feature availability
        if (typeof window !== 'undefined' && window.WebGL) {
            // Load WebGL version
            req(['text!' + name + '.webgl.glsl'], onload);
        } else {
            // Load fallback version
            req(['text!' + name + '.fallback.txt'], onload);
        }
    }
});

Resource Transformation

define({
    load: function(name, req, onload, config) {
        req(['text!' + name + '.template'], function(template) {
            // Transform template (e.g., precompile Handlebars)
            const compiled = Handlebars.compile(template);
            onload(compiled);
        });
    },
    
    write: function(pluginName, moduleName, write, config) {
        // Write precompiled template to build
        if (buildMap.hasOwnProperty(moduleName)) {
            const compiledTemplate = buildMap[moduleName];
            write.asModule(pluginName + "!" + moduleName,
                "define(['handlebars'], function(Handlebars) { return " + 
                compiledTemplate.toString() + "; });");
        }
    }
});

Error Handling

define({
    load: function(name, req, onload, config) {
        const url = req.toUrl(name);
        
        fetchResource(url, function(result, error) {
            if (error) {
                // Signal error to RequireJS
                onload.error(new Error('Failed to load ' + name + ': ' + error.message));
            } else {
                onload(result);
            }
        });
    }
});

Build System Integration

Plugin Optimization

Plugins can be optimized during the build process to improve runtime performance:

// Build configuration
{
    // Replace plugin calls with static content
    stubModules: ['text', 'json'],
    
    // Optimize all plugin resources
    optimizeAllPluginResources: true,
    
    // Plugin-specific build settings
    inlineText: true  // Inline text! resources
}

Build-Time Resource Processing

define({
    load: function(name, req, onload, config) {
        req(['text!' + name], function(content) {
            let processed = content;
            
            if (config.isBuild) {
                // Build-time processing (minification, compilation, etc.)
                processed = minifyContent(content);
                buildMap[name] = processed;
            }
            
            onload(processed);
        });
    },
    
    write: function(pluginName, moduleName, write, config) {
        if (buildMap.hasOwnProperty(moduleName)) {
            write.asModule(pluginName + "!" + moduleName,
                "define(function() { return " + JSON.stringify(buildMap[moduleName]) + "; });");
        }
    }
});

Plugin Development Best Practices

Environment Detection

define({
    load: function(name, req, onload, config) {
        if (typeof window !== 'undefined') {
            // Browser environment
            loadViaBrowser(name, req, onload);
        } else if (typeof process !== 'undefined') {
            // Node.js environment
            loadViaNode(name, req, onload);
        } else {
            // Other environments (Rhino, Nashorn, etc.)
            loadViaGeneric(name, req, onload);
        }
    }
});

Resource Caching

define({
    cache: {},
    
    load: function(name, req, onload, config) {
        if (this.cache[name]) {
            // Return cached result
            onload(this.cache[name]);
            return;
        }
        
        // Load and cache
        loadResource(name, req, function(result) {
            this.cache[name] = result;
            onload(result);
        }.bind(this));
    }
});

Version Management

define({
    version: '2.1.0',
    
    load: function(name, req, onload, config) {
        // Plugin implementation
    },
    
    // Optional: API compatibility check
    loadingFinished: function() {
        console.log('Plugin v' + this.version + ' loaded successfully');
    }
});

Types

interface RequirePlugin {
    load(name: string, require: Function, onload: Function, config: Object): void;
    normalize?(name: string, normalize: Function): string;
    write?(pluginName: string, moduleName: string, write: Function, config: Object): void;
    version?: string;
}

interface PluginOnload extends Function {
    (result: any): void;
    error(err: Error): void;
    fromText(name: string, text: string): void;
}

interface PluginWrite extends Function {
    (content: string): void;
    asModule(moduleName: string, content: string): void;
}

The RequireJS plugin system provides a powerful foundation for extending module loading capabilities, enabling seamless integration of various resource types and custom processing logic into AMD-based applications.

Install with Tessl CLI

npx tessl i tessl/npm-requirejs

docs

amd-loader.md

build-system.md

command-line.md

configuration.md

index.md

plugins.md

tile.json