Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 0 additions & 169 deletions packages/vite/src/node/__tests__/plugins/json.spec.ts

This file was deleted.

13 changes: 8 additions & 5 deletions packages/vite/src/node/plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import aliasPlugin, { type ResolverFunction } from '@rollup/plugin-alias'
import type { ObjectHook } from 'rolldown'
import { viteAliasPlugin as nativeAliasPlugin } from 'rolldown/experimental'
import {
viteAliasPlugin as nativeAliasPlugin,
viteJsonPlugin as nativeJsonPlugin,
viteWasmFallbackPlugin as nativeWasmFallbackPlugin,
} from 'rolldown/experimental'
import type { PluginHookUtils, ResolvedConfig } from '../config'
import {
type HookHandler,
type Plugin,
type PluginWithRequiredHook,
} from '../plugin'
import { watchPackageDataPlugin } from '../packages'
import { jsonPlugin } from './json'
import { oxcResolvePlugin } from './resolve'
import { optimizedDepsPlugin } from './optimizedDeps'
import { importAnalysisPlugin } from './importAnalysis'
import { cssAnalysisPlugin, cssPlugin, cssPostPlugin } from './css'
import { assetPlugin } from './asset'
import { clientInjectionsPlugin } from './clientInjections'
import { buildHtmlPlugin, htmlInlineProxyPlugin } from './html'
import { wasmFallbackPlugin, wasmHelperPlugin } from './wasm'
import { wasmHelperPlugin } from './wasm'
import { modulePreloadPolyfillPlugin } from './modulePreloadPolyfill'
import { webWorkerPlugin } from './worker'
import { preAliasPlugin } from './preAlias'
Expand Down Expand Up @@ -94,14 +97,14 @@ export async function resolvePlugins(
cssPlugin(config),
esbuildBannerFooterCompatPlugin(config),
config.oxc !== false ? oxcPlugin(config) : null,
jsonPlugin(config.json, isBuild, enableNativePluginV1),
nativeJsonPlugin({ ...config.json, minify: isBuild }),
wasmHelperPlugin(config),
webWorkerPlugin(config),
assetPlugin(config),

...normalPlugins,

wasmFallbackPlugin(config),
nativeWasmFallbackPlugin(),
definePlugin(config),
cssPostPlugin(config),
isBundled && buildHtmlPlugin(config),
Expand Down
143 changes: 0 additions & 143 deletions packages/vite/src/node/plugins/json.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
/**
* https://github.com/rollup/plugins/blob/master/packages/json/src/index.js
*
* This source code is licensed under the MIT license found in the
* LICENSE file at
* https://github.com/rollup/plugins/blob/master/LICENSE
*/

import { dataToEsm, makeLegalIdentifier } from '@rollup/pluginutils'
import { viteJsonPlugin as nativeJsonPlugin } from 'rolldown/experimental'
import { SPECIAL_QUERY_RE } from '../constants'
import type { Plugin } from '../plugin'
import { stripBomTag } from '../utils'
import { inlineRE, noInlineRE } from './asset'

export interface JsonOptions {
/**
* Generate a named export for every property of the JSON object
Expand All @@ -28,135 +13,7 @@ export interface JsonOptions {
stringify?: boolean | 'auto'
}

// Custom json filter for vite
const jsonExtRE = /\.json(?:$|\?)(?!commonjs-(?:proxy|external))/

const jsonObjRE = /^\s*\{/

const jsonLangs = `\\.(?:json|json5)(?:$|\\?)`
const jsonLangRE = new RegExp(jsonLangs)
export const isJSONRequest = (request: string): boolean =>
jsonLangRE.test(request)

export function jsonPlugin(
options: Required<JsonOptions>,
isBuild: boolean,
enableNativePlugin: boolean,
): Plugin {
if (enableNativePlugin) {
return nativeJsonPlugin({ ...options, minify: isBuild })
}

return {
name: 'vite:json',

transform: {
filter: {
id: { include: jsonExtRE, exclude: SPECIAL_QUERY_RE },
// don't transform if the file is already transformed to a different format
moduleType: ['json'],
},
handler(json, id) {
if (inlineRE.test(id) || noInlineRE.test(id)) {
this.warn(
`\n` +
`Using ?inline or ?no-inline for JSON imports will have no effect.\n` +
`Please use ?url&inline or ?url&no-inline to control JSON file inlining behavior.\n`,
)
}

json = stripBomTag(json)

try {
if (options.stringify !== false) {
if (options.namedExports && jsonObjRE.test(json)) {
const parsed = JSON.parse(json)
const keys = Object.keys(parsed)

let code = ''
let defaultObjectCode = '{\n'
for (const key of keys) {
if (key === makeLegalIdentifier(key)) {
code += `export const ${key} = ${serializeValue(parsed[key])};\n`
defaultObjectCode += ` ${key},\n`
} else {
defaultObjectCode += ` ${JSON.stringify(key)}: ${serializeValue(parsed[key])},\n`
}
}
defaultObjectCode += '}'

code += `export default ${defaultObjectCode};\n`
return {
code,
map: { mappings: '' },
moduleType: 'js',
}
}

if (
options.stringify === true ||
// use 10kB as a threshold for 'auto'
// https://v8.dev/blog/cost-of-javascript-2019#:~:text=A%20good%20rule%20of%20thumb%20is%20to%20apply%20this%20technique%20for%20objects%20of%2010%20kB%20or%20larger
json.length > 10 * 1000
) {
// during build, parse then double-stringify to remove all
// unnecessary whitespaces to reduce bundle size.
if (isBuild) {
json = JSON.stringify(JSON.parse(json))
}

return {
code: `export default /* #__PURE__ */ JSON.parse(${JSON.stringify(json)})`,
map: { mappings: '' },
moduleType: 'js',
}
}
}

return {
code: dataToEsm(JSON.parse(json), {
preferConst: true,
namedExports: options.namedExports,
}),
map: { mappings: '' },
moduleType: 'js',
}
} catch (e) {
const position = extractJsonErrorPosition(e.message, json.length)
const msg = position
? `, invalid JSON syntax found at position ${position}`
: `.`
this.error(`Failed to parse JSON file` + msg, position)
}
},
},
}
}

function serializeValue(value: unknown): string {
const valueAsString = JSON.stringify(value)
// use 10kB as a threshold
// https://v8.dev/blog/cost-of-javascript-2019#:~:text=A%20good%20rule%20of%20thumb%20is%20to%20apply%20this%20technique%20for%20objects%20of%2010%20kB%20or%20larger
if (
typeof value === 'object' &&
value != null &&
valueAsString.length > 10 * 1000
) {
return `/* #__PURE__ */ JSON.parse(${JSON.stringify(valueAsString)})`
}
return valueAsString
}

export function extractJsonErrorPosition(
errorMessage: string,
inputLength: number,
): number | undefined {
if (errorMessage.startsWith('Unexpected end of JSON input')) {
return inputLength - 1
}

const errorMessageList = /at position (\d+)/.exec(errorMessage)
return errorMessageList
? Math.max(parseInt(errorMessageList[1], 10) - 1, 0)
: undefined
}
Loading