// this is automatically detected by playground/vitestSetup.ts and will replace
// the default e2e test serve behavior

import path from 'node:path'
import kill from 'kill-port'
import { hmrPorts, isBuild, ports, rootDir } from '~utils'

export const port = ports['ssr-noexternal']

export async function serve(): Promise<{ close(): Promise<void> }> {
  if (isBuild) {
    // build first
    const { build } = await import('vite')
    // server build
    await build({
      root: rootDir,
      logLevel: 'silent',
      build: {
        ssr: 'src/entry-server.js',
      },
    })
  }

  await kill(port)

  const { createServer } = await import(path.resolve(rootDir, 'server.js'))
  const { app, vite } = await createServer(
    rootDir,
    isBuild,
    hmrPorts['ssr-noexternal'],
  )

  return new Promise((resolve, reject) => {
    try {
      const server = app.listen(port, () => {
        resolve({
          // for test teardown
          async close() {
            await new Promise((resolve) => {
              server.close(resolve)
            })
            if (vite) {
              await vite.close()
            }
          },
        })
      })
    } catch (e) {
      reject(e)
    }
  })
}


# <small>nlohmann::basic_json::</small>to_msgpack

```cpp
// (1)
static std::vector<std::uint8_t> to_msgpack(const basic_json& j);

// (2)
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o);
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o);
```

Serializes a given JSON value `j` to a byte vector using the MessagePack serialization format. MessagePack is a binary
serialization format that aims to be more compact than JSON itself, yet more efficient to parse.

1. Returns a byte vector containing the MessagePack serialization.
2. Writes the MessagePack serialization to an output adapter.

The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/messagepack.md).

## Parameters

`j` (in)
:   JSON value to serialize

`o` (in)
:   output adapter to write serialization to

## Return value

1. MessagePack serialization as a byte vector
2. (none)

## Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

## Complexity

Linear in the size of the JSON value `j`.

## Examples

??? example

    The example shows the serialization of a JSON value to a byte vector in MessagePack format.

    ```cpp
    --8<-- "examples/to_msgpack.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/to_msgpack.output"
    ```

## See also

- [from_msgpack](from_msgpack.md) create a JSON value from an input in MessagePack format
- [to_cbor](to_cbor.md) create a CBOR serialization of a JSON value
- [to_bson](to_bson.md) create a BSON serialization of a JSON value
- [to_ubjson](to_ubjson.md) create a UBJSON serialization of a JSON value
- [to_bjdata](to_bjdata.md) create a BJData serialization of a JSON value

## Version history

- Added in version 2.0.9.


#include <iostream>
#include <iomanip>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

int main()
{
    // create two JSON objects
    json o1 = R"( {"color": "red", "price": 17.99, "names": {"de": "Flugzeug"}} )"_json;
    json o2 = R"( {"color": "blue", "speed": 100, "names": {"en": "plane"}} )"_json;
    json o3 = o1;

    // add all keys from o2 to o1 (updating "color", replacing "names")
    o1.update(o2.begin(), o2.end());

    // add all keys from o2 to o1 (updating "color", merging "names")
    o3.update(o2.begin(), o2.end(), true);

    // output updated object o1 and o3
    std::cout << std::setw(2) << o1 << '\n';
    std::cout << std::setw(2) << o3 << '\n';
}


NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES,
    NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES,
    NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES,
    NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES,
    NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES,
    NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES, NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES

```cpp
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_NAMES(type, "json_member_name", member...)
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, "json_member_name", member...)
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, "json_member_name", member...)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES(type, "json_member_name", member...)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, "json_member_name", member...)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, "json_member_name", member...)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_NAMES(type, base_type, "json_member_name", member...)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, base_type, "json_member_name", member...)
#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, base_type, "json_member_name", member...)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_NAMES(type, base_type, "json_member_name", member...)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES(type, base_type, "json_member_name", member...)
#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(type, base_type, "json_member_name", member...)
```

These macros can be used in case you want to use the custom names for the member variables in the resulting JSON.
They behave exactly as their non-`WITH_NAMES` counterparts, but require an additional parameter for each member variable
which will be used in JSON. Both serialization and deserialization will only use the custom names for JSON, the names of
the member variables themselves will be ignored.

Using the named conversion macros will halve the maximum number of member variables from 63 to 31.

For further information please refer to the corresponding macros without `WITH_NAMES`.

## Parameters

`type` (in)
:   name of the type (class, struct) to serialize/deserialize

`base_type` (in)
:   name of the base type (class, struct) `type` is derived from (used only in `DEFINE_DERIVED_TYPE` macros)

`json_member_name` (in)
:   the string that will be used as the name for the next value

`member` (in)
:   name of the member variable to serialize/deserialize

## Examples

??? example "Example (1): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES"

    Consider the following complete example:

    ```cpp hl_lines="16"
    --8<-- "examples/nlohmann_define_type_non_intrusive_with_names_macro.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/nlohmann_define_type_non_intrusive_with_names_macro.output"
    ```

    Notes:

    - `ns::person` is default-constructible. This is a requirement for using the macro.
    - `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES` applicable.
    - The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_NAMES` is used _outside_ the class, but _inside_ its namespace `ns`.
    - A missing key "age" in the deserialization yields an exception. To fall back to the default value,
      `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT_WITH_NAMES` can be used.

    The macro is equivalent to:

    ```cpp hl_lines="16 17 18 19 20 21 22 23 24 25 26 27 28"
    --8<-- "examples/nlohmann_define_type_non_intrusive_with_names_explicit.cpp"
    ```

## Version history

1. Added in version 3.13.0.


# NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH

```cpp
#define NLOHMANN_JSON_VERSION_MAJOR /* value */
#define NLOHMANN_JSON_VERSION_MINOR /* value */
#define NLOHMANN_JSON_VERSION_PATCH /* value */
```

These macros are defined by the library and contain the version numbers according to
[Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).

## Default definition

The macros are defined according to the current library version.

## Examples

??? example

    The example below shows how `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, and
    `NLOHMANN_JSON_VERSION_PATCH` are defined by the library.

    ```cpp
    --8<-- "examples/nlohmann_json_version.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/nlohmann_json_version.output"
    ```

## See also

- [meta](../basic_json/meta.md) - returns version information on the library
- [JSON_SKIP_LIBRARY_VERSION_CHECK](json_skip_library_version_check.md) - skip library version check

## Version history

- Added in version 3.1.0.


import fs from 'node:fs'
import path from 'node:path'
import express from 'express'

const isTest = process.env.VITEST

export async function createServer(
  root = process.cwd(),
  hmrPort,
  customLogger,
) {
  const resolve = (p) => path.resolve(import.meta.dirname, p)

  const app = express()

  /**
   * @type {import('vite').ViteDevServer}
   */
  const vite = await (
    await import('vite')
  ).createServer({
    root,
    logLevel: isTest ? 'error' : 'info',
    server: {
      middlewareMode: true,
      watch: {
        // During tests we edit the files too fast and sometimes chokidar
        // misses change events, so enforce polling for consistency
        usePolling: true,
        interval: 100,
      },
      hmr: {
        port: hmrPort,
      },
    },
    appType: 'custom',
    customLogger,
  })
  // use vite's connect instance as middleware
  app.use(vite.middlewares)

  app.use('*all', async (req, res, next) => {
    try {
      const url = req.originalUrl

      let template
      template = fs.readFileSync(resolve('index.html'), 'utf-8')
      template = await vite.transformIndexHtml(url, template)
      const render = (await vite.ssrLoadModule('/src/app.js')).render

      const appHtml = await render(url, import.meta.dirname)

      const html = template.replace(`<!--app-html-->`, appHtml)

      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
    } catch (e) {
      vite && vite.ssrFixStacktrace(e)
      if (isTest) throw e
      console.log(e.stack)
      res.status(500).end(e.stack)
    }
  })

  return { app, vite }
}

if (!isTest) {
  createServer().then(({ app }) =>
    app.listen(5173, () => {
      console.log('http://localhost:5173')
    }),
  )
}


import path from 'node:path'
import { cleanUrl, withTrailingSlash } from '../shared/utils'
import type { ResolvedConfig } from './config'
import {
  ERR_SYMLINK_IN_RECURSIVE_READDIR,
  normalizePath,
  recursiveReaddir,
  tryStatSync,
} from './utils'

const publicFilesMap = new WeakMap<ResolvedConfig, Set<string>>()

export async function initPublicFiles(
  config: ResolvedConfig,
): Promise<Set<string> | undefined> {
  let fileNames: string[]
  try {
    fileNames = await recursiveReaddir(config.publicDir)
  } catch (e) {
    if (e.code === ERR_SYMLINK_IN_RECURSIVE_READDIR) {
      return
    }
    throw e
  }
  const publicFiles = new Set(
    fileNames.map((fileName) => fileName.slice(config.publicDir.length)),
  )
  publicFilesMap.set(config, publicFiles)
  return publicFiles
}

function getPublicFiles(config: ResolvedConfig): Set<string> | undefined {
  return publicFilesMap.get(config)
}

export function checkPublicFile(
  url: string,
  config: ResolvedConfig,
): string | undefined {
  // note if the file is in /public, the resolver would have returned it
  // as-is so it's not going to be a fully resolved path.
  const { publicDir } = config
  if (!publicDir || url[0] !== '/') {
    return
  }

  const fileName = cleanUrl(url)

  // short-circuit if we have an in-memory publicFiles cache
  const publicFiles = getPublicFiles(config)
  if (publicFiles) {
    return publicFiles.has(fileName)
      ? normalizePath(path.join(publicDir, fileName))
      : undefined
  }

  const publicFile = normalizePath(path.join(publicDir, fileName))
  if (!publicFile.startsWith(withTrailingSlash(publicDir))) {
    // can happen if URL starts with '../'
    return
  }

  return tryStatSync(publicFile)?.isFile() ? publicFile : undefined
}


#![allow(
    clippy::elidable_lifetime_names,
    clippy::extra_unused_type_parameters,
    clippy::needless_lifetimes,
    clippy::type_repetition_in_bounds
)]

#[test]
fn test_gen_custom_serde() {
    #[derive(serde_derive::Serialize, serde_derive::Deserialize)]
    #[serde(crate = "fake_serde")]
    struct Foo;

    // Would be overlapping if serde::Serialize were implemented
    impl AssertNotSerdeSerialize for Foo {}
    // Would be overlapping if serde::Deserialize were implemented
    impl<'a> AssertNotSerdeDeserialize<'a> for Foo {}

    fake_serde::assert::<Foo>();
}

mod fake_serde {
    pub use serde::*;

    pub fn assert<T>()
    where
        T: Serialize,
        T: for<'a> Deserialize<'a>,
    {
    }

    #[allow(dead_code)]
    pub trait Serialize {
        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
    }

    #[allow(dead_code)]
    pub trait Deserialize<'a>: Sized {
        fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error>;
    }
}

pub trait AssertNotSerdeSerialize {}

impl<T: serde::Serialize> AssertNotSerdeSerialize for T {}

pub trait AssertNotSerdeDeserialize<'a> {}

impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {}


import { describe, expect, test } from 'vitest'
import {
  browserErrors,
  browserLogs,
  getColor,
  isBuild,
  isServe,
  page,
  readDepOptimizationMetadata,
  serverLogs,
  viteTestUrl,
} from '~utils'

test('default + named imports from cjs dep (react)', async () => {
  await expect.poll(() => page.textContent('.cjs button')).toBe('count is 0')
  await page.click('.cjs button')
  await expect.poll(() => page.textContent('.cjs button')).toBe('count is 1')
})

test('named imports from webpacked cjs (phoenix)', async () => {
  await expect.poll(() => page.textContent('.cjs-phoenix')).toBe('ok')
})

test('default import from webpacked cjs (clipboard)', async () => {
  await expect.poll(() => page.textContent('.cjs-clipboard')).toBe('ok')
})

test('default import from cjs with es-module-flag (dep-cjs-with-es-module-flag)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-with-es-module-flag'))
    .toBe('ok')
})

test('default import from cjs (cjs-dep-cjs-compiled-from-esm)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dep-cjs-compiled-from-esm'))
    .toBe('ok')
})

test('default import from cjs (cjs-dep-cjs-compiled-from-cjs)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dep-cjs-compiled-from-cjs'))
    .toBe('ok')
})

test.runIf(isServe)(
  'named import injected into an optimized dep by a plugin (dep-with-injected-import)',
  async () => {
    await expect
      .poll(() => page.textContent('.injected-import-in-optimized-dep'))
      .toBe('msg from injected cjs import')
  },
)

test('dynamic imports from cjs dep (react)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dynamic button'))
    .toBe('count is 0')
  await page.click('.cjs-dynamic button')
  await expect
    .poll(() => page.textContent('.cjs-dynamic button'))
    .toBe('count is 1')
})

test('dynamic named imports from webpacked cjs (phoenix)', async () => {
  await expect.poll(() => page.textContent('.cjs-dynamic-phoenix')).toBe('ok')
})

test('dynamic default import from webpacked cjs (clipboard)', async () => {
  await expect.poll(() => page.textContent('.cjs-dynamic-clipboard')).toBe('ok')
})

test('dynamic default import from cjs (cjs-dynamic-dep-cjs-compiled-from-esm)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dynamic-dep-cjs-compiled-from-esm'))
    .toBe('ok')
})

test('dynamic default import from cjs (cjs-dynamic-dep-cjs-compiled-from-cjs)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dynamic-dep-cjs-compiled-from-cjs'))
    .toBe('ok')
})

test('dynamic default import from cjs with es-module-flag (cjs-dynamic-dep-cjs-with-es-module-flag)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dynamic-dep-cjs-with-es-module-flag'))
    .toBe('ok')
})

test('dynamic import from format-ambiguous importer respects __esModule flag (cjs-dynamic-importer-ambiguous)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dynamic-importer-ambiguous'))
    .toBe('ok')
})

test('dynamic import from explicit cjs importer uses node interop (cjs-dynamic-importer-cjs)', async () => {
  await expect
    .poll(() => page.textContent('.cjs-dynamic-importer-cjs'))
    .toBe('ok')
})

test('dedupe', async () => {
  await expect.poll(() => page.textContent('.dedupe button')).toBe('count is 0')
  await page.click('.dedupe button')
  await expect.poll(() => page.textContent('.dedupe button')).toBe('count is 1')
})

test('cjs browser field (axios)', async () => {
  await expect.poll(() => page.textContent('.cjs-browser-field')).toBe('pong')
})

test('cjs browser field bare', async () => {
  await expect
    .poll(() => page.textContent('.cjs-browser-field-bare'))
    .toBe('pong')
})

test('dep from linked dep (lodash-es)', async () => {
  await expect.poll(() => page.textContent('.deps-linked')).toBe('fooBarBaz')
})

test('forced include', async () => {
  await expect
    .poll(() => page.textContent('.force-include'))
    .toMatch(`[success]`)
})

test('import * from optimized dep', async () => {
  await expect.poll(() => page.textContent('.import-star')).toMatch(`[success]`)
})

test('import from dep with process.env.NODE_ENV', async () => {
  await expect
    .poll(() => page.textContent('.node-env'))
    .toMatch(isBuild ? 'prod' : 'dev')
})

test('import from dep with .notjs files', async () => {
  await expect.poll(() => page.textContent('.not-js')).toMatch(`[success]`)
})

test('Import from dependency which uses relative path which needs to be resolved by main field', async () => {
  await expect
    .poll(() => page.textContent('.relative-to-main'))
    .toMatch(`[success]`)
})

test('dep with dynamic import', async () => {
  await expect
    .poll(() => page.textContent('.dep-with-dynamic-import'))
    .toMatch(`[success]`)
})

test('dep with optional peer dep', async () => {
  await expect
    .poll(() => page.textContent('.dep-with-optional-peer-dep'))
    .toMatch(`[success]`)
  await expect
    .poll(() => page.textContent('.dep-with-optional-peer-dep-error'))
    .toMatch(`[success]`)
})

test('dep with optional peer dep submodule', async () => {
  await expect
    .poll(() => page.textContent('.dep-with-optional-peer-dep-submodule'))
    .toMatch(`[success]`)
  await expect
    .poll(() => page.textContent('.dep-with-optional-peer-dep-submodule-error'))
    .toMatch(`[success]`)
})

test('dep with optional peer dep (cjs)', async () => {
  await expect
    .poll(() => page.textContent('.dep-with-optional-peer-dep-cjs'))
    .toMatch(`[success]`)
  await expect
    .poll(() => page.textContent('.dep-with-optional-peer-dep-cjs-error'))
    .toMatch(`[success]`)
})

test('dep with css import', async () => {
  await expect.poll(() => getColor('.dep-linked-include')).toBe('red')
})

test('CJS dep with css import', async () => {
  await expect.poll(() => getColor('.cjs-with-assets')).toBe('blue')
})

test('CJS dep requiring dep with css main field', async () => {
  await expect.poll(() => getColor('.cjs-require-css-main-field')).toBe('coral')
})

test('externalize known non-js files in optimize included dep', async () => {
  await expect
    .poll(() => page.textContent('.externalize-known-non-js'))
    .toMatch(`[success]`)
})

test('vue + vuex', async () => {
  await expect.poll(() => page.textContent('.vue')).toMatch(`[success]`)
})

// When we use the Rollup CommonJS plugin instead of esbuild prebundling,
// the esbuild plugins won't apply to dependencies
test.runIf(isServe)('esbuild-plugin', async () => {
  await expect
    .poll(() => page.textContent('.esbuild-plugin'))
    .toMatch(`Hello from an esbuild plugin`)
})

test('import from hidden dir', async () => {
  await expect.poll(() => page.textContent('.hidden-dir')).toBe('hello!')
})

test('import optimize-excluded package that imports optimized-included package', async () => {
  await expect
    .poll(() => page.textContent('.nested-include'))
    .toBe('nested-include')
})

test('import aliased package with colon', async () => {
  await expect.poll(() => page.textContent('.url')).toBe('vite.dev')
})

test('import aliased package using absolute path', async () => {
  await expect
    .poll(() => page.textContent('.alias-using-absolute-path'))
    .toBe('From dep-alias-using-absolute-path')
})

test('variable names are reused in different scripts', async () => {
  await expect
    .poll(() => page.textContent('.reused-variable-names'))
    .toBe('reused')
})

// Regression test for #8428: flattenId must encode '/' and '.' differently
// to avoid collisions between 'lodash/cloneDeep' and 'lodash.clonedeep'
test('flatten id should generate correctly', async () => {
  await expect
    .poll(() => page.textContent('.clonedeep-slash'))
    .toBe('clonedeep-slash')
  await expect
    .poll(() => page.textContent('.clonedeep-dot'))
    .toBe('clonedeep-dot')
  await expect
    .poll(() => page.textContent('.dep-with-plus-subpath'))
    .toBe('plus-subpath')
})

test('non optimized module is not duplicated', async () => {
  await expect
    .poll(() => page.textContent('.non-optimized-module-is-not-duplicated'))
    .toBe('from-absolute-path, from-relative-path')
})

test.runIf(isServe)('error on builtin modules usage', () => {
  expect(browserLogs).toEqual(
    expect.arrayContaining([
      // from dep-with-builtin-module-esm
      expect.stringMatching(/dep-with-builtin-module-esm.*is not a function/),
      // dep-with-builtin-module-esm warnings
      expect.stringContaining(
        'Module "fs" has been externalized for browser compatibility. Cannot access "fs.readFileSync" in client code.',
      ),
      expect.stringContaining(
        'Module "path" has been externalized for browser compatibility. Cannot access "path.join" in client code.',
      ),
      // from dep-with-builtin-module-cjs
      expect.stringMatching(/dep-with-builtin-module-cjs.*is not a function/),
      // dep-with-builtin-module-cjs warnings
      expect.stringContaining(
        'Module "fs" has been externalized for browser compatibility. Cannot access "fs.readFileSync" in client code.',
      ),
      expect.stringContaining(
        'Module "path" has been externalized for browser compatibility. Cannot access "path.join" in client code.',
      ),
    ]),
  )

  expect(browserErrors.map((error) => error.message)).toEqual(
    expect.arrayContaining([
      // from user source code
      expect.stringContaining(
        'Module "buffer" has been externalized for browser compatibility. Cannot access "buffer.Buffer" in client code.',
      ),
      expect.stringContaining(
        'Module "child_process" has been externalized for browser compatibility. Cannot access "child_process.execSync" in client code.',
      ),
    ]),
  )
})

test('pre bundle css require', async () => {
  if (isServe) {
    const response = page.waitForResponse(/@vitejs_test-dep-css-require\.js/)
    await page.goto(viteTestUrl)
    const content = await (await response).text()
    expect(content).toMatch(
      /import\s"\/@fs.+@vitejs\/test-dep-css-require\/style\.css"/,
    )
  }

  await expect.poll(() => getColor('.css-require')).toBe('red')
  await expect.poll(() => getColor('.css-module-require')).toBe('red')
})

test.runIf(isBuild)('no missing deps during build', async () => {
  serverLogs.forEach((log) => {
    // no warning from esbuild css minifier
    expect(log).not.toMatch('Missing dependency found after crawling ended')
  })
})

test('name file limit is 170 characters', async () => {
  if (isServe) {
    const response = page.waitForResponse(
      /@vitejs_longfilename-\w+_[a-zA-Z\d]+\.js\?v=[a-zA-Z\d]+/,
    )
    await page.goto(viteTestUrl)
    const content = await response

    const fromUrl = content.url()
    const stripFolderPart = fromUrl.split('/').at(-1)
    const onlyTheFilePart = stripFolderPart.split('.')[0]
    expect(onlyTheFilePart).toHaveLength(170)
  }
})

describe.runIf(isServe)('optimizeDeps config', () => {
  test('supports include glob syntax', () => {
    const metadata = readDepOptimizationMetadata()
    expect(Object.keys(metadata.optimized)).to.include.members([
      '@vitejs/test-dep-optimize-exports-with-glob',
      '@vitejs/test-dep-optimize-exports-with-glob/named',
      '@vitejs/test-dep-optimize-exports-with-glob/glob-dir/foo',
      '@vitejs/test-dep-optimize-exports-with-glob/glob-dir/bar',
      '@vitejs/test-dep-optimize-exports-with-glob/glob-dir/nested/baz',
      '@vitejs/test-dep-optimize-exports-with-root-glob',
      '@vitejs/test-dep-optimize-exports-with-root-glob/file1.js',
      '@vitejs/test-dep-optimize-exports-with-root-glob/index.js',
      '@vitejs/test-dep-optimize-exports-with-root-glob/dir/file2.js',
      '@vitejs/test-dep-optimize-with-glob',
      '@vitejs/test-dep-optimize-with-glob/index.js',
      '@vitejs/test-dep-optimize-with-glob/named.js',
      '@vitejs/test-dep-optimize-with-glob/glob/foo.js',
      '@vitejs/test-dep-optimize-with-glob/glob/bar.js',
      '@vitejs/test-dep-optimize-with-glob/glob/nested/baz.js',
    ])
  })
})

test('long file name should work', async () => {
  await expect
    .poll(() => page.textContent('.long-file-name'))
    .toMatch(`hello world`)
})

test.runIf(isServe)('warn on incompatible dependency', () => {
  expect(serverLogs).toContainEqual(
    expect.stringContaining(
      'The dependency might be incompatible with the dep optimizer.',
    ),
  )
})

test('import the CommonJS external package that omits the js suffix', async () => {
  await expect.poll(() => page.textContent('.external-package-js')).toBe('okay')
  await expect
    .poll(() => page.textContent('.external-package-scss-js'))
    .toBe('scss')
  await expect
    .poll(() => page.textContent('.external-package-astro-js'))
    .toBe('astro')
  await expect
    .poll(() => page.textContent('.external-package-tsx-js'))
    .toBe('tsx')
})

test('external package name with asset extension', async () => {
  await expect
    .poll(() => page.textContent('.dep-with-asset-ext-no-dual-package'))
    .toBe('true')
  await expect
    .poll(() => page.textContent('.dep-with-asset-ext-prebundled'))
    .toBe(String(isServe))
})

test('dependency with external sub-dependencies', async () => {
  await expect
    .poll(() => page.textContent('.dep-cjs-with-external-deps-object'))
    .toBe('ok')
  await expect
    .poll(() => page.textContent('.dep-cjs-with-external-deps-node-builtin'))
    .toBe('foo bar')
})

test('virtual module with .vue extension does not error during scan', async () => {
  await expect.poll(() => page.textContent('.virtual-module-vue')).toBe('ok')
})

test.runIf(isServe)(
  'no dep scan error for virtual modules with html-like extensions',
  () => {
    // Check that there are no errors related to virtual modules during dep scan
    const scanErrors = serverLogs.filter(
      (log) =>
        log.includes('Failed to scan for dependencies') &&
        log.includes('virtual:'),
    )
    expect(scanErrors).toHaveLength(0)
  },
)

test('should fix relative worker paths in optimized dependencies', async () => {
  await expect
    .poll(() => page.textContent('.worker-lib'))
    .toBe('worker-success')
  await expect
    .poll(() => page.textContent('.worker-nested'))
    .toBe('worker-success')

  const assetMatcher = isBuild
    ? /assets\/logo-[-\w]+\.png/
    : /\/node_modules\/@vitejs\/test-dep-with-assets\/logo\.png/
  await expect.poll(() => page.textContent('.asset-url')).toMatch(assetMatcher)

  const url = await page.textContent('.asset-url')
  const res = await page.request.get(url)
  expect(res.status()).toBe(200)
})


<!doctype html>

    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + Solid</title>


---
title: Vite 3.0 is out!
author:
  name: The Vite Team
date: 2022-07-23
sidebar: false
head:
  - - meta
    - property: og:type
      content: website
  - - meta
    - property: og:title
      content: Announcing Vite 3
  - - meta
    - property: og:image
      content: https://vite.dev/og-image-announcing-vite3.webp
  - - meta
    - property: og:url
      content: https://vite.dev/blog/announcing-vite3
  - - meta
    - property: og:description
      content: Vite 3 Release Announcement
  - - meta
    - name: twitter:card
      content: summary_large_image
---

# Vite 3.0 is out!

_July 23, 2022_ - Check out the [Vite 4.0 announcement](./announcing-vite4.md)

In February last year, [Evan You](https://twitter.com/youyuxi) released Vite 2. Since then, its adoption has grown non-stop, reaching more than 1 million npm downloads per week. A sprawling ecosystem rapidly formed after the release. Vite is powering a renewed innovation race in Web frameworks. [Nuxt 3](https://v3.nuxtjs.org/) uses Vite by default. [SvelteKit](https://kit.svelte.dev/), [Astro](https://astro.build/), [Hydrogen](https://hydrogen.shopify.dev/), and [SolidStart](https://docs.solidjs.com/quick-start) are all built with Vite. [Laravel has now decided to use Vite by default](https://laravel.com/docs/9.x/vite). [Vite Ruby](https://vite-ruby.netlify.app/) shows how Vite can improve Rails DX. [Vitest](https://vitest.dev) is making strides as a Vite-native alternative to Jest. Vite is behind [Cypress](https://docs.cypress.io/guides/component-testing/writing-your-first-component-test) and [Playwright](https://playwright.dev/docs/test-components)'s new Component Testing features, Storybook has [Vite as an official builder](https://github.com/storybookjs/builder-vite). And [the list goes on](https://patak.cat/vite/ecosystem.html). Maintainers from most of these projects got involved in improving the Vite core itself, working closely with the Vite [team](https://vite.dev/team) and other contributors.

![Vite 3 Announcement Cover Image](/og-image-announcing-vite3.webp)

Today, 16 months from the v2 launch we are happy to announce the release of Vite 3. We decided to release a new Vite major at least every year to align with [Node.js's EOL](https://nodejs.org/en/about/releases/), and take the opportunity to review Vite's API regularly with a short migration path for projects in the ecosystem.

Quick links:

- [Docs](/)
- [Migration Guide](https://v3.vite.dev/guide/migration.html)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#300-2022-07-13)

If you are new to Vite, we recommend reading the [Why Vite Guide](https://vite.dev/guide/why.html). Then check out [the Getting Started](https://vite.dev/guide/) and [Features guide](https://vite.dev/guide/features) to see what Vite provides out of the box. As usual, contributions are welcome at [GitHub](https://github.com/vitejs/vite). More than [600 collaborators](https://github.com/vitejs/vite/graphs/contributors) have helped improve Vite so far. Follow the updates on [Twitter](https://twitter.com/vite_js), or join discussions with other Vite users on our [Discord chat server](https://chat.vite.dev).

## New Documentation

Go to [vite.dev](https://vite.dev) to enjoy the new v3 docs. Vite is now using the new [VitePress](https://vitepress.vuejs.org) default theme, with a stunning dark mode between other features.

[![Vite documentation frontpage](../images/v3-docs.webp)](https://vite.dev)

Several projects in the ecosystem have already migrated to it (see [Vitest](https://vitest.dev), [vite-plugin-pwa](https://vite-plugin-pwa.netlify.app/), and [VitePress](https://vitepress.vuejs.org/) itself).

If you need to access the Vite 2 docs, they will remain online at [v2.vite.dev](https://v2.vite.dev). There is also a new [main.vite.dev](https://main.vite.dev) subdomain, where each commit to Vite’s main branch is auto deployed. This is useful when testing beta versions or contributing to the core’s development.

There is also now an official Spanish translation, that has been added to the previous Chinese and Japanese translations:

- [简体中文](https://cn.vite.dev/)
- [日本語](https://ja.vite.dev/)
- [Español](https://es.vite.dev/)

## Create Vite Starter Templates

[create-vite](/guide/#trying-vite-online) templates have been a great tool to quickly test Vite with your favorite framework. In Vite 3, all of the templates got a new theme in line with the new docs. Open them online and start playing with Vite 3 now:

The theme is now shared by all templates. This should help better convey the scope for these starters as minimal templates to get started with Vite. For more complete solutions including linting, testing setup, and other features, there are official Vite-powered templates for some frameworks like [create-vue](https://github.com/vuejs/create-vue) and [create-svelte](https://github.com/sveltejs/kit). There is a community-maintained list of templates at [Awesome Vite](https://github.com/vitejs/awesome-vite#templates).

## Dev Improvements

### Vite CLI

  VITE v3.0.0  ready in 320 ms

  ➜  Local:   http://127.0.0.1:5173/
  ➜  Network: use --host to expose

Apart from the CLI’s aesthetics improvements, you’ll notice that the default dev server port is now 5173 and the preview server listening at 4173. This change ensures Vite will avoid collisions with other tools.

### Improved WebSocket Connection Strategy

One of the pain points of Vite 2 was configuring the server when running behind a proxy. Vite 3 changes the default connection scheme so it works out of the box in most scenarios. All these setups are now tested as part of the Vite Ecosystem CI through [`vite-setup-catalogue`](https://github.com/sapphi-red/vite-setup-catalogue).

### Cold Start Improvements

Vite now avoids full reload during cold start when imports are injected by plugins while crawling the initial statically imported modules ([#8869](https://github.com/vitejs/vite/issues/8869)).

  Click to learn more

In Vite 2.9, both the scanner and optimizer were run in the background. In the best scenario, where the scanner would find every dependency, no reload was needed in cold start. But if the scanner missed a dependency, a new optimization phase and then a reload were needed. Vite was able to avoid some of these reloads in v2.9, as we detected if the new optimized chunks were compatible with the ones the browser had. But if there was a common dep, the sub-chunks could change and a reload was required to avoid duplicated state. In Vite 3, the optimized deps aren't handed to the browser until the crawling of static imports is done. A quick optimization phase is issued if there is a missing dep (for example, injected by a plugin), and only then, the bundled deps are sent. So, a page reload is no longer needed for these cases.

### import.meta.glob

`import.meta.glob` support was rewritten. Read about the new features in the [Glob Import Guide](/guide/features.html#glob-import):

[Multiple Patterns](/guide/features.html#multiple-patterns) can be passed as an array

```js
import.meta.glob(['./dir/*.js', './another/*.js'])
```

[Negative Patterns](/guide/features.html#negative-patterns) are now supported (prefixed with `!`) to ignore some specific files

```js
import.meta.glob(['./dir/*.js', '!**/bar.js'])
```

[Named Imports](/guide/features.html#named-imports) can be specified to improve tree-shaking

```js
import.meta.glob('./dir/*.js', { import: 'setup' })
```

[Custom Queries](/guide/features.html#custom-queries) can be passed to attach metadata

```js
import.meta.glob('./dir/*.js', { query: { custom: 'data' } })
```

[Eager Imports](/guide/features.html#glob-import) is now passed as a flag

```js
import.meta.glob('./dir/*.js', { eager: true })
```

### Aligning WASM Import with Future Standards

The WebAssembly import API has been revised to avoid collisions with future standards and to make it more flexible:

```js
import init from './example.wasm?init'

init().then((instance) => {
  instance.exports.test()
})
```

Learn more in the [WebAssembly guide](/guide/features.html#webassembly)

## Build Improvements

### ESM SSR Build by Default

Most SSR frameworks in the ecosystem were already using ESM builds. So, Vite 3 makes ESM the default format for SSR builds. This allows us to streamline previous [SSR externalization heuristics](https://vite.dev/guide/ssr.html#ssr-externals), externalizing dependencies by default.

### Improved Relative Base Support

Vite 3 now properly supports relative base (using `base: ''`), allowing built assets to be deployed to different bases without re-building. This is useful when the base isn't known at build time, for example when deploying to content-addressable networks like [IPFS](https://ipfs.io/).

## Experimental Features

### Built Asset Paths fine-grained Control (Experimental)

There are other deploy scenarios where this isn't enough. For example, if the generated hashed assets need to be deployed to a different CDN from the public files, then finer-grained control is required over path generation at build time. Vite 3 provides an experimental API to modify the built file paths. Check [Build Advanced Base Options](/guide/build.html#advanced-base-options) for more information.

### Esbuild Deps Optimization at Build Time (Experimental)

One of the main differences between dev and build time is how Vite handles dependencies. During build time, [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is used to allow importing CJS only dependencies (like React). When using the dev server, esbuild is used instead to pre-bundle and optimize dependencies, and an inline interop scheme is applied while transforming user code importing CJS deps. During the development of Vite 3, we introduced the changes needed to also allow the use of [esbuild to optimize dependencies during build time](https://v3.vite.dev/guide/migration.html#using-esbuild-deps-optimization-at-build-time). [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) can then be avoided, making dev and build time work in the same way.

Given that Rollup v3 will be out in the next months, and we're going to follow up with another Vite major, we've decided to make this mode optional to reduce v3 scope and give Vite and the ecosystem more time to work out possible issues with the new CJS interop approach during build time. Frameworks may switch to using esbuild deps optimization during build time by default at their own pace before Vite 4.

### HMR Partial Accept (Experimental)

There is opt-in support for [HMR Partial Accept](https://github.com/vitejs/vite/pull/7324). This feature could unlock finer-grained HMR for framework components that export several bindings in the same module. You can learn more at [the discussion for this proposal](https://github.com/vitejs/vite/discussions/7309).

## Bundle Size Reduction

Vite cares about its publish and install footprint; a fast installation of a new app is a feature. Vite bundles most of its dependencies and tries to use modern lightweight alternatives where possible. Continuing with this ongoing goal, Vite 3 publish size is 30% smaller than v2.

|             | Publish Size | Install Size |
| ----------- | :----------: | :----------: |
| Vite 2.9.14 |    4.38MB    |    19.1MB    |
| Vite 3.0.0  |    3.05MB    |    17.8MB    |
| Reduction   |     -30%     |     -7%      |

In part, this reduction was possible by making some dependencies that most users weren't needing optional. First, [Terser](https://github.com/terser/terser) is no longer installed by default. This dependency was no longer needed since we already made esbuild the default minifier for both JS and CSS in Vite 2. If you use `build.minify: 'terser'`, you'll need to install it (`npm add -D terser`). We also moved [node-forge](https://github.com/digitalbazaar/forge) out of the monorepo, implementing support for automatic https certificate generation as a new plugin: [`@vitejs/plugin-basic-ssl`](https://v3.vite.dev/guide/migration.html#automatic-https-certificate-generation). Since this feature only creates untrusted certificates that are not added to the local store, it didn't justify the added size.

## Bug Fixing

A triaging marathon was spearheaded by [@bluwyoo](https://twitter.com/bluwyoo), [@sapphi_red](https://twitter.com/sapphi_red), that recently joined the Vite team. During the past three months, the Vite open issues were reduced from 770 to 400. And this dive was achieved while the newly open PRs were at an all-time high. At the same time, [@haoqunjiang](https://twitter.com/haoqunjiang) had also curated a comprehensive [overview of Vite issues](https://github.com/vitejs/vite/discussions/8232).

[![Graph of open issues and pull requests in Vite](../images/v3-open-issues-and-PRs.webp)](https://www.repotrends.com/vitejs/vite)

[![Graph of new issues and pull requests in Vite](../images/v3-new-open-issues-and-PRs.webp)](https://www.repotrends.com/vitejs/vite)

## Compatibility Notes

- Vite no longer supports Node.js 12 / 13 / 15, which reached its EOL. Node.js 14.18+ / 16+ is now required.
- Vite is now published as ESM, with a CJS proxy to the ESM entry for compatibility.
- The Modern Browser Baseline now targets browsers which support the [native ES Modules](https://caniuse.com/es6-module), [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import), and [`import.meta`](https://caniuse.com/mdn-javascript_operators_import_meta) features.
- JS file extensions in SSR and library mode now use a valid extension (`js`, `mjs`, or `cjs`) for output JS entries and chunks based on their format and the package type.

Learn more in the [Migration Guide](https://v3.vite.dev/guide/migration.html).

## Upgrades to Vite Core

While working towards Vite 3, we also improved the contributing experience for collaborators to [Vite Core](https://github.com/vitejs/vite).

- Unit and E2E tests have been migrated to [Vitest](https://vitest.dev), providing a faster and more stable DX. This move also works as dog fooding for an important infrastructure project in the ecosystem.
- VitePress build is now tested as part of CI.
- Vite upgraded to [pnpm 7](https://pnpm.io/), following the rest of the ecosystem.
- Playgrounds have been moved to [`/playgrounds`](https://github.com/vitejs/vite/tree/main/playground) out of packages directory.
- The packages and playgrounds are now `"type": "module"`.
- Plugins are now bundled using [unbuild](https://github.com/unjs/unbuild), and [plugin-vue-jsx](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue-jsx) and [plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) were moved to TypeScript.

## The Ecosystem is Ready for v3

We have worked closely with projects in the ecosystem to ensure that frameworks powered by Vite are ready for Vite 3. [vite-ecosystem-ci](https://github.com/vitejs/vite-ecosystem-ci) allows us to run the CI's from the leading players in the ecosystem against Vite's main branch and receive timely reports before introducing a regression. Today's release should soon be compatible with most projects using Vite.

## Acknowledgments

Vite 3 is the result of the aggregate effort of members of the [Vite Team](/team) working together with ecosystem project maintainers and other collaborators to Vite core.

We want to thank everyone who has implemented features, and fixes, given feedback, and have been involved in Vite 3:

- Vite team members [@youyuxi](https://twitter.com/youyuxi), [@patak_dev](https://twitter.com/patak_dev), [@antfu7](https://twitter.com/antfu7), [@bluwyoo](https://twitter.com/bluwyoo), [@sapphi_red](https://twitter.com/sapphi_red), [@haoqunjiang](https://twitter.com/haoqunjiang), [@poyoho](https://github.com/poyoho), [@Shini_92](https://twitter.com/Shini_92), and [@retropragma](https://twitter.com/retropragma).
- [@benmccann](https://github.com/benmccann), [@danielcroe](https://twitter.com/danielcroe), [@brillout](https://twitter.com/brillout), [@sheremet_va](https://twitter.com/sheremet_va), [@userquin](https://twitter.com/userquin), [@enzoinnocenzi](https://twitter.com/enzoinnocenzi), [@maximomussini](https://twitter.com/maximomussini), [@IanVanSchooten](https://twitter.com/IanVanSchooten), the [Astro team](https://astro.build/), and all other maintainers of frameworks and plugins in the ecosystem in that helped shape v3.
- [@dominikg](https://github.com/dominikg) for his work on vite-ecosystem-ci.
- [@ZoltanKochan](https://twitter.com/ZoltanKochan) for his work on [pnpm](https://pnpm.io/), and for his responsiveness when we needed support with it.
- [@rixo](https://github.com/rixo) for HMR Partial Accept support.
- [@KiaKing85](https://twitter.com/KiaKing85) for getting the theme ready for the Vite 3 release, and [@\_brc_dd](https://twitter.com/_brc_dd) for working on the VitePress internals.
- [@CodingWithCego](https://twitter.com/CodingWithCego) for the new Spanish translation, and [@ShenQingchuan](https://twitter.com/ShenQingchuan), [@hiro-lapis](https://github.com/hiro-lapis) and others in the Chinese and Japanese translations teams for keeping the translated docs up to date.

We also want to thank individuals and companies sponsoring the Vite team, and companies investing in Vite development: some of [@antfu7](https://twitter.com/antfu7)'s work on Vite and the ecosystem is part of his job at [Nuxt Labs](https://nuxtlabs.com/), and [StackBlitz](https://stackblitz.com/) hired [@patak_dev](https://twitter.com/patak_dev) to work full time on Vite.

## What's Next

We'll take the following months to ensure a smooth transition for all the projects built on top of Vite. So the first minors will be focused on continuing our triaging efforts with a focus on newly opened issues.

The Rollup team is [working on its next major](https://twitter.com/lukastaegert/status/1544186847399743488), to be released in the following months. Once the Rollup plugins ecosystem has time to update, we'll follow up with a new Vite major. This will give us another opportunity to introduce more significant changes this year, which we could take to stabilize some of the experimental features introduced in this release.

If you are interested in helping improve Vite, the best way to get on board is to help with triaging issues. Join [our Discord](https://chat.vite.dev) and look for the `#contributing` channel. Or get involved in our `#docs`, `#help` others, or create plugins. We are just getting started. There are many open ideas to keep improving Vite's DX.


# Dependency Pre-Bundling

When you run `vite` for the first time, Vite prebundles your project dependencies before loading your site locally. It is done automatically and transparently by default.

## The Why

This is Vite performing what we call "dependency pre-bundling". This process serves two purposes:

1. **CommonJS and UMD compatibility:** During development, Vite serves all code as native ESM. Therefore, Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first.

   When converting CommonJS dependencies, Vite performs smart import analysis so that named imports to CommonJS modules will work as expected even if the exports are dynamically assigned (e.g. React):

   ```js
   // works as expected
   import React, { useState } from 'react'
   ```

2. **Performance:** Vite converts ESM dependencies with many internal modules into a single module to improve subsequent page load performance.

   Some packages ship their ES modules builds as many separate files importing one another. For example, [`lodash-es` has over 600 internal modules](https://unpkg.com/browse/lodash-es/)! When we do `import { debounce } from 'lodash-es'`, the browser fires off 600+ HTTP requests at the same time! Even though the server has no problem handling them, the large number of requests creates network congestion on the browser side, causing the page to load noticeably slower.

   By pre-bundling `lodash-es` into a single module, we now only need one HTTP request instead!

::: tip NOTE
Dependency pre-bundling only applies in development mode.
:::

## Automatic Dependency Discovery

If an existing cache is not found, Vite will crawl your source code and automatically discover dependency imports (i.e. "bare imports" that expect to be resolved from `node_modules`) and use these found imports as entry points for the pre-bundle. The pre-bundling is performed with [Rolldown](https://rolldown.rs/), so it's typically very fast.

After the server has already started, if a new dependency import is encountered that isn't already in the cache, Vite will re-run the dep bundling process and reload the page if needed.

## Monorepos and Linked Dependencies

In a monorepo setup, a dependency may be a linked package from the same repo. Vite automatically detects dependencies that are not resolved from `node_modules` and treats the linked dep as source code. It will not attempt to bundle the linked dep, and will analyze the linked dep's dependency list instead.

However, this requires the linked dep to be exported as ESM. If not, you can add the dependency to [`optimizeDeps.include`](/config/dep-optimization-options.md#optimizedeps-include) in your config.

```js twoslash [vite.config.js]
import { defineConfig } from 'vite'
// ---cut---
export default defineConfig({
  optimizeDeps: {
    include: ['linked-dep'],
  },
})
```

When making changes to the linked dep, restart the dev server with the `--force` command line option for the changes to take effect.

## Customizing the Behavior

The default dependency discovery heuristics may not always be desirable. In cases where you want to explicitly include/exclude dependencies from the list, use the [`optimizeDeps` config options](/config/dep-optimization-options.md).

A typical use case for `optimizeDeps.include` or `optimizeDeps.exclude` is when you have an import that is not directly discoverable in the source code. For example, maybe the import is created as a result of a plugin transform. This means Vite won't be able to discover the import on the initial scan - it can only discover it after the file is requested by the browser and transformed. This will cause the server to immediately re-bundle after server start.

Both `include` and `exclude` can be used to deal with this. If the dependency is large (with many internal modules) or is CommonJS, then you should include it; If the dependency is small and is already valid ESM, you can exclude it and let the browser load it directly.

You can further customize Rolldown too with the [`optimizeDeps.rolldownOptions` option](/config/dep-optimization-options.md#optimizedeps-rolldownoptions). For example, adding a Rolldown plugin to handle special files in dependencies or changing the [build `target`](https://rolldown.rs/reference/InputOptions.transform#target).

## Caching

### File System Cache

Vite caches the pre-bundled dependencies in `node_modules/.vite`. It determines whether it needs to re-run the pre-bundling step based on a few sources:

- Package manager lockfile content, e.g. `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock`, `aube-lock.yaml` or `nub.lock`.
- Patches folder modification time.
- Relevant fields in your `vite.config.js`, if present.
- `NODE_ENV` value.

The pre-bundling step will only need to be re-run when one of the above has changed.

If for some reason you want to force Vite to re-bundle deps, you can either start the dev server with the `--force` command line option, or manually delete the `node_modules/.vite` cache directory.

### Browser Cache

Resolved dependency requests are strongly cached with HTTP headers `max-age=31536000,immutable` to improve page reload performance during dev. Once cached, these requests will never hit the dev server again. They are auto invalidated by the appended version query if a different version is installed (as reflected in your package manager lockfile). If you want to debug your dependencies by making local edits, you can:

1. Temporarily disable cache via the Network tab of your browser devtools.
2. Restart Vite dev server with the `--force` flag to re-bundle the deps.
3. Reload the page.


#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

namespace ns
{
class person
{
  private:
    std::string name = "John Doe";
    std::string address = "123 Fake St";
    int age = -1;

  public:
    // No default constructor
    person(std::string name_, std::string address_, int age_)
        : name(std::move(name_)), address(std::move(address_)), age(age_)
    {}

    template<typename BasicJsonType>
    friend void to_json(BasicJsonType& nlohmann_json_j, const person& nlohmann_json_t)
    {
        nlohmann_json_j["name"] = nlohmann_json_t.name;
        nlohmann_json_j["address"] = nlohmann_json_t.address;
        nlohmann_json_j["age"] = nlohmann_json_t.age;
    }
};
} // namespace ns

int main()
{
    ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

    // serialization: person -> json
    json j = p;
    std::cout << "serialization: " << j << std::endl;
}


import barJson from 'virtual:/bar.json'
import fooJson from './foo.json'

// 'TRANSFORM_COUNT' is injected by the transform plugin
document.getElementById('transform-count').innerHTML = TRANSFORM_COUNT

document.getElementById('module-type-json-pre').innerHTML =
  fooJson.moduleTypePre
document.getElementById('module-type-json-post').innerHTML =
  fooJson.moduleTypePost

document.getElementById('module-type-json-virtual-pre').innerHTML =
  barJson.moduleTypePre
document.getElementById('module-type-json-virtual-post').innerHTML =
  barJson.moduleTypePost

// 'LAZY_HOOK_FILTER_CONTENT' is replaced by lazy-hook-filter plugin
document.getElementById('lazy-hook-filter').innerHTML =
  'LAZY_HOOK_FILTER_CONTENT'


import fs from 'node:fs'
import path from 'node:path'
import type { Plugin } from '../plugin'
import { isInNodeModules, sortObjectKeys } from '../utils'
import type { PackageCache } from '../packages'
import { findNearestMainPackageData } from '../packages'

export interface LicenseEntry {
  /**
   * Package name
   */
  name: string
  /**
   * Package version
   */
  version: string
  /**
   * SPDX license identifier (from package.json "license" field)
   */
  identifier?: string
  /**
   * License file text
   */
  text?: string
}

export interface LicenseOptions {
  /**
   * The output file name of the license file relative to the output directory.
   * Specify a path that ends with `.json` to output the raw JSON metadata.
   *
   * @default '.vite/license.md'
   */
  fileName: string
}

const licenseConfigDefaults = Object.freeze({
  fileName: '.vite/license.md',
} satisfies LicenseOptions)

// https://github.com/npm/npm-packlist/blob/53b2a4f42b7fef0f63e8f26a3ea4692e23a58fed/lib/index.js#L284-L286
const licenseFiles = [/^license/i, /^licence/i, /^copying/i]

export function licensePlugin(): Plugin {
  return {
    name: 'vite:license',

    generateBundle(_, bundle) {
      const licenseOption = this.environment.config.build.license
      if (licenseOption === false) return

      const packageCache: PackageCache = new Map()
      // Track license via a key to its license entry.
      // A key consists of "name@version" of a package.
      const licenses: Record<string, LicenseEntry> = {}

      for (const file in bundle) {
        const chunk = bundle[file]
        if (chunk.type === 'asset') continue

        for (const moduleId of chunk.moduleIds) {
          if (moduleId.startsWith('\0') || !isInNodeModules(moduleId)) continue

          // Find the dependency package.json
          const pkgData = findNearestMainPackageData(
            path.dirname(moduleId),
            packageCache,
          )
          if (!pkgData) continue

          // Grab the package.json keys and check if already exists in the licenses
          const { name, version = '0.0.0', license } = pkgData.data
          const key = `${name}@${version}`
          if (licenses[key]) continue

          // If not, create a new license entry
          const entry: LicenseEntry = { name, version }
          if (license) {
            entry.identifier = license.trim()
          }
          const licenseFile = findLicenseFile(pkgData.dir)
          if (licenseFile) {
            entry.text = fs.readFileSync(licenseFile, 'utf-8').trim()
          }
          licenses[key] = entry
        }
      }

      const licenseEntries = Object.values(sortObjectKeys(licenses))
      const licenseOutputFileName =
        typeof licenseOption === 'object'
          ? licenseOption.fileName
          : licenseConfigDefaults.fileName

      // Emit as a JSON file
      if (licenseOutputFileName.endsWith('.json')) {
        this.emitFile({
          fileName: licenseOutputFileName,
          type: 'asset',
          source: JSON.stringify(licenseEntries, null, 2),
        })
        return
      }

      // Emit a license file as markdown
      const markdown = licenseEntryToMarkdown(licenseEntries)
      this.emitFile({
        fileName: licenseOutputFileName,
        type: 'asset',
        source: markdown,
      })
    },
  }
}

function licenseEntryToMarkdown(licenses: LicenseEntry[]) {
  if (licenses.length === 0) {
    return `\
# Licenses

The app does not bundle any dependencies with licenses.
`
  }

  let text = `\
# Licenses

The app bundles dependencies which contain the following licenses:
`
  for (const license of licenses) {
    const nameAndVersionText = `${license.name} - ${license.version}`
    const identifierText = license.identifier ? ` (${license.identifier})` : ''

    text += `\n## ${nameAndVersionText}${identifierText}\n`
    if (license.text) {
      text += `\n${license.text}\n`
    }
  }
  return text
}

function findLicenseFile(pkgDir: string) {
  const files = fs.readdirSync(pkgDir)
  const matchedFile = files.find((file) =>
    licenseFiles.some((re) => re.test(file)),
  )
  if (matchedFile) {
    return path.join(pkgDir, matchedFile)
  }
}


import a18 from './a18'
import a19 from './a19'
import a20 from './a20'
import a21 from './a21'
import a22 from './a22'
import a23 from './a23'
import a24 from './a24'

export const that = () => import('./a16.js')

export function other() {
  return a18() + a19() + a20() + a21() + a22() + a23() + a24()
}

export default function () {
  return 123
}


export default () => ({
  name: 'plugin-for-worker',
  transform(code, id) {
    if (id.includes('worker/modules/test-plugin.js')) {
      return {
        // keep length for sourcemap
        code: code.replace('plugin fail.   ', 'plugin success!'),
        map: null,
      }
    }
  },
})


import { describe, expect, test } from 'vitest'
import { port } from './serve'
import { editFile, getColor, isServe, page } from '~utils'

const url = `http://localhost:${port}`

/**
 * test for #5809
 */
test('msg should be encrypted', async () => {
  await page.goto(url)
  expect(await page.textContent('.encrypted-msg')).not.toMatch(
    'Secret Message!',
  )
})

test('msg read by fs/promises', async () => {
  await page.goto(url)
  expect(await page.textContent('.file-message')).toMatch('File Content!')
})

test('msg from primitive export', async () => {
  await page.goto(url)
  expect(await page.textContent('.primitive-export-message')).toMatch(
    'Hello World!',
  )
})

test('msg from TS transpiled exports', async () => {
  await page.goto(url)
  expect(await page.textContent('.ts-default-export-message')).toMatch(
    'Hello World!',
  )
  expect(await page.textContent('.ts-named-export-message')).toMatch(
    'Hello World!',
  )
})

test('msg from Object.assign exports', async () => {
  await page.goto(url)
  expect(await page.textContent('.object-assigned-exports-message')).toMatch(
    'Hello World!',
  )
})

test('msg from forwarded exports', async () => {
  await page.goto(url)
  expect(await page.textContent('.forwarded-export-message')).toMatch(
    'Hello World!',
  )
})

test('msg from define properties exports', async () => {
  await page.goto(url)
  expect(await page.textContent('.define-properties-exports-msg')).toMatch(
    'Hello World!',
  )
})

test('msg from define property exports', async () => {
  await page.goto(url)
  expect(await page.textContent('.define-property-exports-msg')).toMatch(
    'Hello World!',
  )
})

test('msg from only object assigned exports', async () => {
  await page.goto(url)
  expect(await page.textContent('.only-object-assigned-exports-msg')).toMatch(
    'Hello World!',
  )
})

test('msg from no external cjs', async () => {
  await page.goto(url)
  expect(await page.textContent('.no-external-cjs-msg')).toMatch('Hello World!')
})

test('msg from optimized with nested external', async () => {
  await page.goto(url)
  expect(await page.textContent('.optimized-with-nested-external')).toMatch(
    'Hello World!',
  )
})

test('msg from optimized cjs with nested external', async () => {
  await page.goto(url)
  expect(await page.textContent('.optimized-cjs-with-nested-external')).toMatch(
    'Hello World!',
  )
})

test('msg from external using external entry', async () => {
  await page.goto(url)
  expect(await page.textContent('.external-using-external-entry')).toMatch(
    'Hello World!',
  )
})

test('msg from linked no external', async () => {
  await page.goto(url)
  expect(await page.textContent('.linked-no-external')).toMatch(
    `Hello World from ${process.env.NODE_ENV}!`,
  )
})

test('msg from linked no external', async () => {
  await page.goto(url)
  expect(await page.textContent('.dep-virtual')).toMatch('[success]')
})

test('import css library', async () => {
  await page.goto(url)
  expect(await getColor('.css-lib')).toBe('blue')
})

test('import css library', async () => {
  await page.goto(url)
  expect(await page.textContent('.module-condition')).toMatch('[success]')
})

test('optimize-deps-nested-include', async () => {
  await page.goto(url)
  expect(await page.textContent('.optimize-deps-nested-include')).toMatch(
    'nested-include',
  )
})

describe.runIf(isServe)('hmr', () => {
  // TODO: the server file is not imported on the client at all
  // so it's not present in the client moduleGraph anymore
  // we need to decide if we want to support a usecase when ssr change
  // affects the client in any way
  test.skip('handle isomorphic module updates', async () => {
    await page.goto(url)

    expect(await page.textContent('.isomorphic-module-server')).toMatch(
      '[server]',
    )
    // Allowing additional time for this element to be filled in
    // by a client script that is loaded using dynamic import
    await expect
      .poll(async () => {
        return page.textContent('.isomorphic-module-browser')
      })
      .toMatch('[browser]')

    editFile('src/isomorphic-module-browser.js', (code) =>
      code.replace('[browser]', '[browser-hmr]'),
    )
    await page.waitForNavigation()
    await expect
      .poll(async () => {
        return page.textContent('.isomorphic-module-browser')
      })
      .toMatch('[browser-hmr]')

    editFile('src/isomorphic-module-server.js', (code) =>
      code.replace('[server]', '[server-hmr]'),
    )
    await page.waitForNavigation()
    await expect
      .poll(async () => {
        return page.textContent('.isomorphic-module-server')
      })
      .toMatch('[server-hmr]')
  })
})


#include <iostream>
#include <nlohmann/json.hpp>

// define a byte container based on std::vector
using byte_container_with_subtype = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>;

int main()
{
    std::vector<std::uint8_t> bytes = {{0xca, 0xfe, 0xba, 0xbe}};

    // create container
    auto c1 = byte_container_with_subtype(bytes);

    // create container with subtype
    auto c2 = byte_container_with_subtype(bytes, 42);

    std::cout << std::boolalpha << "c1.has_subtype() = " << c1.has_subtype()
              << "\nc2.has_subtype() = " << c2.has_subtype() << std::endl;
}


import a12 from './a12'
import a13 from './a13'
import a14 from './a14'
import a15 from './a15'
import a16 from './a16'
import a17 from './a17'
import a18 from './a18'
import a19 from './a19'
import a20 from './a20'
import a21 from './a21'
import a22 from './a22'
import a23 from './a23'
import a24 from './a24'

export const that = () => import('./a10.js')

export function other() {
  return (
    a12() +
    a13() +
    a14() +
    a15() +
    a16() +
    a17() +
    a18() +
    a19() +
    a20() +
    a21() +
    a22() +
    a23() +
    a24()
  )
}

export default function () {
  return 123
}


//     __ _____ _____ _____
//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
// |  |  |__   |  |  | | | |  version 3.12.0
// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT

#include "doctest_compatibility.h"

#include <nlohmann/json.hpp>
#include <exception>
#include <iostream>

struct Foo
{
    int a;
    int b;
};

namespace nlohmann
{
template <>
struct adl_serializer<Foo>
{
    static void to_json(json& j, Foo const& f)
    {
        switch (f.b)
        {
            case 0:
                j["a"] = f.a;
                break;
            case 1:
                j[0] = f.a;
                break;
            default:
                j = "test";
        }
        if (f.a == 1)
        {
            throw std::runtime_error("b is invalid");
        }
    }
};
} // namespace nlohmann

TEST_CASE("check_for_mem_leak_on_adl_to_json-1")
{
    try
    {
        const nlohmann::json j = Foo {1, 0};
        std::cout << j.dump() << "\n";
    }
    catch (...) // NOLINT(bugprone-empty-catch)
    {
        // just ignore the exception in this POC
    }
}

TEST_CASE("check_for_mem_leak_on_adl_to_json-2")
{
    try
    {
        const nlohmann::json j = Foo {1, 1};
        std::cout << j.dump() << "\n";
    }
    catch (...) // NOLINT(bugprone-empty-catch)
    {
        // just ignore the exception in this POC
    }
}

TEST_CASE("check_for_mem_leak_on_adl_to_json-2")
{
    try
    {
        const nlohmann::json j = Foo {1, 2};
        std::cout << j.dump() << "\n";
    }
    catch (...) // NOLINT(bugprone-empty-catch)
    {
        // just ignore the exception in this POC
    }
}


//===- FuzzerValueBitMap.h - INTERNAL - Bit map -----------------*- C++ -* ===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// ValueBitMap.
//===----------------------------------------------------------------------===//

#ifndef LLVM_FUZZER_VALUE_BIT_MAP_H
#define LLVM_FUZZER_VALUE_BIT_MAP_H

#include "FuzzerDefs.h"

namespace fuzzer {

// A bit map containing kMapSizeInWords bits.
struct ValueBitMap {
  static const size_t kMapSizeInBits = 65371;        // Prime.
  static const size_t kMapSizeInBitsAligned = 65536; // 2^16
  static const size_t kBitsInWord = (sizeof(uintptr_t) * 8);
  static const size_t kMapSizeInWords = kMapSizeInBitsAligned / kBitsInWord;
 public:
  static const size_t kNumberOfItems = kMapSizeInBits;
  // Clears all bits.
  void Reset() { memset(Map, 0, sizeof(Map)); }

  // Computes a hash function of Value and sets the corresponding bit.
  // Returns true if the bit was changed from 0 to 1.
  inline bool AddValue(uintptr_t Value) {
    uintptr_t Idx = Value < kMapSizeInBits ? Value : Value % kMapSizeInBits;
    uintptr_t WordIdx = Idx / kBitsInWord;
    uintptr_t BitIdx = Idx % kBitsInWord;
    uintptr_t Old = Map[WordIdx];
    uintptr_t New = Old | (1UL << BitIdx);
    Map[WordIdx] = New;
    return New != Old;
  }

  inline bool Get(uintptr_t Idx) {
    assert(Idx < kMapSizeInBits);
    uintptr_t WordIdx = Idx / kBitsInWord;
    uintptr_t BitIdx = Idx % kBitsInWord;
    return Map[WordIdx] & (1UL << BitIdx);
  }

  size_t GetNumBitsSinceLastMerge() const { return NumBits; }

  // Merges 'Other' into 'this', clears 'Other', updates NumBits,
  // returns true if new bits were added.
  ATTRIBUTE_TARGET_POPCNT
  bool MergeFrom(ValueBitMap &Other) {
    uintptr_t Res = 0;
    size_t OldNumBits = NumBits;
    for (size_t i = 0; i < kMapSizeInWords; i++) {
      auto O = Other.Map[i];
      auto M = Map[i];
      if (O) {
        Map[i] = (M |= O);
        Other.Map[i] = 0;
      }
      if (M)
        Res += __builtin_popcountl(M);
    }
    NumBits = Res;
    return OldNumBits < NumBits;
  }

  template <class Callback>
  void ForEach(Callback CB) {
    for (size_t i = 0; i < kMapSizeInWords; i++)
      if (uintptr_t M = Map[i])
        for (size_t j = 0; j < sizeof(M) * 8; j++)
          if (M & ((uintptr_t)1 << j))
            CB(i * sizeof(M) * 8 + j);
  }

 private:
  size_t NumBits = 0;
  uintptr_t Map[kMapSizeInWords] __attribute__((aligned(512)));
};

}  // namespace fuzzer

#endif  // LLVM_FUZZER_VALUE_BIT_MAP_H


# <small>nlohmann::basic_json::</small>to_bson

```cpp
// (1)
static std::vector<std::uint8_t> to_bson(const basic_json& j);

// (2)
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o);
static void to_bson(const basic_json& j, detail::output_adapter<char> o);
```

BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are stored as a single entity (a
so-called document).

1. Returns a byte vector containing the BSON serialization.
2. Writes the BSON serialization to an output adapter.

The exact mapping and its limitations are described on a [dedicated page](../../features/binary_formats/bson.md).

## Parameters

`j` (in)
:   JSON value to serialize

`o` (in)
:   output adapter to write serialization to

## Return value

1. BSON serialization as a byte vector
2. (none)

## Exception safety

Strong guarantee: if an exception is thrown, there are no changes in the JSON value.

## Exceptions

- Throws [`type_error.317`](../../home/exceptions.md#jsonexceptiontype_error317) if the top-level type of the JSON value
  is not an object; example: `"to serialize to BSON, top-level type must be object, but is string"`
- Throws [`out_of_range.409`](../../home/exceptions.md#jsonexceptionout_of_range409) if a key in the JSON object contains
  a null byte (code point U+0000); example: `"BSON key cannot contain code point U+0000 (at byte 2)"`
- Throws [`out_of_range.412`](../../home/exceptions.md#jsonexceptionout_of_range412) if the length of a document, array,
  string, or binary value exceeds the range of the 32-bit BSON length field; example:
  `"BSON length 2147483661 exceeds maximum of 2147483647"`

## Complexity

Linear in the size of the JSON value `j`.

## Examples

??? example

    The example shows the serialization of a JSON value to a byte vector in BSON format.

    ```cpp
    --8<-- "examples/to_bson.cpp"
    ```

    Output:

    ```json
    --8<-- "examples/to_bson.output"
    ```

## See also

- [from_bson](from_bson.md) create a JSON value from an input in BSON format
- [to_cbor](to_cbor.md) create a CBOR serialization of a JSON value
- [to_msgpack](to_msgpack.md) create a MessagePack serialization of a JSON value
- [to_ubjson](to_ubjson.md) create a UBJSON serialization of a JSON value
- [to_bjdata](to_bjdata.md) create a BJData serialization of a JSON value

## Version history

- Added in version 3.4.0.


use serde_derive::Deserialize;

// No errors expected.
#[derive(Deserialize)]
struct T0(u8, u8);

// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
#[derive(Deserialize)]
struct T1(u8, #[serde(default)] u8);

// ERROR: The first field can get default value only if sequence is empty, but
// that means that all other fields cannot be deserialized without errors.
#[derive(Deserialize)]
struct T2(#[serde(default)] u8, u8, u8);

// No errors expected:
// - If both fields are provided, both get value from data.
// - If only one field is provided, the second gets default value.
// - If no fields are provided, both get default value.
#[derive(Deserialize)]
struct T3(#[serde(default)] u8, #[serde(default)] u8);

////////////////////////////////////////////////////////////////////////////////

// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T4(u8, u8);

// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T5(#[serde(default)] u8, u8);

// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T6(u8, #[serde(default)] u8);

// No errors expected -- missing fields get default values.
#[derive(Deserialize, Default)]
#[serde(default)]
struct T7(#[serde(default)] u8, #[serde(default)] u8);

fn main() {}


import a5 from './a5'
import a6 from './a6'
import a7 from './a7'
import a8 from './a8'
import a9 from './a9'
import a10 from './a10'
import a11 from './a11'
import a12 from './a12'
import a13 from './a13'
import a14 from './a14'
import a15 from './a15'
import a16 from './a16'
import a17 from './a17'
import a18 from './a18'
import a19 from './a19'
import a20 from './a20'
import a21 from './a21'
import a22 from './a22'
import a23 from './a23'
import a24 from './a24'

export const that = () => import('./a3.js')

export function other() {
  return (
    a5() +
    a6() +
    a7() +
    a8() +
    a9() +
    a10() +
    a11() +
    a12() +
    a13() +
    a14() +
    a15() +
    a16() +
    a17() +
    a18() +
    a19() +
    a20() +
    a21() +
    a22() +
    a23() +
    a24()
  )
}

export default function () {
  return 123
}


export default {
  isMain: import.meta.main,
  url: import.meta.url,
  dirname: import.meta.dirname,
  filename: import.meta.filename,
  resolved: import.meta.resolve('../import-meta/vite.config.ts'),
  // prettier-ignore
  resolvedMultiline: import.meta
    .resolve('../import-meta/vite.config.ts'),
}