NPM Package Aliasing Guide¶
Overview¶
OrchardCore's asset management system now uses NPM package aliasing to manage multiple versions of the same package without manual copying. This eliminates the need for manually vendored packages in the Assets/Vendor/ folder, if an NPM package is available.
What is NPM Package Aliasing?¶
NPM package aliasing allows you to install multiple versions of the same package under different names. For example:
{
"dependencies": {
"vue": "3.5.13", // Latest version
"vue-2.6.14": "npm:vue@2.6.14" // Alias for older version
}
}
This installs both versions into node_modules/:
- node_modules/vue/ (version 3.5.13)
- node_modules/vue-2.6.14/ (version 2.6.14)
Benefits¶
✅ No manual copying - NPM handles all package installations
✅ Automated updates - Run yarn install to sync all versions
✅ Version control - All versions tracked in package.json
✅ No Git bloat - Vendor files excluded from source control
✅ Consistent builds - Same versions across all environments
How to Add a New Versioned Package¶
1. Add the alias to package.json¶
In your module's Assets/package.json:
{
"dependencies": {
"bootstrap": "5.3.8", // Current version
"bootstrap-4.6.1": "npm:bootstrap@4.6.1" // Legacy version
}
}
2. Reference it in Assets.json¶
In your module's Assets.json:
[
{
"action": "copy",
"name": "bootstrap-4.6.1",
"source": "node_modules/bootstrap-4.6.1/dist/**",
"dest": "wwwroot/Vendor/bootstrap-4.6.1/",
"tags": ["resources", "js"]
}
]
3. Run yarn install¶
cd src
yarn install
4. Build the assets¶
yarn build
Examples¶
Multiple Vue Versions¶
{
"dependencies": {
"vue": "3.5.13",
"vue-2.6.14": "npm:vue@2.6.14"
}
}
Assets.json:
[
{
"action": "copy",
"name": "vue2",
"source": "node_modules/vue-2.6.14/dist/*.js",
"dest": "wwwroot/Vendor/vue-2.6.14/"
},
{
"action": "copy",
"name": "vue3",
"source": "node_modules/vue/dist/*.js",
"dest": "wwwroot/Scripts/"
}
]
Multiple jQuery Versions¶
{
"dependencies": {
"jquery": "3.7.1",
"jquery-3.6.0": "npm:jquery@3.6.0",
"jquery-3.5.1": "npm:jquery@3.5.1"
}
}
Multiple Font Awesome Versions¶
{
"dependencies": {
"@fortawesome/fontawesome-free": "7.2.0",
"@fortawesome/fontawesome-free-6.7.2": "npm:@fortawesome/fontawesome-free@6.7.2",
"@fortawesome/fontawesome-free-6.6.0": "npm:@fortawesome/fontawesome-free@6.6.0"
}
}
Migration from Manual Vendor Files¶
If you have existing manually vendored packages:
Before (Manual Vendor)¶
src/OrchardCore.Modules/YourModule/
├── Assets/
│ └── Vendor/
│ ├── vue-2.6.14/ ← Manually copied
│ └── bootstrap-4.6.1/ ← Manually copied
└── Assets.json
Assets.json:
{
"action": "copy",
"name": "vue2",
"source": "Assets/Vendor/vue-2.6.14/dist/*.js",
"dest": "wwwroot/Vendor/vue-2.6.14/"
}
After (NPM Aliasing)¶
src/OrchardCore.Modules/YourModule/
├── Assets/
│ └── package.json ← Defines aliases
└── Assets.json ← References node_modules
package.json:
{
"dependencies": {
"vue-2.6.14": "npm:vue@2.6.14"
}
}
Assets.json:
{
"action": "copy",
"name": "vue2",
"source": "node_modules/vue-2.6.14/dist/*.js",
"dest": "wwwroot/Vendor/vue-2.6.14/"
}
Migration Steps¶
-
Add aliases to package.json
cd src/OrchardCore.Modules/YourModule/Assets # Edit package.json to add aliases -
Update Assets.json paths
-
Change
Assets/Vendor/package-name/tonode_modules/package-alias/ -
Install dependencies
cd src yarn install -
Remove manual vendor files
# After verifying build works: rm -rf src/OrchardCore.Modules/YourModule/Assets/Vendor/ -
Update .gitignore (if needed)
# Make sure vendor files aren't tracked **/Assets/Vendor/
Troubleshooting¶
Package Not Found¶
Error: ENOENT: no such file or directory, stat 'node_modules/package-name'
Solution: Run yarn install from the repository root:
cd src
yarn install
Wrong Version Copied¶
Problem: The build copies the wrong version of a package.
Solution: Check your alias name matches the path in Assets.json:
// package.json
"vue-2.6.14": "npm:vue@2.6.14"
// Assets.json - alias name must match folder name
"source": "node_modules/vue-2.6.14/dist/*.js"
Workspace Dependency Conflicts¶
Problem: Different modules need different versions of the same package.
Solution: This is exactly what aliasing solves! Add the alias to each module's Assets/package.json:
// Module A needs Bootstrap 4
{
"dependencies": {
"bootstrap-4.6.1": "npm:bootstrap@4.6.1"
}
}
// Module B needs Bootstrap 5
{
"dependencies": {
"bootstrap": "5.3.8"
}
}
Both versions will be installed and available.
Best Practices¶
1. Use Semantic Alias Names¶
Include the version number in the alias name for clarity:
"vue-2.6.14": "npm:vue@2.6.14" // ✅ Good
"vue2": "npm:vue@2.6.14" // ⚠️ Less clear
2. Document Required Versions¶
Add comments in package.json to explain why legacy versions are needed:
{
"dependencies": {
"vue": "3.5.13",
// Required for legacy admin components - DO NOT REMOVE
"vue-2.6.14": "npm:vue@2.6.14"
}
}
3. Keep Aliases in Resources Module¶
For shared libraries used across multiple modules, define the alias in OrchardCore.Resources/Assets/package.json so all modules can reference the same version.
4. Clean Builds¶
When changing versions, do a clean build:
yarn clean
yarn install
yarn build
Advanced: Version Constraints¶
You can use version ranges in aliases:
{
"dependencies": {
// Exact version
"bootstrap-4.6.1": "npm:bootstrap@4.6.1",
// Latest in 4.x series
"bootstrap-4-latest": "npm:bootstrap@^4.6.0",
// Any 4.x version
"bootstrap-4": "npm:bootstrap@~4.0.0"
}
}
Recommendation: Use exact versions for predictable builds.