mirror of
https://github.com/alex8088/electron-vite.git
synced 2025-11-10 22:43:34 +08:00
perf(plugin): more efficient module filtering via regular expressions
This commit is contained in:
parent
28bb22b353
commit
70e027d38a
@ -3,48 +3,15 @@ import fs from 'node:fs/promises'
|
|||||||
import type { SourceMapInput } from 'rollup'
|
import type { SourceMapInput } from 'rollup'
|
||||||
import { type Plugin, normalizePath } from 'vite'
|
import { type Plugin, normalizePath } from 'vite'
|
||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
import { cleanUrl, parseRequest, getHash, toRelativePath } from '../utils'
|
import { cleanUrl, getHash, toRelativePath } from '../utils'
|
||||||
|
|
||||||
interface AssetResolved {
|
|
||||||
type: 'asset' | 'native' | 'wasm'
|
|
||||||
file: string
|
|
||||||
query: Record<string, string> | null
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveAsset(id: string): AssetResolved | null {
|
|
||||||
const file = cleanUrl(id)
|
|
||||||
const query = parseRequest(id)
|
|
||||||
|
|
||||||
if (query && typeof query.asset === 'string') {
|
|
||||||
return {
|
|
||||||
type: 'asset',
|
|
||||||
file,
|
|
||||||
query
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.endsWith('.node')) {
|
|
||||||
return {
|
|
||||||
type: 'native',
|
|
||||||
file,
|
|
||||||
query
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id.endsWith('.wasm?loader')) {
|
|
||||||
return {
|
|
||||||
type: 'wasm',
|
|
||||||
file,
|
|
||||||
query
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const nodeAssetRE = /__VITE_NODE_ASSET__([\w$]+)__/g
|
const nodeAssetRE = /__VITE_NODE_ASSET__([\w$]+)__/g
|
||||||
const nodePublicAssetRE = /__VITE_NODE_PUBLIC_ASSET__([a-z\d]{8})__/g
|
const nodePublicAssetRE = /__VITE_NODE_PUBLIC_ASSET__([a-z\d]{8})__/g
|
||||||
|
|
||||||
|
const assetImportRE = /(?:[?|&]asset(?:&|$)|\.wasm\?loader$|\.node$)/
|
||||||
|
const assetRE = /[?|&]asset(?:&|$)/
|
||||||
|
const assetUnpackRE = /[?|&]asset&asarUnpack$/
|
||||||
|
|
||||||
const wasmHelperId = '\0__electron-vite-wasm-helper'
|
const wasmHelperId = '\0__electron-vite-wasm-helper'
|
||||||
|
|
||||||
const wasmHelperCode = `
|
const wasmHelperCode = `
|
||||||
@ -87,19 +54,12 @@ export default function assetPlugin(): Plugin {
|
|||||||
return wasmHelperCode
|
return wasmHelperCode
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.startsWith('\0')) {
|
if (id.startsWith('\0') || !assetImportRE.test(id)) {
|
||||||
// Rollup convention, this id should be handled by the
|
|
||||||
// plugin that marked it with \0
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const assetResolved = resolveAsset(id)
|
|
||||||
if (!assetResolved) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let referenceId: string
|
let referenceId: string
|
||||||
const file = assetResolved.file
|
const file = cleanUrl(id)
|
||||||
if (publicDir && file.startsWith(publicDir)) {
|
if (publicDir && file.startsWith(publicDir)) {
|
||||||
const hash = getHash(file)
|
const hash = getHash(file)
|
||||||
if (!publicAssetPathCache.get(hash)) {
|
if (!publicAssetPathCache.get(hash)) {
|
||||||
@ -122,8 +82,8 @@ export default function assetPlugin(): Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assetResolved.type === 'asset') {
|
if (assetRE.test(id)) {
|
||||||
if (assetResolved.query && typeof assetResolved.query.asarUnpack === 'string') {
|
if (assetUnpackRE.test(id)) {
|
||||||
return `
|
return `
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
export default join(__dirname, ${referenceId}).replace('app.asar', 'app.asar.unpacked')`
|
export default join(__dirname, ${referenceId}).replace('app.asar', 'app.asar.unpacked')`
|
||||||
@ -134,11 +94,11 @@ export default function assetPlugin(): Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assetResolved.type === 'native') {
|
if (id.endsWith('.node')) {
|
||||||
return `export default require(${referenceId})`
|
return `export default require(${referenceId})`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (assetResolved.type === 'wasm') {
|
if (id.endsWith('.wasm?loader')) {
|
||||||
return `
|
return `
|
||||||
import loadWasm from ${JSON.stringify(wasmHelperId)}
|
import loadWasm from ${JSON.stringify(wasmHelperId)}
|
||||||
export default importObject => loadWasm(${referenceId}, importObject)`
|
export default importObject => loadWasm(${referenceId}, importObject)`
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import path from 'node:path'
|
|||||||
import { type Plugin, type InlineConfig, build as viteBuild, mergeConfig } from 'vite'
|
import { type Plugin, type InlineConfig, build as viteBuild, mergeConfig } from 'vite'
|
||||||
import type { SourceMapInput, RollupOutput, OutputOptions } from 'rollup'
|
import type { SourceMapInput, RollupOutput, OutputOptions } from 'rollup'
|
||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
import { cleanUrl, parseRequest, toRelativePath } from '../utils'
|
import { cleanUrl, toRelativePath } from '../utils'
|
||||||
|
|
||||||
const modulePathRE = /__VITE_MODULE_PATH__([\w$]+)__/g
|
const modulePathRE = /__VITE_MODULE_PATH__([\w$]+)__/g
|
||||||
|
|
||||||
@ -18,17 +18,10 @@ export default function modulePathPlugin(config: InlineConfig): Plugin {
|
|||||||
configResolved(config): void {
|
configResolved(config): void {
|
||||||
sourcemap = config.build.sourcemap
|
sourcemap = config.build.sourcemap
|
||||||
},
|
},
|
||||||
resolveId(id, importer): string | void {
|
|
||||||
const query = parseRequest(id)
|
|
||||||
if (query && typeof query.modulePath === 'string') {
|
|
||||||
return id + `&importer=${importer}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async load(id): Promise<string | void> {
|
async load(id): Promise<string | void> {
|
||||||
const query = parseRequest(id)
|
if (id.endsWith('?modulePath')) {
|
||||||
if (query && typeof query.modulePath === 'string' && typeof query.importer === 'string') {
|
// id resolved by Vite resolve plugin
|
||||||
const entry = path.resolve(path.dirname(query.importer), cleanUrl(id))
|
const bundle = await bundleEntryFile(cleanUrl(id), config)
|
||||||
const bundle = await bundleEntryFile(entry, config)
|
|
||||||
const [outputChunk, ...outputChunks] = bundle.output
|
const [outputChunk, ...outputChunks] = bundle.output
|
||||||
const hash = this.emitFile({
|
const hash = this.emitFile({
|
||||||
type: 'asset',
|
type: 'asset',
|
||||||
@ -44,8 +37,8 @@ export default function modulePathPlugin(config: InlineConfig): Plugin {
|
|||||||
})
|
})
|
||||||
const refId = `__VITE_MODULE_PATH__${hash}__`
|
const refId = `__VITE_MODULE_PATH__${hash}__`
|
||||||
return `
|
return `
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
export default join(__dirname, ${refId})`
|
export default join(__dirname, ${refId})`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderChunk(code, chunk): { code: string; map: SourceMapInput } | null {
|
renderChunk(code, chunk): { code: string; map: SourceMapInput } | null {
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import type { Plugin } from 'vite'
|
import type { Plugin } from 'vite'
|
||||||
import type { SourceMapInput } from 'rollup'
|
import type { SourceMapInput } from 'rollup'
|
||||||
import MagicString from 'magic-string'
|
import MagicString from 'magic-string'
|
||||||
import { cleanUrl, parseRequest, toRelativePath } from '../utils'
|
import { cleanUrl, toRelativePath } from '../utils'
|
||||||
|
|
||||||
const nodeWorkerAssetUrlRE = /__VITE_NODE_WORKER_ASSET__([\w$]+)__/g
|
const nodeWorkerAssetUrlRE = /__VITE_NODE_WORKER_ASSET__([\w$]+)__/g
|
||||||
|
const nodeWorkerRE = /\?nodeWorker(?:&|$)/
|
||||||
|
const nodeWorkerImporterRE = /(?:\?)nodeWorker&importer=([^&]+)(?:&|$)/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve `?nodeWorker` import and automatically generate `Worker` wrapper.
|
* Resolve `?nodeWorker` import and automatically generate `Worker` wrapper.
|
||||||
@ -18,24 +20,24 @@ export default function workerPlugin(): Plugin {
|
|||||||
sourcemap = config.build.sourcemap
|
sourcemap = config.build.sourcemap
|
||||||
},
|
},
|
||||||
resolveId(id, importer): string | void {
|
resolveId(id, importer): string | void {
|
||||||
const query = parseRequest(id)
|
if (id.endsWith('?nodeWorker')) {
|
||||||
if (query && typeof query.nodeWorker === 'string') {
|
|
||||||
return id + `&importer=${importer}`
|
return id + `&importer=${importer}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
load(id): string | void {
|
load(id): string | void {
|
||||||
const query = parseRequest(id)
|
if (nodeWorkerRE.test(id)) {
|
||||||
if (query && typeof query.nodeWorker === 'string' && typeof query.importer === 'string') {
|
const match = nodeWorkerImporterRE.exec(id)
|
||||||
const cleanPath = cleanUrl(id)
|
if (match) {
|
||||||
const hash = this.emitFile({
|
const hash = this.emitFile({
|
||||||
type: 'chunk',
|
type: 'chunk',
|
||||||
id: cleanPath,
|
id: cleanUrl(id),
|
||||||
importer: query.importer
|
importer: match[1]
|
||||||
})
|
})
|
||||||
const assetRefId = `__VITE_NODE_WORKER_ASSET__${hash}__`
|
const assetRefId = `__VITE_NODE_WORKER_ASSET__${hash}__`
|
||||||
return `
|
return `
|
||||||
import { Worker } from 'node:worker_threads';
|
import { Worker } from 'node:worker_threads';
|
||||||
export default function (options) { return new Worker(new URL(${assetRefId}, import.meta.url), options); }`
|
export default function (options) { return new Worker(new URL(${assetRefId}, import.meta.url), options); }`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
renderChunk(code, chunk): { code: string; map: SourceMapInput } | null {
|
renderChunk(code, chunk): { code: string; map: SourceMapInput } | null {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { URL, URLSearchParams } from 'node:url'
|
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import { createHash } from 'node:crypto'
|
import { createHash } from 'node:crypto'
|
||||||
@ -20,14 +19,6 @@ export const hashRE = /#.*$/s
|
|||||||
|
|
||||||
export const cleanUrl = (url: string): string => url.replace(hashRE, '').replace(queryRE, '')
|
export const cleanUrl = (url: string): string => url.replace(hashRE, '').replace(queryRE, '')
|
||||||
|
|
||||||
export function parseRequest(id: string): Record<string, string> | null {
|
|
||||||
const { search } = new URL(id, 'file:')
|
|
||||||
if (!search) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return Object.fromEntries(new URLSearchParams(search))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHash(text: Buffer | string): string {
|
export function getHash(text: Buffer | string): string {
|
||||||
return createHash('sha256')
|
return createHash('sha256')
|
||||||
.update(text as unknown as Uint8Array)
|
.update(text as unknown as Uint8Array)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user