Skip to content

Commit

Permalink
feat: support stringifying json
Browse files Browse the repository at this point in the history
close #1672
  • Loading branch information
yyx990803 committed Jan 24, 2021
1 parent f6b58a0 commit 98c321b
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 49 deletions.
20 changes: 18 additions & 2 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ export default ({ command, mode }) => {
- **Default:** `/`

Base public path when served in development or production. Valid values include:

- Absolute URL pathname, e.g. `/foo/`
- Full URL, e.g. `https://foo.com/`
- Empty string or `./` (for embedded deployment)

See [Public Base Path](/guide/build#public-base-path) for more details.

### mode
Expand Down Expand Up @@ -167,6 +167,22 @@ export default ({ command, mode }) => {
}
```

### json.namedExports

- **Type:** `boolean`
- **Default:** `true`

Whether to support named imports from `.json` files.

### json.stringify

- **Type:** `boolean`
- **Default:** `false`

If set to `true`, imported JSON will be transformed into `export default JSON.parse("...")` which is significantly more performant than Object literals, espeically when the JSON file is large.

Enabling this disables named imports.

### esbuild

- **Type:** `ESBuildOptions | false`
Expand Down
15 changes: 10 additions & 5 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { DepOptimizationOptions } from './optimizer'
import { createFilter } from '@rollup/pluginutils'
import { ResolvedBuildOptions } from '.'
import { parse as parseUrl } from 'url'
import { JsonOptions } from './plugins/json'

const debug = createDebugger('vite:config')

Expand Down Expand Up @@ -58,6 +59,11 @@ export interface UserConfig {
* @default process.cwd()
*/
root?: string
/**
* Base public path when served in development or production.
* @default '/'
*/
base?: string
/**
* Explicitly set a mode to run in. This will override the default mode for
* each command, and can be overridden by the command line --mode option.
Expand All @@ -80,6 +86,10 @@ export interface UserConfig {
* CSS related options (preprocessors and CSS modules)
*/
css?: CSSOptions
/**
* JSON loading options
*/
json?: JsonOptions
/**
* Transform options to pass to esbuild.
* Or set to `false` to disable esbuild.
Expand Down Expand Up @@ -120,11 +130,6 @@ export interface UserConfig {
* Default: true
*/
clearScreen?: boolean
/**
* Base public path when served in development or production.
* @default '/'
*/
base?: string
}

export interface SSROptions {
Expand Down
12 changes: 8 additions & 4 deletions packages/vite/src/node/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ export async function resolvePlugins(
htmlInlineScriptProxyPlugin(),
cssPlugin(config),
config.esbuild !== false ? esbuildPlugin(config.esbuild) : null,
jsonPlugin({
preferConst: true,
namedExports: true
}),
jsonPlugin(
{
preferConst: true,
namedExports: true,
...config.json
},
isBuild
),
wasmPlugin(config),
webWorkerPlugin(config),
assetPlugin(config),
Expand Down
68 changes: 30 additions & 38 deletions packages/vite/src/node/plugins/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,57 @@
* https://github.com/rollup/plugins/blob/master/LICENSE
*/

import { createFilter, dataToEsm } from '@rollup/pluginutils'
import { FilterPattern } from '@rollup/pluginutils'
import { dataToEsm } from '@rollup/pluginutils'
import { Plugin } from 'rollup'

export interface RollupJsonOptions {
/**
* All JSON files will be parsed by default,
* but you can also specifically include files
*/
include?: FilterPattern
/**
* All JSON files will be parsed by default,
* but you can also specifically exclude files
*/
exclude?: FilterPattern
/**
* For tree-shaking, properties will be declared as variables, using
* either `var` or `const`.
* @default false
*/
preferConst?: boolean
/**
* Specify indentation for the generated default export
* @default '\t'
*/
indent?: string
/**
* Ignores indent and generates the smallest code
* @default false
*/
compact?: boolean
export interface JsonOptions {
/**
* Generate a named export for every property of the JSON object
* @default true
*/
namedExports?: boolean
/**
* Generate performant output as JSON.parse("stringified").
* Enabling this will disable namedExports.
* @default false
*/
stringify?: boolean
}

// Custom json filter for vite
const jsonExtRE = new RegExp(`\\.json($|\\?)`)

export function jsonPlugin(options: RollupJsonOptions = {}): Plugin {
const filter = createFilter(options.include, options.exclude)
const indent = 'indent' in options ? options.indent : '\t'

export function jsonPlugin(
options: JsonOptions = {},
isBuild: boolean
): Plugin {
return {
name: 'vite:json',

transform(json, id) {
if (!jsonExtRE.test(id) || !filter(id)) return null
if (!jsonExtRE.test(id)) return null

try {
if (options.stringify) {
if (isBuild) {
return {
// during build, parse then double-stringify to remove all
// unnecessary whitespaces to reduce bundle size.
code: `export default JSON.parse(${JSON.stringify(
JSON.stringify(JSON.parse(json))
)})`,
map: { mappings: '' }
}
} else {
return `export default JSON.parse(${JSON.stringify(json)})`
}
}

const parsed = JSON.parse(json)
return {
code: dataToEsm(parsed, {
preferConst: options.preferConst,
compact: options.compact,
namedExports: options.namedExports,
indent
preferConst: true,
namedExports: options.namedExports
}),
map: { mappings: '' }
}
Expand Down

0 comments on commit 98c321b

Please sign in to comment.