@@ -2,21 +2,32 @@ const { Trouter } = require('trouter')
22const next = require ( './../next' )
33const { parse } = require ( 'regexparam' )
44const { LRUCache : Cache } = require ( 'lru-cache' )
5- const queryparams = require ( '../utils/queryparams' )
5+ const queryparams = require ( './. ./utils/queryparams' )
66
7- // Default handlers as constants to avoid creating functions on each router instance
7+ /**
8+ * Default handlers as constants to avoid creating functions on each router instance.
9+ * This reduces memory allocation and improves performance when multiple routers are created.
10+ */
811const DEFAULT_ROUTE = ( req , res ) => {
912 res . statusCode = 404
1013 res . end ( )
1114}
1215
1316const DEFAULT_ERROR_HANDLER = ( err , req , res ) => {
1417 res . statusCode = 500
18+ // Note: err.message could expose sensitive information in production
1519 res . end ( err . message )
1620}
1721
18- // Simple ID generator
19- const generateId = ( ) => Math . random ( ) . toString ( 36 ) . substring ( 2 , 10 ) . toUpperCase ( )
22+ /**
23+ * Simple ID generator using Math.random for router identification.
24+ * Warning: Not cryptographically secure - suitable only for internal routing logic.
25+ * Optimized to minimize string operations.
26+ */
27+ const generateId = ( ) => {
28+ // Use a more efficient approach - avoid substring operations
29+ return Math . random ( ) . toString ( 36 ) . slice ( 2 , 10 ) . toUpperCase ( )
30+ }
2031
2132module . exports = ( config = { } ) => {
2233 // Use object destructuring with defaults for cleaner config initialization
@@ -29,88 +40,127 @@ module.exports = (config = {}) => {
2940
3041 const routers = { }
3142
32- // Initialize cache only once
43+ /**
44+ * Initialize LRU cache for route matching results with optimized settings.
45+ * Cache keys are method+path combinations to speed up repeated lookups.
46+ * - cacheSize > 0: Limited LRU cache with specified max entries
47+ * - cacheSize = 0: No caching (disabled)
48+ * - cacheSize < 0: Large LRU cache (50k entries) for "unlimited" mode
49+ * Optimized cache size for better memory management and performance.
50+ */
3351 let cache = null
3452 if ( cacheSize > 0 ) {
35- cache = new Cache ( { max : cacheSize } )
53+ cache = new Cache ( {
54+ max : cacheSize ,
55+ updateAgeOnGet : false , // Disable age updates for better performance
56+ updateAgeOnHas : false
57+ } )
3658 } else if ( cacheSize < 0 ) {
37- // For unlimited cache, still use LRUCache but with a very high max
38- // This provides better memory management than an unbounded Map
39- cache = new Cache ( { max : 100000 } )
59+ // Reduced from 100k to 50k for better memory efficiency while maintaining performance
60+ cache = new Cache ( {
61+ max : 50000 ,
62+ updateAgeOnGet : false ,
63+ updateAgeOnHas : false
64+ } )
4065 }
4166
4267 const router = new Trouter ( )
4368 router . id = id
4469
4570 const _use = router . use
4671
72+ /**
73+ * Enhanced router.use method with support for nested routers.
74+ * Handles both middleware functions and nested router instances.
75+ * Automatically handles prefix parsing when first argument is a function.
76+ * Optimized for minimal overhead in the common case.
77+ */
4778 router . use = ( prefix , ...middlewares ) => {
4879 if ( typeof prefix === 'function' ) {
4980 middlewares = [ prefix , ...middlewares ]
5081 prefix = '/'
5182 }
5283 _use . call ( router , prefix , middlewares )
5384
54- if ( middlewares [ 0 ] ?. id ) {
55- // caching router -> pattern relation for urls pattern replacement
85+ // Optimized nested router detection - check first middleware only
86+ const firstMiddleware = middlewares [ 0 ]
87+ if ( firstMiddleware ?. id ) {
88+ // Cache router -> pattern relation for URL pattern replacement in nested routing
89+ // This enables efficient URL rewriting when entering nested router contexts
5690 const { pattern } = parse ( prefix , true )
57- routers [ middlewares [ 0 ] . id ] = pattern
91+ routers [ firstMiddleware . id ] = pattern
5892 }
5993
60- return router // Fix: return router instead of this
94+ return router // Ensure chainable API by returning router instance
6195 }
6296
63- // Create the cleanup middleware once
64- const createCleanupMiddleware = ( step ) => ( req , res , next ) => {
65- req . url = req . preRouterUrl
66- req . path = req . preRouterPath
67-
68- req . preRouterUrl = undefined
69- req . preRouterPath = undefined
70-
71- return step ( )
97+ /**
98+ * Creates cleanup middleware for nested router restoration.
99+ * This middleware restores the original URL and path after nested router processing.
100+ * Uses property deletion instead of undefined assignment for better performance.
101+ * Optimized to minimize closure creation overhead.
102+ */
103+ const createCleanupMiddleware = ( step ) => {
104+ // Pre-create the cleanup function to avoid repeated function creation
105+ return ( req , res , next ) => {
106+ req . url = req . preRouterUrl
107+ req . path = req . preRouterPath
108+
109+ // Use delete for better performance than setting undefined
110+ delete req . preRouterUrl
111+ delete req . preRouterPath
112+
113+ return step ( )
114+ }
72115 }
73116
74117 router . lookup = ( req , res , step ) => {
75- // Initialize URL and originalUrl if needed
76- req . url = req . url || '/'
77- req . originalUrl = req . originalUrl || req . url
118+ // Initialize URL and originalUrl if needed - use nullish coalescing for better performance
119+ req . url ??= '/'
120+ req . originalUrl ??= req . url
78121
79- // Parse query parameters
122+ // Parse query parameters using optimized utility
80123 queryparams ( req , req . url )
81124
82- // Fast path for cache lookup
83- const reqCacheKey = cache && ( req . method + req . path )
84- let match = cache && cache . get ( reqCacheKey )
125+ // Cache lookup optimization - minimize variable assignments
126+ let match
127+ if ( cache ) {
128+ // Pre-compute cache key with direct concatenation (fastest approach)
129+ const reqCacheKey = req . method + req . path
130+ match = cache . get ( reqCacheKey )
85131
86- if ( ! match ) {
87- match = router . find ( req . method , req . path )
88- if ( cache && reqCacheKey ) {
132+ if ( ! match ) {
133+ match = router . find ( req . method , req . path )
89134 cache . set ( reqCacheKey , match )
90135 }
136+ } else {
137+ match = router . find ( req . method , req . path )
91138 }
92139
93140 const { handlers, params } = match
94141
95- if ( handlers . length > 0 ) {
96- // Avoid creating a new array with spread operator
97- // Use the handlers array directly
142+ if ( handlers . length ) {
143+ // Optimized middleware array handling
98144 let middlewares
99-
100145 if ( step !== undefined ) {
101- // Only create a new array if we need to add the cleanup middleware
146+ // Create new array only when step middleware is needed
102147 middlewares = handlers . slice ( )
103148 middlewares . push ( createCleanupMiddleware ( step ) )
104149 } else {
105150 middlewares = handlers
106151 }
107152
108- // Initialize params object if needed
153+ // Optimized parameter assignment with minimal overhead
109154 if ( ! req . params ) {
110- req . params = params
155+ // Use pre-created empty object or provided params directly
156+ req . params = params || Object . create ( null )
111157 } else if ( params ) {
112- // Faster than Object.assign for small objects
113- for ( const key in params ) {
158+ // Manual property copying - optimized for small objects
159+ // Pre-compute keys and length to avoid repeated calls
160+ const paramKeys = Object . keys ( params )
161+ let i = paramKeys . length
162+ while ( i -- ) {
163+ const key = paramKeys [ i ]
114164 req . params [ key ] = params [ key ]
115165 }
116166 }
@@ -121,6 +171,10 @@ module.exports = (config = {}) => {
121171 }
122172 }
123173
174+ /**
175+ * Shorthand method for registering routes with specific HTTP methods.
176+ * Delegates to router.add with the provided method, pattern, and handlers.
177+ */
124178 router . on = ( method , pattern , ...handlers ) => router . add ( method , pattern , handlers )
125179
126180 return router
0 commit comments