Selective Component Imports

September 14, 2025 ยท View on GitHub

Selective imports allow you to import only the Forge components you need, resulting in smaller bundle sizes and better tree-shaking. This feature is available starting from @nexcraft/forge v0.5.2-beta.22+.

Benefits

๐Ÿš€ Smaller Bundle Sizes

// Before: Import entire library (~300KB)
import '@nexcraft/forge';

// After: Import only what you need (~15KB)
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input';

โšก Faster Build Times

  • Reduced dependency graph processing
  • Better tree-shaking optimization
  • Smaller TypeScript compilation scope

๐ŸŽฏ Explicit Dependencies

  • Clear visibility into which components are used
  • Easier dependency tracking and auditing
  • Better compatibility with bundler analysis tools

Basic Usage

Individual Component Imports

// Import specific components with auto-registration
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input';
import { ForgeCheckbox } from '@nexcraft/forge/checkbox';

// Components are automatically registered as custom elements
// <forge-button>, <forge-input>, <forge-checkbox> are now available

Manual Registration Pattern

// Import without auto-registration
import ForgeButton from '@nexcraft/forge/button';

// Manually register with custom name
customElements.define('my-button', ForgeButton);

// Now use as <my-button>

Available Selective Imports

Atomic Components

// Form components
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input'; 
import { ForgeCheckbox } from '@nexcraft/forge/checkbox';
import { ForgeSelect } from '@nexcraft/forge/select';

// Feedback components  
import { ForgeAlert } from '@nexcraft/forge/alert';

// Display components
// More components will be added in future releases

Molecular Components

// Layout components
import { ForgeCard } from '@nexcraft/forge/card';
import { ForgeModal } from '@nexcraft/forge/modal';

// More molecular components coming soon...

Framework Integration

React

import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input';

function LoginForm() {
  return (
    <form>
      <ForgeInput 
        type="email" 
        label="Email"
        required
      />
      <ForgeButton type="submit" variant="primary">
        Sign In
      </ForgeButton>
    </form>
  );
}

React + TypeScript

import { ForgeButton } from '@nexcraft/forge/button';
import type { ButtonVariant } from '@nexcraft/forge/button';

interface ActionButtonProps {
  variant: ButtonVariant;
  children: React.ReactNode;
  onClick: () => void;
}

function ActionButton({ variant, children, onClick }: ActionButtonProps) {
  return (
    <ForgeButton variant={variant} onClick={onClick}>
      {children}
    </ForgeButton>
  );
}

Vue 3

<template>
  <form>
    <forge-input 
      type="email" 
      label="Email"
      :required="true"
    />
    <forge-button 
      type="submit" 
      variant="primary"
      @click="handleSubmit"
    >
      Sign In
    </forge-button>
  </form>
</template>

<script setup>
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input';

const handleSubmit = () => {
  console.log('Form submitted');
};
</script>

Angular

// app.component.ts
import { Component } from '@angular/core';
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input';

@Component({
  selector: 'app-root',
  template: `
    <form>
      <forge-input 
        type="email" 
        label="Email"
        [required]="true">
      </forge-input>
      <forge-button 
        type="submit" 
        variant="primary"
        (click)="handleSubmit()">
        Sign In
      </forge-button>
    </form>
  `
})
export class AppComponent {
  handleSubmit() {
    console.log('Form submitted');
  }
}

Bundle Analysis

Webpack Bundle Analyzer

# Install analyzer
npm install --save-dev webpack-bundle-analyzer

# Analyze your bundle to see component sizes
npm run build:analyze

Expected Results:

Before (bulk import):
โ”œโ”€โ”€ @nexcraft/forge.es.js (300KB)

After (selective imports):
โ”œโ”€โ”€ @nexcraft/forge/button (15KB)
โ”œโ”€โ”€ @nexcraft/forge/input (18KB)  
โ”œโ”€โ”€ @nexcraft/forge/checkbox (12KB)
Total: 45KB (85% reduction)

Rollup Bundle Analyzer

// rollup.config.js
import { visualizer } from 'rollup-plugin-visualizer';

export default {
  plugins: [
    visualizer({
      filename: 'bundle-analysis.html',
      open: true
    })
  ]
};

Advanced Patterns

Conditional Loading

// Load components only when needed
async function loadFormComponents() {
  const [
    { ForgeInput },
    { ForgeButton },
    { ForgeCheckbox }
  ] = await Promise.all([
    import('@nexcraft/forge/input'),
    import('@nexcraft/forge/button'), 
    import('@nexcraft/forge/checkbox')
  ]);
  
  return { ForgeInput, ForgeButton, ForgeCheckbox };
}

// Use in React with Suspense
function FormSection() {
  const [components, setComponents] = useState(null);
  
  useEffect(() => {
    loadFormComponents().then(setComponents);
  }, []);
  
  if (!components) return <div>Loading...</div>;
  
  return (
    <form>
      <components.ForgeInput label="Name" />
      <components.ForgeButton variant="primary">Submit</components.ForgeButton>
    </form>
  );
}

Custom Component Registry

// Create a custom component registry
class ForgeComponentRegistry {
  static async loadComponent(name) {
    const componentMap = {
      'button': () => import('@nexcraft/forge/button'),
      'input': () => import('@nexcraft/forge/input'),
      'checkbox': () => import('@nexcraft/forge/checkbox'),
      'select': () => import('@nexcraft/forge/select'),
      'alert': () => import('@nexcraft/forge/alert'),
      'card': () => import('@nexcraft/forge/card'),
      'modal': () => import('@nexcraft/forge/modal')
    };
    
    const loader = componentMap[name];
    if (!loader) {
      throw new Error(`Component ${name} not found`);
    }
    
    return await loader();
  }
  
  static async loadComponents(names) {
    const promises = names.map(name => this.loadComponent(name));
    return await Promise.all(promises);
  }
}

// Usage
const [buttonModule, inputModule] = await ForgeComponentRegistry.loadComponents(['button', 'input']);

Micro-frontend Integration

// Module federation with selective imports
// webpack.config.js
const ModuleFederationPlugin = require('@module-federation/webpack');

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'shell',
      exposes: {
        // Expose individual components
        './ForgeButton': '@nexcraft/forge/button',
        './ForgeInput': '@nexcraft/forge/input'
      }
    })
  ]
};

// Consumer app
const { ForgeButton } = await import('shell/ForgeButton');
const { ForgeInput } = await import('shell/ForgeInput');

Migration Guide

From Bulk Imports

Before:

// Old pattern - loads entire library
import '@nexcraft/forge';

// All components available globally

After:

// New pattern - selective imports  
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input';

// Only imported components are available

From Framework Integration Imports

Before:

// Load React integration (includes all components)
import { ForgeButton, ForgeInput, ForgeCheckbox } from '@nexcraft/forge/integrations/react';

After:

// Mix selective imports with React integration for best performance
import { ForgeButton } from '@nexcraft/forge/button';
import { ForgeInput } from '@nexcraft/forge/input'; 
import { RHFForgeCheckbox } from '@nexcraft/forge/integrations/rhf';

Gradual Migration

// Step 1: Identify most used components
import { ForgeButton, ForgeInput } from '@nexcraft/forge/integrations/react'; // Remove this
import { ForgeButton } from '@nexcraft/forge/button'; // Add this
import { ForgeInput } from '@nexcraft/forge/input';   // Add this

// Step 2: Replace other components gradually  
// Keep using integration imports for less common components
import { ForgeTooltip, ForgeModal } from '@nexcraft/forge/integrations/react';

// Step 3: Eventually move to full selective imports
import { ForgeTooltip } from '@nexcraft/forge/tooltip'; // When available
import { ForgeModal } from '@nexcraft/forge/modal';     // Available now

Performance Benchmarks

Bundle Size Comparison

Import PatternBundle SizeComponents Included
Full Library~300KBAll 27 components
Framework Integration~150KBFramework + components
Selective (5 components)~75KBOnly imported components
Selective (1 component)~15KBSingle component

Real-world Example

E-commerce Form:

// Selective imports for checkout form
import { ForgeInput } from '@nexcraft/forge/input';     // 18KB
import { ForgeSelect } from '@nexcraft/forge/select';   // 16KB  
import { ForgeCheckbox } from '@nexcraft/forge/checkbox'; // 12KB
import { ForgeButton } from '@nexcraft/forge/button';   // 15KB
// Total: 61KB vs 300KB full library (80% savings)

Troubleshooting

Import Errors

// โŒ Wrong - component not available for selective import yet
import { ForgeTooltip } from '@nexcraft/forge/tooltip';

// โœ… Correct - use integration import for now  
import { ForgeTooltip } from '@nexcraft/forge/integrations/react';

TypeScript Errors

// โŒ Wrong - importing from wrong path
import type { ButtonVariant } from '@nexcraft/forge';

// โœ… Correct - import types from component path
import type { ButtonVariant } from '@nexcraft/forge/button';

Bundle Not Shrinking

  1. Check bundler configuration:

    // Ensure tree-shaking is enabled
    optimization: {
      usedExports: true,
      sideEffects: false
    }
    
  2. Verify imports:

    // โœ… Good - selective import
    import { ForgeButton } from '@nexcraft/forge/button';
    
    // โŒ Bad - still imports everything
    import '@nexcraft/forge';
    
  3. Check for mixed patterns:

    // Don't mix bulk and selective imports
    import '@nexcraft/forge'; // โŒ This loads everything
    import { ForgeButton } from '@nexcraft/forge/button'; // โœ… This is redundant now
    

Version Requirements

  • Minimum Version: @nexcraft/forge v0.5.2-beta.22+
  • Node.js: v16.0.0+
  • Bundler: Webpack 5+, Rollup 3+, Vite 4+, or esbuild 0.17+

Roadmap

Planned Selective Imports:

  • @nexcraft/forge/tooltip
  • @nexcraft/forge/dropdown
  • @nexcraft/forge/date-picker
  • @nexcraft/forge/multi-select
  • @nexcraft/forge/form-field
  • @nexcraft/forge/toast
  • @nexcraft/forge/tabs
  • @nexcraft/forge/accordion
  • @nexcraft/forge/data-table
  • @nexcraft/forge/navigation-bar
  • @nexcraft/forge/pagination

All selective imports will be available by v0.6.0.