Files
rspade_system/app/RSpade/man/npm.txt
2025-12-09 21:16:16 +00:00

242 lines
8.0 KiB
Plaintext
Executable File

NPM(3) RSX Framework Manual NPM(3)
NAME
npm - Including npm packages in RSX bundles
SYNOPSIS
// Asset Bundle with npm imports
class My_Bundle extends Rsx_Asset_Bundle_Abstract
{
public static function define(): array
{
return [
'npm' => [
'moment' => "import moment from 'moment'",
'axios' => "import axios from 'axios'",
],
];
}
}
// Usage in JavaScript
const now = moment().format('YYYY-MM-DD');
const response = await axios.get('/api/data');
DESCRIPTION
RSX bundles can include npm packages through Asset Bundles. The bundle
system uses esbuild to compile npm imports into the vendor bundle,
exposing them as global variables accessible throughout your application.
Unlike traditional webpack/vite setups where you write import statements
in your JavaScript files, RSX centralizes npm dependencies in Asset
Bundle definitions. This provides:
- Explicit dependency declaration in PHP
- Automatic vendor/app bundle splitting
- Tree-shaking of unused exports
- No import statements needed in application code
PACKAGE INSTALLATION
All npm packages must be installed in the system directory:
cd /var/www/html/system
npm install <package-name>
The framework's esbuild runs from system/, so packages must exist in
system/node_modules/. The project root package.json is for reference
only - actual dependencies live in system/.
ASSET BUNDLE SYNTAX
Create an Asset Bundle extending Rsx_Asset_Bundle_Abstract with an
'npm' array in the define() method:
class My_Library_Bundle extends Rsx_Asset_Bundle_Abstract
{
public static function define(): array
{
return [
'npm' => [
'global_name' => "import statement",
],
];
}
}
Each entry maps a global variable name to an ES module import statement.
The global becomes available to all JavaScript in bundles that include
this Asset Bundle.
IMPORT FORMATS
DEFAULT EXPORT
Package exports a single default value:
'moment' => "import moment from 'moment'",
'axios' => "import axios from 'axios'",
'lodash' => "import _ from 'lodash'",
Usage: moment(), axios.get(), _.map()
NAMED EXPORT
Package exports multiple named values. Each named export needs its
own entry:
// CORRECT - separate entries for each named export
'createApp' => "import { createApp } from 'vue'",
'ref' => "import { ref } from 'vue'",
'computed' => "import { computed } from 'vue'",
Usage: createApp(), ref(), computed()
IMPORTANT: You cannot combine multiple named exports into one global.
This does NOT work:
// WRONG - creates single value, not object with both
'vue' => "import { createApp, ref } from 'vue'",
The global 'vue' would only contain createApp, not both functions.
NAMESPACE IMPORT
Import all exports as a namespace object:
'Shiki' => "import * as Shiki from 'shiki'",
Usage: Shiki.createHighlighter(), Shiki.bundledLanguages
SUB-PATH IMPORTS
Many packages offer sub-path imports for tree-shaking:
// Full package - includes everything
'shiki' => "import { createHighlighter } from 'shiki'",
// Sub-path - only what you need
'createHighlighter' => "import { createHighlighterCore } from '@shikijs/core'",
'darkPlus' => "import darkPlus from '@shikijs/themes/dark-plus'",
Sub-path imports significantly reduce bundle size.
BUNDLE PLACEMENT
Asset Bundles are auto-discovered when Module Bundles scan directories.
Place your npm Asset Bundle alongside the components that use it:
rsx/app/docs/components/
shiki_bundle.php # Asset Bundle with npm imports
Docs_Code_Block.js # Component using shiki globals
Docs_Code_Block.jqhtml
The Module Bundle scanning rsx/app/docs/ will automatically include
the Shiki_Bundle and its npm dependencies.
VENDOR BUNDLE COMPILATION
npm packages compile into the vendor bundle, separate from app code.
This provides better caching since vendor code changes less frequently.
REBUILD TRIGGERS
The vendor bundle rebuilds when:
- npm entries in Asset Bundles change
- First HTTP request after cache clear
- Running rsx:clean followed by page request
IMPORTANT: Running rsx:bundle:compile alone may not rebuild the
vendor bundle if the cache key hasn't changed. To force a complete
rebuild:
php artisan rsx:bundle:compile --clean
Or trigger via HTTP request:
curl http://localhost/your-page
php artisan rsx:debug /your-page
TROUBLESHOOTING
NPM MODULE NOT FOUND ERROR
Error: RSX Framework Error: NPM module "xyz" not found.
Expected window._rsx_npm.xyz to be defined by the vendor bundle.
Causes:
1. Package not installed in system/node_modules/
2. Vendor bundle not rebuilt after adding npm entry
3. Import statement syntax error
Solutions:
1. cd system && npm install <package>
2. php artisan rsx:bundle:compile --clean
3. Verify import syntax matches package's actual exports
VERIFYING PACKAGE EXPORTS
Check what a package actually exports:
# Default export
grep -E "^export default" node_modules/pkg/dist/index.mjs
# Named exports
grep -E "^export \{|^export function|^export const" \
node_modules/pkg/dist/index.mjs
BUNDLE SIZE OPTIMIZATION
Use sub-path imports when available:
// Before: 9.7 MB (all languages, themes)
'shiki' => "import { createHighlighter } from 'shiki'",
// After: 2.4 MB (only what's needed)
'createHighlighter' => "import { createHighlighterCore } from '@shikijs/core'",
'langJs' => "import js from '@shikijs/langs/javascript'",
'themeDark' => "import dark from '@shikijs/themes/dark-plus'",
EXAMPLES
CHART.JS
class Chart_Bundle extends Rsx_Asset_Bundle_Abstract
{
public static function define(): array
{
return [
'npm' => [
'Chart' => "import { Chart } from 'chart.js/auto'",
],
];
}
}
// Usage
new Chart(ctx, { type: 'bar', data: {...} });
DATE-FNS (Tree-Shaking Friendly)
class DateFns_Bundle extends Rsx_Asset_Bundle_Abstract
{
public static function define(): array
{
return [
'npm' => [
'format' => "import { format } from 'date-fns'",
'parseISO' => "import { parseISO } from 'date-fns'",
'addDays' => "import { addDays } from 'date-fns'",
],
];
}
}
// Usage
format(parseISO('2024-01-15'), 'MMM d, yyyy');
VUE 3
class Vue_Bundle extends Rsx_Asset_Bundle_Abstract
{
public static function define(): array
{
return [
'npm' => [
'createApp' => "import { createApp } from 'vue'",
'ref' => "import { ref } from 'vue'",
'reactive' => "import { reactive } from 'vue'",
'computed' => "import { computed } from 'vue'",
'watch' => "import { watch } from 'vue'",
],
];
}
}
SEE ALSO
bundle_api(3), jqhtml(3)
RSX Framework 2025-12-09 NPM(3)