mirror of
https://github.com/alex8088/electron-vite.git
synced 2026-07-07 14:47:06 +08:00
Compare commits
6 Commits
ad50cba495
...
28bb22b353
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28bb22b353 | ||
|
|
327adc23df | ||
|
|
4a6aea3704 | ||
|
|
3f7f65bf57 | ||
|
|
0badfc493f | ||
|
|
cbb039c3e9 |
@ -1,11 +1,11 @@
|
||||
// ts-check
|
||||
|
||||
import { defineConfig } from 'eslint/config'
|
||||
import eslint from '@eslint/js'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
import globals from 'globals'
|
||||
import tseslint from 'typescript-eslint'
|
||||
|
||||
export default tseslint.config(
|
||||
export default defineConfig(
|
||||
{ ignores: ['**/node_modules', '**/dist', '**/bin'] },
|
||||
eslint.configs.recommended,
|
||||
tseslint.configs.recommended,
|
||||
@ -29,6 +29,7 @@ export default tseslint.config(
|
||||
},
|
||||
rules: {
|
||||
'prettier/prettier': 'warn',
|
||||
'no-empty': ['warn', { allowEmptyCatch: true }],
|
||||
'@typescript-eslint/ban-ts-comment': ['error', { 'ts-ignore': 'allow-with-description' }],
|
||||
'@typescript-eslint/explicit-function-return-type': [
|
||||
'error',
|
||||
@ -52,6 +53,10 @@ export default tseslint.config(
|
||||
allowTaggedTemplates: true,
|
||||
allowTernary: true
|
||||
}
|
||||
],
|
||||
'@typescript-eslint/consistent-type-imports': [
|
||||
'error',
|
||||
{ prefer: 'type-imports', disallowTypeAnnotations: false }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
2
node.d.ts
vendored
2
node.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
// node worker
|
||||
declare module '*?nodeWorker' {
|
||||
import { Worker, WorkerOptions } from 'node:worker_threads'
|
||||
import type { Worker, WorkerOptions } from 'node:worker_threads'
|
||||
export default function (options: WorkerOptions): Worker
|
||||
}
|
||||
|
||||
|
||||
39
package.json
39
package.json
@ -69,33 +69,34 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.29.0",
|
||||
"@eslint/js": "^9.37.0",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||
"@rollup/plugin-typescript": "^12.1.3",
|
||||
"@swc/core": "^1.12.7",
|
||||
"@types/node": "^22.15.33",
|
||||
"eslint": "^9.29.0",
|
||||
"eslint-config-prettier": "^10.1.5",
|
||||
"eslint-plugin-prettier": "^5.5.1",
|
||||
"globals": "^16.2.0",
|
||||
"lint-staged": "^16.1.2",
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"@rollup/plugin-typescript": "^12.1.4",
|
||||
"@swc/core": "^1.13.5",
|
||||
"@types/babel__core": "^7.20.5",
|
||||
"@types/node": "^22.18.11",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"globals": "^16.4.0",
|
||||
"lint-staged": "^16.2.4",
|
||||
"prettier": "^3.6.2",
|
||||
"rollup": "^4.44.1",
|
||||
"rollup-plugin-dts": "^6.2.1",
|
||||
"rollup": "^4.52.4",
|
||||
"rollup-plugin-dts": "^6.2.3",
|
||||
"rollup-plugin-rm": "^1.0.2",
|
||||
"simple-git-hooks": "^2.13.0",
|
||||
"simple-git-hooks": "^2.13.1",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.35.0",
|
||||
"vite": "^7.0.0"
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.46.1",
|
||||
"vite": "^7.1.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.27.7",
|
||||
"@babel/core": "^7.28.4",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.27.1",
|
||||
"cac": "^6.7.14",
|
||||
"esbuild": "^0.25.5",
|
||||
"magic-string": "^0.30.17",
|
||||
"esbuild": "^0.25.11",
|
||||
"magic-string": "^0.30.19",
|
||||
"picocolors": "^1.1.1"
|
||||
},
|
||||
"pnpm": {
|
||||
|
||||
1450
pnpm-lock.yaml
generated
1450
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@ import rm from 'rollup-plugin-rm'
|
||||
const require = createRequire(import.meta.url)
|
||||
const pkg = require('./package.json')
|
||||
|
||||
const external = ['esbuild', ...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
|
||||
const external = [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
|
||||
@ -150,7 +150,14 @@ export async function resolveConfig(
|
||||
...electronMainVitePlugin({ root }),
|
||||
assetPlugin(),
|
||||
workerPlugin(),
|
||||
modulePathPlugin(),
|
||||
modulePathPlugin(
|
||||
mergeConfig(
|
||||
{
|
||||
plugins: [electronMainVitePlugin({ root })[0], assetPlugin(), importMetaPlugin(), esmShimPlugin()]
|
||||
},
|
||||
mainViteConfig
|
||||
)
|
||||
),
|
||||
importMetaPlugin(),
|
||||
esmShimPlugin()
|
||||
])
|
||||
@ -417,7 +424,6 @@ async function loadConfigFormBundledFile(
|
||||
} finally {
|
||||
try {
|
||||
fs.unlinkSync(fileNameTmp)
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch {}
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import { spawn } from 'node:child_process'
|
||||
import { createRequire } from 'node:module'
|
||||
import colors from 'picocolors'
|
||||
import { type Plugin, type ResolvedConfig, normalizePath, createFilter } from 'vite'
|
||||
import { type Plugin, type Logger, type LibraryOptions, normalizePath } from 'vite'
|
||||
import * as babel from '@babel/core'
|
||||
import MagicString from 'magic-string'
|
||||
import type { SourceMapInput, OutputChunk } from 'rollup'
|
||||
import type { SourceMapInput, OutputChunk, OutputOptions } from 'rollup'
|
||||
import { getElectronPath } from '../electron'
|
||||
import { toRelativePath } from '../utils'
|
||||
|
||||
@ -159,137 +158,100 @@ export function bytecodePlugin(options: BytecodeOptions = {}): Plugin | null {
|
||||
const { chunkAlias = [], transformArrowFunctions = true, removeBundleJS = true, protectedStrings = [] } = options
|
||||
const _chunkAlias = Array.isArray(chunkAlias) ? chunkAlias : [chunkAlias]
|
||||
|
||||
const filter = createFilter(/\.(m?[jt]s|[jt]sx)$/)
|
||||
|
||||
const escapeRegExpString = (str: string): string => {
|
||||
return str
|
||||
.replace(/\\/g, '\\\\\\\\')
|
||||
.replace(/[|{}()[\]^$+*?.]/g, '\\$&')
|
||||
.replace(/-/g, '\\u002d')
|
||||
}
|
||||
|
||||
const transformAllChunks = _chunkAlias.length === 0
|
||||
const isBytecodeChunk = (chunkName: string): boolean => {
|
||||
return transformAllChunks || _chunkAlias.some(alias => alias === chunkName)
|
||||
}
|
||||
|
||||
const _transform = (code: string): string => {
|
||||
const re = babel.transform(code, {
|
||||
plugins: ['@babel/plugin-transform-arrow-functions']
|
||||
})
|
||||
return re.code || ''
|
||||
const plugins: babel.PluginItem[] = []
|
||||
|
||||
if (transformArrowFunctions) {
|
||||
plugins.push('@babel/plugin-transform-arrow-functions')
|
||||
}
|
||||
|
||||
if (protectedStrings.length > 0) {
|
||||
plugins.push([protectStringsPlugin, { protectedStrings: new Set(protectedStrings) }])
|
||||
}
|
||||
|
||||
const shouldTransformBytecodeChunk = plugins.length !== 0
|
||||
|
||||
const _transform = (code: string, sourceMaps: boolean = false): { code: string; map?: SourceMapInput } | null => {
|
||||
const re = babel.transform(code, { plugins, sourceMaps })
|
||||
return re ? { code: re.code || '', map: re.map } : null
|
||||
}
|
||||
|
||||
let bytecodeChunkCount = 0
|
||||
|
||||
const useStrict = '"use strict";'
|
||||
const bytecodeModuleLoader = 'bytecode-loader.cjs'
|
||||
|
||||
let config: ResolvedConfig
|
||||
let useInRenderer = false
|
||||
let bytecodeRequired = false
|
||||
let bytecodeFiles: { name: string; size: number }[] = []
|
||||
let logger: Logger
|
||||
let sourcemap: boolean | 'inline' | 'hidden' = false
|
||||
let supported = false
|
||||
|
||||
return {
|
||||
name: 'vite:bytecode',
|
||||
apply: 'build',
|
||||
enforce: 'post',
|
||||
configResolved(resolvedConfig): void {
|
||||
config = resolvedConfig
|
||||
useInRenderer = config.plugins.some(p => p.name === 'vite:electron-renderer-preset-config')
|
||||
configResolved(config): void {
|
||||
if (supported) {
|
||||
return
|
||||
}
|
||||
logger = config.logger
|
||||
sourcemap = config.build.sourcemap
|
||||
const useInRenderer = config.plugins.some(p => p.name === 'vite:electron-renderer-preset-config')
|
||||
if (useInRenderer) {
|
||||
config.logger.warn(colors.yellow('bytecodePlugin does not support renderer.'))
|
||||
return
|
||||
}
|
||||
if (resolvedConfig.build.minify && protectedStrings.length > 0) {
|
||||
const build = config.build
|
||||
const resolvedOutputs = resolveBuildOutputs(build.rollupOptions.output, build.lib)
|
||||
if (resolvedOutputs) {
|
||||
const outputs = Array.isArray(resolvedOutputs) ? resolvedOutputs : [resolvedOutputs]
|
||||
const output = outputs[0]
|
||||
if (output.format === 'es') {
|
||||
config.logger.warn(
|
||||
colors.yellow(
|
||||
'bytecodePlugin does not support ES module, please remove "type": "module" ' +
|
||||
'in package.json or set the "build.rollupOptions.output.format" option to "cjs".'
|
||||
)
|
||||
)
|
||||
}
|
||||
supported = output.format === 'cjs' && !useInRenderer
|
||||
}
|
||||
if (supported && config.build.minify && protectedStrings.length > 0) {
|
||||
config.logger.warn(colors.yellow('Strings cannot be protected when minification is enabled.'))
|
||||
}
|
||||
},
|
||||
transform(code, id): void | { code: string; map: SourceMapInput } {
|
||||
if (config.build.minify || protectedStrings.length === 0 || !filter(id)) return
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
let s: MagicString | undefined
|
||||
|
||||
protectedStrings.forEach(str => {
|
||||
const escapedStr = escapeRegExpString(str)
|
||||
const re = new RegExp(`\\u0027${escapedStr}\\u0027|\\u0022${escapedStr}\\u0022`, 'g')
|
||||
const charCodes = Array.from(str).map(s => s.charCodeAt(0))
|
||||
const replacement = `String.fromCharCode(${charCodes.toString()})`
|
||||
while ((match = re.exec(code))) {
|
||||
s ||= new MagicString(code)
|
||||
const [full] = match
|
||||
s.overwrite(match.index, match.index + full.length, replacement, {
|
||||
contentOnly: true
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
if (s) {
|
||||
return {
|
||||
code: s.toString(),
|
||||
map: config.build.sourcemap ? s.generateMap({ hires: 'boundary' }) : null
|
||||
}
|
||||
}
|
||||
},
|
||||
renderChunk(code, chunk, options): { code: string } | null {
|
||||
if (options.format === 'es') {
|
||||
config.logger.warn(
|
||||
colors.yellow(
|
||||
'bytecodePlugin does not support ES module, please remove "type": "module" ' +
|
||||
'in package.json or set the "build.rollupOptions.output.format" option to "cjs".'
|
||||
)
|
||||
)
|
||||
return null
|
||||
}
|
||||
if (useInRenderer) {
|
||||
return null
|
||||
}
|
||||
if (chunk.type === 'chunk' && isBytecodeChunk(chunk.name)) {
|
||||
bytecodeRequired = true
|
||||
if (transformArrowFunctions) {
|
||||
return {
|
||||
code: _transform(code)
|
||||
}
|
||||
}
|
||||
renderChunk(code, chunk): { code: string; map?: SourceMapInput } | null {
|
||||
if (supported && isBytecodeChunk(chunk.name) && shouldTransformBytecodeChunk) {
|
||||
return _transform(code, !!sourcemap)
|
||||
}
|
||||
return null
|
||||
},
|
||||
generateBundle(options): void {
|
||||
if (options.format !== 'es' && !useInRenderer && bytecodeRequired) {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
source: bytecodeModuleLoaderCode.join('\n') + '\n',
|
||||
name: 'Bytecode Loader File',
|
||||
fileName: bytecodeModuleLoader
|
||||
})
|
||||
async generateBundle(_, output): Promise<void> {
|
||||
if (!supported) {
|
||||
return
|
||||
}
|
||||
},
|
||||
async writeBundle(options, output): Promise<void> {
|
||||
if (options.format === 'es' || useInRenderer || !bytecodeRequired) {
|
||||
const _chunks = Object.values(output)
|
||||
const chunks = _chunks.filter(chunk => chunk.type === 'chunk' && isBytecodeChunk(chunk.name)) as OutputChunk[]
|
||||
|
||||
if (chunks.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const outDir = options.dir!
|
||||
|
||||
bytecodeFiles = []
|
||||
|
||||
const bundles = Object.keys(output)
|
||||
const chunks = Object.values(output).filter(
|
||||
chunk => chunk.type === 'chunk' && isBytecodeChunk(chunk.name) && chunk.fileName !== bytecodeModuleLoader
|
||||
) as OutputChunk[]
|
||||
const bytecodeChunks = chunks.map(chunk => chunk.fileName)
|
||||
const nonEntryChunks = chunks.filter(chunk => !chunk.isEntry).map(chunk => path.basename(chunk.fileName))
|
||||
|
||||
const pattern = nonEntryChunks.map(chunk => `(${chunk})`).join('|')
|
||||
const bytecodeRE = pattern ? new RegExp(`require\\(\\S*(?=(${pattern})\\S*\\))`, 'g') : null
|
||||
|
||||
const keepBundle = (chunkFileName: string): void => {
|
||||
const newFileName = path.resolve(path.dirname(chunkFileName), `_${path.basename(chunkFileName)}`)
|
||||
fs.renameSync(chunkFileName, newFileName)
|
||||
}
|
||||
|
||||
const getBytecodeLoaderBlock = (chunkFileName: string): string => {
|
||||
return `require("${toRelativePath(bytecodeModuleLoader, normalizePath(chunkFileName))}");`
|
||||
}
|
||||
|
||||
const bundles = Object.keys(output)
|
||||
|
||||
await Promise.all(
|
||||
bundles.map(async name => {
|
||||
const chunk = output[name]
|
||||
@ -307,26 +269,29 @@ export function bytecodePlugin(options: BytecodeOptions = {}): Plugin | null {
|
||||
}
|
||||
_code = s.toString()
|
||||
}
|
||||
const chunkFileName = path.resolve(outDir, name)
|
||||
if (bytecodeChunks.includes(name)) {
|
||||
const bytecodeBuffer = await compileToBytecode(_code)
|
||||
fs.writeFileSync(path.resolve(outDir, name + 'c'), bytecodeBuffer as unknown as Uint8Array)
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: name + 'c',
|
||||
source: bytecodeBuffer
|
||||
})
|
||||
if (!removeBundleJS) {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: '_' + chunk.fileName,
|
||||
source: chunk.code
|
||||
})
|
||||
}
|
||||
if (chunk.isEntry) {
|
||||
if (!removeBundleJS) {
|
||||
keepBundle(chunkFileName)
|
||||
}
|
||||
const bytecodeLoaderBlock = getBytecodeLoaderBlock(chunk.fileName)
|
||||
const bytecodeModuleBlock = `require("./${path.basename(name) + 'c'}");`
|
||||
const code = `${useStrict}\n${bytecodeLoaderBlock}\n${bytecodeModuleBlock}\n`
|
||||
fs.writeFileSync(chunkFileName, code)
|
||||
chunk.code = code
|
||||
} else {
|
||||
if (removeBundleJS) {
|
||||
fs.unlinkSync(chunkFileName)
|
||||
} else {
|
||||
keepBundle(chunkFileName)
|
||||
}
|
||||
delete output[chunk.fileName]
|
||||
}
|
||||
bytecodeFiles.push({ name: name + 'c', size: bytecodeBuffer.length })
|
||||
bytecodeChunkCount += 1
|
||||
} else {
|
||||
if (chunk.isEntry) {
|
||||
let hasBytecodeMoudle = false
|
||||
@ -343,36 +308,76 @@ export function bytecodePlugin(options: BytecodeOptions = {}): Plugin | null {
|
||||
for (const importerId of dynamicImporters) idsToHandle.add(importerId)
|
||||
}
|
||||
}
|
||||
const bytecodeLoaderBlock = getBytecodeLoaderBlock(chunk.fileName)
|
||||
_code = hasBytecodeMoudle
|
||||
? _code.replace(/("use strict";)|('use strict';)/, `${useStrict}\n${bytecodeLoaderBlock}`)
|
||||
? _code.replace(
|
||||
/("use strict";)|('use strict';)/,
|
||||
`${useStrict}\n${getBytecodeLoaderBlock(chunk.fileName)}`
|
||||
)
|
||||
: _code
|
||||
}
|
||||
fs.writeFileSync(chunkFileName, _code)
|
||||
chunk.code = _code
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
if (bytecodeChunkCount && !_chunks.some(ass => ass.type === 'asset' && ass.fileName === bytecodeModuleLoader)) {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
source: bytecodeModuleLoaderCode.join('\n') + '\n',
|
||||
name: 'Bytecode Loader File',
|
||||
fileName: bytecodeModuleLoader
|
||||
})
|
||||
}
|
||||
},
|
||||
closeBundle(): void {
|
||||
if (!useInRenderer) {
|
||||
const chunkLimit = config.build.chunkSizeWarningLimit
|
||||
const outDir = normalizePath(path.relative(config.root, path.resolve(config.root, config.build.outDir))) + '/'
|
||||
config.logger.info(`${colors.green(`✓`)} ${bytecodeFiles.length} bundles compiled into bytecode.`)
|
||||
let longest = 0
|
||||
bytecodeFiles.forEach(file => {
|
||||
const len = file.name.length
|
||||
if (len > longest) longest = len
|
||||
})
|
||||
bytecodeFiles.forEach(file => {
|
||||
const kbs = file.size / 1000
|
||||
config.logger.info(
|
||||
`${colors.gray(colors.white(colors.dim(outDir)))}${colors.green(file.name.padEnd(longest + 2))} ${
|
||||
kbs > chunkLimit ? colors.yellow(`${kbs.toFixed(2)} kB`) : colors.dim(`${kbs.toFixed(2)} kB`)
|
||||
}`
|
||||
)
|
||||
})
|
||||
bytecodeFiles = []
|
||||
writeBundle(): void {
|
||||
if (supported) {
|
||||
logger.info(`${colors.green(`✓`)} ${bytecodeChunkCount} chunks compiled into bytecode.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function resolveBuildOutputs(
|
||||
outputs: OutputOptions | OutputOptions[] | undefined,
|
||||
libOptions: LibraryOptions | false
|
||||
): OutputOptions | OutputOptions[] | undefined {
|
||||
if (libOptions && !Array.isArray(outputs)) {
|
||||
const libFormats = libOptions.formats || []
|
||||
return libFormats.map(format => ({ ...outputs, format }))
|
||||
}
|
||||
return outputs
|
||||
}
|
||||
|
||||
interface ProtectStringsPluginState extends babel.PluginPass {
|
||||
opts: { protectedStrings: Set<string> }
|
||||
}
|
||||
|
||||
function protectStringsPlugin(api: typeof babel & babel.ConfigAPI): babel.PluginObj<ProtectStringsPluginState> {
|
||||
const { types: t } = api
|
||||
return {
|
||||
name: 'protect-strings-plugin',
|
||||
visitor: {
|
||||
StringLiteral(path, state) {
|
||||
if (
|
||||
path.parentPath.isImportDeclaration() || // import x from 'module'
|
||||
path.parentPath.isExportNamedDeclaration() || // export { x } from 'module'
|
||||
path.parentPath.isExportAllDeclaration() || // export * from 'module'
|
||||
path.parentPath.isObjectProperty({ key: path.node, computed: false }) // { 'key': 'value' }
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const { value } = path.node
|
||||
if (state.opts.protectedStrings.has(value)) {
|
||||
const charCodes = Array.from(value).map(s => s.charCodeAt(0))
|
||||
const charCodeLiterals = charCodes.map(code => t.numericLiteral(code))
|
||||
const replacement = t.callExpression(
|
||||
t.memberExpression(t.identifier('String'), t.identifier('fromCharCode')),
|
||||
charCodeLiterals
|
||||
)
|
||||
path.replaceWith(replacement)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { Plugin } from 'vite'
|
||||
import type { SourceMapInput } from 'rollup'
|
||||
import path from 'node:path'
|
||||
import { type Plugin, type InlineConfig, build as viteBuild, mergeConfig } from 'vite'
|
||||
import type { SourceMapInput, RollupOutput, OutputOptions } from 'rollup'
|
||||
import MagicString from 'magic-string'
|
||||
import { cleanUrl, parseRequest, toRelativePath } from '../utils'
|
||||
|
||||
@ -8,7 +9,7 @@ const modulePathRE = /__VITE_MODULE_PATH__([\w$]+)__/g
|
||||
/**
|
||||
* Resolve `?modulePath` import and return the module bundle path.
|
||||
*/
|
||||
export default function modulePathPlugin(): Plugin {
|
||||
export default function modulePathPlugin(config: InlineConfig): Plugin {
|
||||
let sourcemap: boolean | 'inline' | 'hidden' = false
|
||||
return {
|
||||
name: 'vite:module-path',
|
||||
@ -23,14 +24,23 @@ export default function modulePathPlugin(): Plugin {
|
||||
return id + `&importer=${importer}`
|
||||
}
|
||||
},
|
||||
load(id): string | void {
|
||||
async load(id): Promise<string | void> {
|
||||
const query = parseRequest(id)
|
||||
if (query && typeof query.modulePath === 'string' && typeof query.importer === 'string') {
|
||||
const cleanPath = cleanUrl(id)
|
||||
const entry = path.resolve(path.dirname(query.importer), cleanUrl(id))
|
||||
const bundle = await bundleEntryFile(entry, config)
|
||||
const [outputChunk, ...outputChunks] = bundle.output
|
||||
const hash = this.emitFile({
|
||||
type: 'chunk',
|
||||
id: cleanPath,
|
||||
importer: query.importer
|
||||
type: 'asset',
|
||||
fileName: outputChunk.fileName,
|
||||
source: outputChunk.code
|
||||
})
|
||||
outputChunks.forEach(chunk => {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: chunk.fileName,
|
||||
source: chunk.type === 'chunk' ? chunk.code : chunk.source
|
||||
})
|
||||
})
|
||||
const refId = `__VITE_MODULE_PATH__${hash}__`
|
||||
return `
|
||||
@ -63,3 +73,28 @@ export default function modulePathPlugin(): Plugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function bundleEntryFile(input: string, config: InlineConfig): Promise<RollupOutput> {
|
||||
const viteConfig = mergeConfig(config, {
|
||||
build: {
|
||||
rollupOptions: { input },
|
||||
write: false,
|
||||
watch: false
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
name: 'vite:entry-file-name',
|
||||
outputOptions(output): OutputOptions {
|
||||
if (typeof output.entryFileNames !== 'function' && output.entryFileNames) {
|
||||
output.entryFileNames = '[name]-[hash]' + path.extname(output.entryFileNames)
|
||||
}
|
||||
return output
|
||||
}
|
||||
}
|
||||
],
|
||||
logLevel: 'warn',
|
||||
configFile: false
|
||||
})
|
||||
const bundles = await viteBuild(viteConfig)
|
||||
return bundles as RollupOutput
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user