From 7b308358f4024283bc95265a60ac518db8870106 Mon Sep 17 00:00:00 2001 From: EdamAmex <121654029+EdamAme-x@users.noreply.github.com> Date: Wed, 13 Nov 2024 04:38:10 +0900 Subject: [PATCH] refactor(router): use `#` for private props to reduce the minified file size (#3660) --- src/router/linear-router/router.ts | 8 ++-- src/router/reg-exp-router/node.ts | 38 +++++++-------- src/router/reg-exp-router/router.ts | 19 ++++---- src/router/reg-exp-router/trie.ts | 8 ++-- src/router/smart-router/router.ts | 26 +++++----- src/router/trie-router/node.ts | 74 ++++++++++++++--------------- src/router/trie-router/router.ts | 10 ++-- 7 files changed, 93 insertions(+), 90 deletions(-) diff --git a/src/router/linear-router/router.ts b/src/router/linear-router/router.ts index 6a490448..28796ec7 100644 --- a/src/router/linear-router/router.ts +++ b/src/router/linear-router/router.ts @@ -10,7 +10,7 @@ const splitPathRe = /\/(:\w+(?:{(?:(?:{[\d,]+})|[^}])+})?)|\/[^\/\?]+|(\?)/g const splitByStarRe = /\*/ export class LinearRouter implements Router { name: string = 'LinearRouter' - routes: [string, string, T][] = [] + #routes: [string, string, T][] = [] add(method: string, path: string, handler: T) { for ( @@ -18,14 +18,14 @@ export class LinearRouter implements Router { i < len; i++ ) { - this.routes.push([method, paths[i], handler]) + this.#routes.push([method, paths[i], handler]) } } match(method: string, path: string): Result { const handlers: [T, Params][] = [] - ROUTES_LOOP: for (let i = 0, len = this.routes.length; i < len; i++) { - const [routeMethod, routePath, handler] = this.routes[i] + ROUTES_LOOP: for (let i = 0, len = this.#routes.length; i < len; i++) { + const [routeMethod, routePath, handler] = this.#routes[i] if (routeMethod === method || routeMethod === METHOD_NAME_ALL) { if (routePath === '*' || routePath === '/*') { handlers.push([handler, emptyParams]) diff --git a/src/router/reg-exp-router/node.ts b/src/router/reg-exp-router/node.ts index c894c898..91abea7f 100644 --- a/src/router/reg-exp-router/node.ts +++ b/src/router/reg-exp-router/node.ts @@ -43,9 +43,9 @@ function compareKey(a: string, b: string): number { } export class Node { - index?: number - varIndex?: number - children: Record = Object.create(null) + #index?: number + #varIndex?: number + #children: Record = Object.create(null) insert( tokens: readonly string[], @@ -55,14 +55,14 @@ export class Node { pathErrorCheckOnly: boolean ): void { if (tokens.length === 0) { - if (this.index !== undefined) { + if (this.#index !== undefined) { throw PATH_ERROR } if (pathErrorCheckOnly) { return } - this.index = index + this.#index = index return } @@ -88,10 +88,10 @@ export class Node { } } - node = this.children[regexpStr] + node = this.#children[regexpStr] if (!node) { if ( - Object.keys(this.children).some( + Object.keys(this.#children).some( (k) => k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR ) ) { @@ -100,19 +100,19 @@ export class Node { if (pathErrorCheckOnly) { return } - node = this.children[regexpStr] = new Node() + node = this.#children[regexpStr] = new Node() if (name !== '') { - node.varIndex = context.varIndex++ + node.#varIndex = context.varIndex++ } } if (!pathErrorCheckOnly && name !== '') { - paramMap.push([name, node.varIndex as number]) + paramMap.push([name, node.#varIndex as number]) } } else { - node = this.children[token] + node = this.#children[token] if (!node) { if ( - Object.keys(this.children).some( + Object.keys(this.#children).some( (k) => k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR ) @@ -122,7 +122,7 @@ export class Node { if (pathErrorCheckOnly) { return } - node = this.children[token] = new Node() + node = this.#children[token] = new Node() } } @@ -130,21 +130,21 @@ export class Node { } buildRegExpStr(): string { - const childKeys = Object.keys(this.children).sort(compareKey) + const childKeys = Object.keys(this.#children).sort(compareKey) const strList = childKeys.map((k) => { - const c = this.children[k] + const c = this.#children[k] return ( - (typeof c.varIndex === 'number' - ? `(${k})@${c.varIndex}` + (typeof c.#varIndex === 'number' + ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + c.buildRegExpStr() ) }) - if (typeof this.index === 'number') { - strList.unshift(`#${this.index}`) + if (typeof this.#index === 'number') { + strList.unshift(`#${this.#index}`) } if (strList.length === 0) { diff --git a/src/router/reg-exp-router/router.ts b/src/router/reg-exp-router/router.ts index c3358885..a9f6285c 100644 --- a/src/router/reg-exp-router/router.ts +++ b/src/router/reg-exp-router/router.ts @@ -123,16 +123,17 @@ function findMiddleware( export class RegExpRouter implements Router { name: string = 'RegExpRouter' - middleware?: Record[]>> - routes?: Record[]>> + #middleware?: Record[]>> + #routes?: Record[]>> constructor() { - this.middleware = { [METHOD_NAME_ALL]: Object.create(null) } - this.routes = { [METHOD_NAME_ALL]: Object.create(null) } + this.#middleware = { [METHOD_NAME_ALL]: Object.create(null) } + this.#routes = { [METHOD_NAME_ALL]: Object.create(null) } } add(method: string, path: string, handler: T) { - const { middleware, routes } = this + const middleware = this.#middleware + const routes = this.#routes if (!middleware || !routes) { throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT) @@ -232,14 +233,14 @@ export class RegExpRouter implements Router { #buildAllMatchers(): Record | null> { const matchers: Record | null> = Object.create(null) - Object.keys(this.routes!) - .concat(Object.keys(this.middleware!)) + Object.keys(this.#routes!) + .concat(Object.keys(this.#middleware!)) .forEach((method) => { matchers[method] ||= this.#buildMatcher(method) }) // Release cache - this.middleware = this.routes = undefined + this.#middleware = this.#routes = undefined return matchers } @@ -249,7 +250,7 @@ export class RegExpRouter implements Router { let hasOwnRoute = method === METHOD_NAME_ALL - ;[this.middleware!, this.routes!].forEach((r) => { + ;[this.#middleware!, this.#routes!].forEach((r) => { const ownRoute = r[method] ? Object.keys(r[method]).map((path) => [path, r[method][path]]) : [] diff --git a/src/router/reg-exp-router/trie.ts b/src/router/reg-exp-router/trie.ts index 39bf99f7..f7daacad 100644 --- a/src/router/reg-exp-router/trie.ts +++ b/src/router/reg-exp-router/trie.ts @@ -4,8 +4,8 @@ import { Node } from './node' export type ReplacementMap = number[] export class Trie { - context: Context = { varIndex: 0 } - root: Node = new Node() + #context: Context = { varIndex: 0 } + #root: Node = new Node() insert(path: string, index: number, pathErrorCheckOnly: boolean): ParamAssocArray { const paramAssoc: ParamAssocArray = [] @@ -41,13 +41,13 @@ export class Trie { } } - this.root.insert(tokens, index, paramAssoc, this.context, pathErrorCheckOnly) + this.#root.insert(tokens, index, paramAssoc, this.#context, pathErrorCheckOnly) return paramAssoc } buildRegExp(): [RegExp, ReplacementMap, ReplacementMap] { - let regexp = this.root.buildRegExpStr() + let regexp = this.#root.buildRegExpStr() if (regexp === '') { return [/^$/, [], []] // never match } diff --git a/src/router/smart-router/router.ts b/src/router/smart-router/router.ts index 8e7a11a5..9ec464da 100644 --- a/src/router/smart-router/router.ts +++ b/src/router/smart-router/router.ts @@ -3,27 +3,29 @@ import { MESSAGE_MATCHER_IS_ALREADY_BUILT, UnsupportedPathError } from '../../ro export class SmartRouter implements Router { name: string = 'SmartRouter' - routers: Router[] = [] - routes?: [string, string, T][] = [] + #routers: Router[] = [] + #routes?: [string, string, T][] = [] - constructor(init: Pick, 'routers'>) { - Object.assign(this, init) + constructor(init: { routers: Router[] }) { + this.#routers = init.routers } add(method: string, path: string, handler: T) { - if (!this.routes) { + if (!this.#routes) { throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT) } - this.routes.push([method, path, handler]) + this.#routes.push([method, path, handler]) } match(method: string, path: string): Result { - if (!this.routes) { + if (!this.#routes) { throw new Error('Fatal error') } - const { routers, routes } = this + const routers = this.#routers + const routes = this.#routes + const len = routers.length let i = 0 let res @@ -42,8 +44,8 @@ export class SmartRouter implements Router { } this.match = router.match.bind(router) - this.routers = [router] - this.routes = undefined + this.#routers = [router] + this.#routes = undefined break } @@ -59,10 +61,10 @@ export class SmartRouter implements Router { } get activeRouter(): Router { - if (this.routes || this.routers.length !== 1) { + if (this.#routes || this.#routers.length !== 1) { throw new Error('No active router has been determined yet.') } - return this.routers[0] + return this.#routers[0] } } diff --git a/src/router/trie-router/node.ts b/src/router/trie-router/node.ts index 2d0ae6c3..1efe89d2 100644 --- a/src/router/trie-router/node.ts +++ b/src/router/trie-router/node.ts @@ -14,26 +14,26 @@ type HandlerParamsSet = HandlerSet & { } export class Node { - methods: Record>[] + #methods: Record>[] - children: Record> - patterns: Pattern[] - order: number = 0 - params: Record = Object.create(null) + #children: Record> + #patterns: Pattern[] + #order: number = 0 + #params: Record = Object.create(null) constructor(method?: string, handler?: T, children?: Record>) { - this.children = children || Object.create(null) - this.methods = [] + this.#children = children || Object.create(null) + this.#methods = [] if (method && handler) { const m: Record> = Object.create(null) m[method] = { handler, possibleKeys: [], score: 0 } - this.methods = [m] + this.#methods = [m] } - this.patterns = [] + this.#patterns = [] } insert(method: string, path: string, handler: T): Node { - this.order = ++this.order + this.#order = ++this.#order // eslint-disable-next-line @typescript-eslint/no-this-alias let curNode: Node = this @@ -44,8 +44,8 @@ export class Node { for (let i = 0, len = parts.length; i < len; i++) { const p: string = parts[i] - if (Object.keys(curNode.children).includes(p)) { - curNode = curNode.children[p] + if (Object.keys(curNode.#children).includes(p)) { + curNode = curNode.#children[p] const pattern = getPattern(p) if (pattern) { possibleKeys.push(pattern[1]) @@ -53,14 +53,14 @@ export class Node { continue } - curNode.children[p] = new Node() + curNode.#children[p] = new Node() const pattern = getPattern(p) if (pattern) { - curNode.patterns.push(pattern) + curNode.#patterns.push(pattern) possibleKeys.push(pattern[1]) } - curNode = curNode.children[p] + curNode = curNode.#children[p] } const m: Record> = Object.create(null) @@ -68,11 +68,11 @@ export class Node { const handlerSet: HandlerSet = { handler, possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i), - score: this.order, + score: this.#order, } m[method] = handlerSet - curNode.methods.push(m) + curNode.#methods.push(m) return curNode } @@ -85,8 +85,8 @@ export class Node { params: Record ): HandlerParamsSet[] { const handlerSets: HandlerParamsSet[] = [] - for (let i = 0, len = node.methods.length; i < len; i++) { - const m = node.methods[i] + for (let i = 0, len = node.#methods.length; i < len; i++) { + const m = node.#methods[i] const handlerSet = (m[method] || m[METHOD_NAME_ALL]) as HandlerParamsSet const processedSet: Record = {} if (handlerSet !== undefined) { @@ -107,7 +107,7 @@ export class Node { search(method: string, path: string): [[T, Params][]] { const handlerSets: HandlerParamsSet[] = [] - this.params = Object.create(null) + this.#params = Object.create(null) // eslint-disable-next-line @typescript-eslint/no-this-alias const curNode: Node = this @@ -121,42 +121,42 @@ export class Node { for (let j = 0, len2 = curNodes.length; j < len2; j++) { const node = curNodes[j] - const nextNode = node.children[part] + const nextNode = node.#children[part] if (nextNode) { - nextNode.params = node.params + nextNode.#params = node.#params if (isLast) { // '/hello/*' => match '/hello' - if (nextNode.children['*']) { + if (nextNode.#children['*']) { handlerSets.push( ...this.#getHandlerSets( - nextNode.children['*'], + nextNode.#children['*'], method, - node.params, + node.#params, Object.create(null) ) ) } handlerSets.push( - ...this.#getHandlerSets(nextNode, method, node.params, Object.create(null)) + ...this.#getHandlerSets(nextNode, method, node.#params, Object.create(null)) ) } else { tempNodes.push(nextNode) } } - for (let k = 0, len3 = node.patterns.length; k < len3; k++) { - const pattern = node.patterns[k] + for (let k = 0, len3 = node.#patterns.length; k < len3; k++) { + const pattern = node.#patterns[k] - const params = { ...node.params } + const params = { ...node.#params } // Wildcard // '/hello/*/foo' => match /hello/bar/foo if (pattern === '*') { - const astNode = node.children['*'] + const astNode = node.#children['*'] if (astNode) { handlerSets.push( - ...this.#getHandlerSets(astNode, method, node.params, Object.create(null)) + ...this.#getHandlerSets(astNode, method, node.#params, Object.create(null)) ) tempNodes.push(astNode) } @@ -169,27 +169,27 @@ export class Node { const [key, name, matcher] = pattern - const child = node.children[key] + const child = node.#children[key] // `/js/:filename{[a-z]+.js}` => match /js/chunk/123.js const restPathString = parts.slice(i).join('/') if (matcher instanceof RegExp && matcher.test(restPathString)) { params[name] = restPathString - handlerSets.push(...this.#getHandlerSets(child, method, node.params, params)) + handlerSets.push(...this.#getHandlerSets(child, method, node.#params, params)) continue } if (matcher === true || matcher.test(part)) { params[name] = part if (isLast) { - handlerSets.push(...this.#getHandlerSets(child, method, params, node.params)) - if (child.children['*']) { + handlerSets.push(...this.#getHandlerSets(child, method, params, node.#params)) + if (child.#children['*']) { handlerSets.push( - ...this.#getHandlerSets(child.children['*'], method, params, node.params) + ...this.#getHandlerSets(child.#children['*'], method, params, node.#params) ) } } else { - child.params = params + child.#params = params tempNodes.push(child) } } diff --git a/src/router/trie-router/router.ts b/src/router/trie-router/router.ts index 65700ffd..65b99788 100644 --- a/src/router/trie-router/router.ts +++ b/src/router/trie-router/router.ts @@ -4,25 +4,25 @@ import { Node } from './node' export class TrieRouter implements Router { name: string = 'TrieRouter' - node: Node + #node: Node constructor() { - this.node = new Node() + this.#node = new Node() } add(method: string, path: string, handler: T) { const results = checkOptionalParameter(path) if (results) { for (let i = 0, len = results.length; i < len; i++) { - this.node.insert(method, results[i], handler) + this.#node.insert(method, results[i], handler) } return } - this.node.insert(method, path, handler) + this.#node.insert(method, path, handler) } match(method: string, path: string): Result { - return this.node.search(method, path) + return this.#node.search(method, path) } }