Skip to content

Commit

Permalink
perf: optimize path matches
Browse files Browse the repository at this point in the history
  • Loading branch information
pengzhanbo committed Jan 12, 2023
1 parent 56da840 commit 7ee6fed
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 16 deletions.
12 changes: 12 additions & 0 deletions src/pathRules.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { pathToRegexp } from 'path-to-regexp'

export type FindPathRule = (pathname: string) => string | undefined

export function generatePathRules(prefix: string) {
return [
'/bg/:background/text/:text/:width?/:height?{.:type}?',
Expand All @@ -7,3 +11,11 @@ export function generatePathRules(prefix: string) {
'/:width?/:height?{.:type}?',
].map((_) => `${prefix}${_}`)
}

export function createPathRuleMatch(prefix: string): FindPathRule {
const rules = generatePathRules(prefix).map((rule) => ({
regexp: pathToRegexp(rule),
rule,
}))
return (pathname) => rules.find(({ regexp }) => regexp.test(pathname))?.rule
}
9 changes: 4 additions & 5 deletions src/pathToImage.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { parse as urlParse } from 'node:url'
import { match, pathToRegexp } from 'path-to-regexp'
import { match } from 'path-to-regexp'
import type { Create, CreateText } from 'sharp'
import sharp from 'sharp'
import { bufferCache } from './cache'
import { DEFAULT_PARAMS } from './constants'
import type { FindPathRule } from './pathRules'
import type {
ImageCacheItem,
ImagePlaceholderOptions,
Expand All @@ -19,17 +20,15 @@ export type TextOptions = CreateText

export async function pathToImage(
url: string,
rules: string[],
findPathRule: FindPathRule,
options: Required<ImagePlaceholderOptions>,
): Promise<ImageCacheItem | undefined> {
if (bufferCache.has(url)) {
return bufferCache.get(url)
}
const { query: urlQuery, pathname } = urlParse(url, true)

const rule = rules.find((rule) => {
return pathToRegexp(rule).test(pathname!)
})
const rule = findPathRule(pathname!)

if (!rule) return
const urlMatch = match(rule, { decode: decodeURIComponent })(pathname!) || {
Expand Down
24 changes: 13 additions & 11 deletions src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { isCSSRequest } from 'vite'
import { bufferToFile } from './bufferToFile'
import { contentCache } from './cache'
import { DEFAULT_PREFIX } from './constants'
import { generatePathRules } from './pathRules'
import type { FindPathRule } from './pathRules'
import { createPathRuleMatch } from './pathRules'
import { pathToImage } from './pathToImage'
import type {
ImageCacheItem,
Expand Down Expand Up @@ -63,7 +64,7 @@ function placeholderServerPlugin(
options: ImagePlaceholderOptions = {},
): Plugin {
const opts = parseOptions(options)
const pathRules = generatePathRules(opts.prefix)
const findPathRule = createPathRuleMatch(opts.prefix)

return {
name: 'vite-plugin-image-placeholder-server',
Expand All @@ -73,7 +74,7 @@ function placeholderServerPlugin(
const url = req.url!
if (!url.startsWith(opts.prefix)) return next()

const image = await pathToImage(url, pathRules, opts)
const image = await pathToImage(url, findPathRule, opts)

if (!image) return next()

Expand All @@ -89,7 +90,7 @@ function placeholderImporterPlugin(
options: ImagePlaceholderOptions = {},
): Plugin {
const opts = parseOptions(options)
const pathRules = generatePathRules(opts.prefix)
const findPathRule = createPathRuleMatch(opts.prefix)
const RE_VIRTUAL = /^\0virtual:\s*/
const moduleId = `virtual:${opts.prefix.slice(1)}`
const resolveVirtualModuleId = `\0${moduleId}`
Expand All @@ -112,7 +113,7 @@ function placeholderImporterPlugin(
if (contentCache.has(url)) {
return `export default '${contentCache.get(url)!}'`
}
const image = await pathToImage(url, pathRules, opts)
const image = await pathToImage(url, findPathRule, opts)
if (image) {
let content: string
if (
Expand Down Expand Up @@ -143,7 +144,7 @@ function placeholderTransformPlugin(
options: ImagePlaceholderOptions = {},
): Plugin {
const opts = parseOptions(options)
const pathRules = generatePathRules(opts.prefix)
const findPathRule = createPathRuleMatch(opts.prefix)
const moduleId = `virtual:${opts.prefix.slice(1)}`
const resolveVirtualModuleId = `\0${moduleId}`
const s = `(${opts.prefix}.*?)`
Expand Down Expand Up @@ -183,7 +184,7 @@ function placeholderTransformPlugin(
ctx,
code,
RE_PATTERN,
pathRules,
findPathRule,
opts,
config,
)
Expand All @@ -197,7 +198,7 @@ function placeholderTransformPlugin(
ctx,
html,
RE_PATTERN,
pathRules,
findPathRule,
opts,
config,
)
Expand All @@ -211,7 +212,7 @@ async function transformPlaceholder(
ctx: PluginContext,
code: string,
pattern: RegExp,
rules: string[],
findPathRule: FindPathRule,
opts: Required<ImagePlaceholderOptions>,
config: ResolvedConfig,
) {
Expand All @@ -228,13 +229,14 @@ async function transformPlaceholder(
hasReplaced = true
s.update(start, end, `${dynamic[0]}${contentCache.get(url)}${dynamic[1]}`)
} else {
const image = await pathToImage(url, rules, opts)
const image = await pathToImage(url, findPathRule, opts)
if (image) {
hasReplaced = true
let content: string
if (
opts.output &&
image.buffer.byteLength >= config.build.assetsInlineLimit
image.buffer.byteLength >= config.build.assetsInlineLimit &&
config.command === 'build'
) {
const { assetsDir, filename } = parseOutput(opts.output, config)
content = await bufferToFile(
Expand Down

0 comments on commit 7ee6fed

Please sign in to comment.