StealJS

repository·master·Indexed 23 days ago

https://github.com/stealjs/steal

An extensible, universal module loader designed to handle multiple JavaScript module formats, including ES6, AMD, and CommonJS, within a single project. StealJS supports non-JS assets via plugins, integrates Babel 6 for transpilation and JSX support, and provides comprehensive configuration options for module resolution, production bundling, and cache busting.

Tokens
23.3K
Snippets
90
Records
145
Agent score
79%

What's inside steal

  1. What is steal and how does it work?

    master

    Steal is an extensible, universal module loader. Its primary capability is the ability to load JavaScript modules defined in multiple formats simultaneously, including ES6, AMD, and CommonJS. This allows developers to mix and match different module styles within a single project.

    Supported module formats include:

    • ES6: Using import statements.
    • AMD: Using define calls.
    • CommonJS: Using require calls.
    // ES6
    import { hello, goodbye } from  "greetings";
    
    // AMD
    define(["greetings"],function(greetings){ ... });
    
    // CommonJS
    var hello = require('greetings').hello;
    var goodbye = require('greetings').goodbye;
  2. Use the `@steal` module to access the local Steal instance

    master
    The @steal module is a special virtual module that refers to the specific instance of steal that is currently loading your module. Using @steal is preferred over relying on the global window.steal, especially in environments where multiple Steal instances might exist or when you need to access Steal's special lifecycle methods like steal.done().
  3. Understand npm moduleName normalization

    master

    When importing npm packages, Steal normalizes the moduleName to include versioning and internal paths to ensure uniqueness and semver compatibility across different dependency trees.

    A normalized npm moduleName follows the pattern: packageName@version#modulePath.

    Components of an npm moduleName

    Using lodash@1.0.0#main as an example:

    1. packageName: The name used during installation (e.g., lodash).
    2. version: The specific version of the package (e.g., 1.0.0). Steal uses this to ensure that different parts of your dependency tree receive semver-compatible versions of the same package.
    3. modulePath: The specific entry point or file within the package (e.g., main).

    Importing specific paths

    You can import specific files within a package rather than just the main entry point. For example:

    import each from "lodash/arrays/for_each";

    This results in a moduleName of lodash@1.0.0#arrays/for_each and resolves to the actual file path within the node_modules directory.

  4. Configure npm package resolution via package.json

    master
    You can control how StealJS resolves modules within an npm package by adding a steal object to its package.json. This allows individual packages to define their own resolution logic, mapping, and metadata.
  5. Use the `homeAlias` (~) scheme for module lookups

    master

    The homeAlias is a lookup scheme that roots module lookups to your project's base folder. By default, this is represented by the ~ symbol. This allows you to reference modules relative to your project root without using long relative paths (e.g., ../../) or the full package name.

    To use it, prepend your module path with ~/.

    If your package.json defines a specific library directory via steal.directories.lib, the ~ symbol will resolve relative to that directory.

  6. Understand the `load` object in module loading lifecycle hooks

    master

    The load object is a Plain Old JavaScript Object (POJO) provided during StealJS module loading lifecycle hooks. It contains information about the module being processed. The load object is instantiated after the steal.hooks.normalize step, meaning the module name is guaranteed to be available.

    Key properties include:

    • name: The moduleName of the module. This property is always present.
    • address: The URL, filesystem path, or generic location where the module can be fetched (available after the steal.hooks.locate step).
    • source: The actual source code of the module.
    • metadata: An object containing metadata associated with the module, such as its module format.
  7. Understand the moduleIdentifier type

    master

    A moduleIdentifier is a string used in import functions to specify which module to load. It is the raw string passed to functions like require() (CommonJS), import (ES6), or steal.import() (dynamic loading).

    Common forms of a moduleIdentifier include:

    • Relative paths: e.g., './foo'
    • npm dependency names: e.g., 'lodash'
    • Mapped names: A name that has been mapped to a different moduleName via configuration.

    Internally, StealJS uses steal.hooks.normalize to convert these identifiers into moduleNames, which serve as the actual keys in the module registry.

  8. Understand the difference between moduleName and moduleIdentifier

    master

    In Steal, it is critical to distinguish between the string you use in your code and the canonical name Steal uses to track the module in its registry.

    • moduleIdentifier: The raw string provided to import, require(), or other statements (e.g., ./dep, lodash, or styles.css). These are typically relative to the current module.
    • moduleName: The canonical, unique string produced after the identifier is normalized (e.g., app/util/dep, lodash@3.0.0#main). This is used as the key in the module registry to ensure a module is only loaded and executed once.
    Module identifierModule name
    ./depapp/util/dep
    styles.cssstyles.css!$css
    lodashlodash@3.0.0#main
  9. Use the `locate://` path scheme to resolve resources

    master

    The locate:// scheme allows you to rewrite paths using the StealJS path resolution system. This is useful for referencing resources that might be located in node_modules, relative to the baseURL, or within other stealable modules, without hardcoding complex relative paths.

    Supported Extensions:

    • CSS
    • LESS
    • Stache

    Important Limitations:

    • CSS Imports: The locate:// syntax is not supported in standard CSS @import statements because the browser handles those imports directly, bypassing the Steal CSS plugin's ability to rewrite the paths.
    • Recursion: In LESS and Stache, the syntax is available recursively (it works in sub-imports).
  10. Ways to set Steal configuration

    master

    Steal configuration can be established in three ways:

    1. Global object: Set a steal object on the window before loading the script.

      <script>
        steal = {main: "myapp"};
      </script>
      <script src="../path/to/steal/steal.js"></script>
    2. Script attributes: Use attributes directly on the steal.js script tag.

      <script src="../path/to/steal/steal.js" main="myapp"></script>
    3. Programmatic call: Use steal.config() (typically inside a configuration module).

      steal.config({
        paths: {"can/*" : "http://canjs.com/release/2.0.1/can/*"}
      });
  11. Configure module overrides in `steal-clone`

    master

    When calling clone(moduleOverrides), the moduleOverrides object maps module identifiers to their new definitions.

    Module Identifiers

    Identifiers can be any valid Steal module syntax, including:

    • ES6 modules: The exact string used in your import statement.
    • CommonJS: The exact string used in require().
    • Relative paths: e.g., './moduleB'.
    • npm packages: The package name used to resolve the dependency.

    Module Definitions

    The values in the moduleOverrides object define the exports for the overridden module. You must match the export structure of the original module (e.g., providing a default key for default exports, or named keys for named exports).

    clone({
      'moduleB': {
        getName: function() {
          return 'moduleBOverride';
        },
        getExcitedName: function() {
          return 'moduleBOverride!';
        }
      }
    });
  12. Use the @loader module for configuration and dynamic imports

    master

    The @loader module refers specifically to the loader instance that is currently loading the module where @loader is imported.

    While @loader is often identical to the global steal.loader, you should use @loader instead of the global instance when:

    1. You are in a build environment where multiple loaders may exist.
    2. You are using steal.steal-clone to test injected modules.

    Using @loader ensures you are configuring or importing modules through the correct loader context. It supports all standard Steal loader methods like .config() and .import().