diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5173da859417be..b1c663db40e80f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,8 @@ on: - feat/* - fix/* - perf/* + - v1 + - v2 pull_request: workflow_dispatch: diff --git a/README.md b/README.md index 546014a12c7116..a6f13829f2635f 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ In addition, Vite is highly extensible via its [Plugin API](https://vitejs.dev/g ## Packages +> This branch is for the upcoming v3.0, if you are looking for current stable releases, check the [`v2` branch](https://github.com/vitejs/vite/tree/v2) instead. + | Package | Version (click for changelogs) | | ------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | | [vite](packages/vite) | [![vite version](https://img.shields.io/npm/v/vite.svg?label=%20)](packages/vite/CHANGELOG.md) | diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.ts similarity index 94% rename from docs/.vitepress/config.js rename to docs/.vitepress/config.ts index ee76a29986d3fb..4659ea5ab7ae4f 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.ts @@ -1,9 +1,6 @@ -// @ts-check +import { defineConfig } from 'vitepress' -/** - * @type {import('vitepress').UserConfig} - */ -module.exports = { +export default defineConfig({ title: 'Vite', description: 'Next Generation Frontend Tooling', head: [['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }]], @@ -64,6 +61,15 @@ module.exports = { } ] }, + { + text: 'v3 (next)', + items: [ + { + text: 'v2.x (stable)', + link: 'https://v2.vitejs.dev' + } + ] + }, { text: 'Languages', items: [ @@ -169,4 +175,4 @@ module.exports = { ] } } -} +}) diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 50353765261e34..76b9984a069828 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -305,6 +305,28 @@ Vite plugins can also provide hooks that serve Vite-specific purposes. These hoo Note `configureServer` is not called when running the production build so your other hooks need to guard against its absence. +### `configurePreviewServer` + +- **Type:** `(server: { middlewares: Connect.Server, httpServer: http.Server }) => (() => void) | void | Promise<(() => void) | void>` +- **Kind:** `async`, `sequential` + + Same as [`configureServer`](/guide/api-plugin.html#configureserver) but for the preview server. It provides the [connect](https://github.com/senchalabs/connect) server and its underlying [http server](https://nodejs.org/api/http.html). Similarly to `configureServer`, the `configurePreviewServer` hook is called before other middlewares are installed. If you want to inject a middleware **after** other middlewares, you can return a function from `configurePreviewServer`, which will be called after internal middlewares are installed: + + ```js + const myPlugin = () => ({ + name: 'configure-preview-server', + configurePreviewServer(server) { + // return a post hook that is called after other middlewares are + // installed + return () => { + server.middlewares.use((req, res, next) => { + // custom handle request... + }) + } + } + }) + ``` + ### `transformIndexHtml` - **Type:** `IndexHtmlTransformHook | { enforce?: 'pre' | 'post', transform: IndexHtmlTransformHook }` diff --git a/docs/guide/features.md b/docs/guide/features.md index 1a8c03bbd0be22..01798ad0d4ea56 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -282,10 +282,10 @@ for (const path in modules) { } ``` -Matched files are by default lazy loaded via dynamic import and will be split into separate chunks during build. If you'd rather import all the modules directly (e.g. relying on side-effects in these modules to be applied first), you can use `import.meta.globEager` instead: +Matched files are by default lazy-loaded via dynamic import and will be split into separate chunks during build. If you'd rather import all the modules directly (e.g. relying on side-effects in these modules to be applied first), you can pass `{ eager: true }` as the second argument: ```js -const modules = import.meta.globEager('./dir/*.js') +const modules = import.meta.glob('./dir/*.js', { eager: true }) ``` The above will be transformed into the following: @@ -300,7 +300,9 @@ const modules = { } ``` -`import.meta.glob` and `import.meta.globEager` also support importing files as strings (similar to [Importing Asset as String](https://vitejs.dev/guide/assets.html#importing-asset-as-string)) with the [Import Reflection](https://github.com/tc39/proposal-import-reflection) syntax: +### Glob Import As + +`import.meta.glob` also supports importing files as strings (similar to [Importing Asset as String](https://vitejs.dev/guide/assets.html#importing-asset-as-string)) with the [Import Reflection](https://github.com/tc39/proposal-import-reflection) syntax: ```js const modules = import.meta.glob('./dir/*.js', { as: 'raw' }) @@ -311,18 +313,115 @@ The above will be transformed into the following: ```js // code produced by vite const modules = { - './dir/foo.js': '{\n "msg": "foo"\n}\n', - './dir/bar.js': '{\n "msg": "bar"\n}\n' + './dir/foo.js': 'export default "foo"\n', + './dir/bar.js': 'export default "bar"\n' +} +``` + +`{ as: 'url' }` is also supported for loading assets as URLs. + +### Multiple Patterns + +The first argument can be an array of globs, for example + +```js +const modules = import.meta.glob(['./dir/*.js', './another/*.js']) +``` + +### Negative Patterns + +Negative glob patterns are also supported (prefixed with `!`). To ignore some files from the result, you can add exclude glob patterns to the first argument: + +```js +const modules = import.meta.glob(['./dir/*.js', '!**/bar.js']) +``` + +```js +// code produced by vite +const modules = { + './dir/foo.js': () => import('./dir/foo.js') +} +``` + +#### Named Imports + +It's possible to only import parts of the modules with the `import` options. + +```ts +const modules = import.meta.glob('./dir/*.js', { import: 'setup' }) +``` + +```ts +// code produced by vite +const modules = { + './dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup), + './dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup) +} +``` + +When combined with `eager` it's even possible to have tree-shaking enabled for those modules. + +```ts +const modules = import.meta.glob('./dir/*.js', { import: 'setup', eager: true }) +``` + +```ts +// code produced by vite: +import { setup as __glob__0_0 } from './dir/foo.js' +import { setup as __glob__0_1 } from './dir/bar.js' +const modules = { + './dir/foo.js': __glob__0_0, + './dir/bar.js': __glob__0_1 +} +``` + +Set `import` to `default` to import the default export. + +```ts +const modules = import.meta.glob('./dir/*.js', { + import: 'default', + eager: true +}) +``` + +```ts +// code produced by vite: +import __glob__0_0 from './dir/foo.js' +import __glob__0_1 from './dir/bar.js' +const modules = { + './dir/foo.js': __glob__0_0, + './dir/bar.js': __glob__0_1 +} +``` + +#### Custom Queries + +You can also use the `query` option to provide custom queries to imports for other plugins to consume. + +```ts +const modules = import.meta.glob('./dir/*.js', { + query: { foo: 'bar', bar: true } +}) +``` + +```ts +// code produced by vite: +const modules = { + './dir/foo.js': () => + import('./dir/foo.js?foo=bar&bar=true').then((m) => m.setup), + './dir/bar.js': () => + import('./dir/bar.js?foo=bar&bar=true').then((m) => m.setup) } ``` +### Glob Import Caveats + Note that: - This is a Vite-only feature and is not a web or ES standard. - The glob patterns are treated like import specifiers: they must be either relative (start with `./`) or absolute (start with `/`, resolved relative to project root) or an alias path (see [`resolve.alias` option](/config/#resolve-alias)). -- The glob matching is done via `fast-glob` - check out its documentation for [supported glob patterns](https://github.com/mrmlnc/fast-glob#pattern-syntax). -- You should also be aware that glob imports do not accept variables, you need to directly pass the string pattern. -- The glob patterns cannot contain the same quote string (i.e. `'`, `"`, `` ` ``) as outer quotes, e.g. `'/Tom\'s files/**'`, use `"/Tom's files/**"` instead. +- The glob matching is done via [`fast-glob`](https://github.com/mrmlnc/fast-glob) - check out its documentation for [supported glob patterns](https://github.com/mrmlnc/fast-glob#pattern-syntax). +- You should also be aware that all the arguments in the `import.meta.glob` must be **passed as literals**. You can NOT use variables or expressions in them. ## WebAssembly diff --git a/packages/playground/assets/__tests__/assets.spec.ts b/packages/playground/assets/__tests__/assets.spec.ts index f1075f6fe1cb39..c63ffc7cc1c0c2 100644 --- a/packages/playground/assets/__tests__/assets.spec.ts +++ b/packages/playground/assets/__tests__/assets.spec.ts @@ -145,8 +145,8 @@ describe('css url() references', () => { expect(await getBg('.css-url-quotes-base64-inline')).toMatch(match) const icoMatch = isBuild ? `data:image/x-icon;base64` : `favicon.ico` const el = await page.$(`link.ico`) - const herf = await el.getAttribute('href') - expect(herf).toMatch(icoMatch) + const href = await el.getAttribute('href') + expect(href).toMatch(icoMatch) }) test('multiple urls on the same line', async () => { diff --git a/packages/playground/css/main.js b/packages/playground/css/main.js index f728b0251066d1..90f74c96793c55 100644 --- a/packages/playground/css/main.js +++ b/packages/playground/css/main.js @@ -80,12 +80,14 @@ text('.inlined-code', inlined) // glob const glob = import.meta.glob('./glob-import/*.css') -Promise.all(Object.keys(glob).map((key) => glob[key]())).then((res) => { +Promise.all( + Object.keys(glob).map((key) => glob[key]().then((i) => i.default)) +).then((res) => { text('.imported-css-glob', JSON.stringify(res, null, 2)) }) // globEager -const globEager = import.meta.globEager('./glob-import/*.css') +const globEager = import.meta.glob('./glob-import/*.css', { eager: true }) text('.imported-css-globEager', JSON.stringify(globEager, null, 2)) import postcssSourceInput from './postcss-source-input.css?query=foo' diff --git a/packages/playground/glob-import/__tests__/glob-import.spec.ts b/packages/playground/glob-import/__tests__/glob-import.spec.ts index ebdf6c0ab29193..d738ccec1d4c97 100644 --- a/packages/playground/glob-import/__tests__/glob-import.spec.ts +++ b/packages/playground/glob-import/__tests__/glob-import.spec.ts @@ -42,7 +42,7 @@ const allResult = { }, '/dir/index.js': { globWithAlias: { - './alias.js': { + '/dir/alias.js': { default: 'hi' } }, @@ -67,7 +67,7 @@ const rawResult = { } const relativeRawResult = { - '../glob-import/dir/baz.json': { + './dir/baz.json': { msg: 'baz' } } diff --git a/packages/playground/glob-import/dir/index.js b/packages/playground/glob-import/dir/index.js index fb87f69f0f3a61..ab298abed485b3 100644 --- a/packages/playground/glob-import/dir/index.js +++ b/packages/playground/glob-import/dir/index.js @@ -1,4 +1,4 @@ -const modules = import.meta.globEager('./*.(js|ts)') -const globWithAlias = import.meta.globEager('@dir/al*.js') +const modules = import.meta.glob('./*.(js|ts)', { eager: true }) +const globWithAlias = import.meta.glob('@dir/al*.js', { eager: true }) export { modules, globWithAlias } diff --git a/packages/playground/glob-import/dir/nested/bar.js b/packages/playground/glob-import/dir/nested/bar.js index a2d2921cca80ad..bb23a5a141de8e 100644 --- a/packages/playground/glob-import/dir/nested/bar.js +++ b/packages/playground/glob-import/dir/nested/bar.js @@ -1,4 +1,4 @@ -const modules = import.meta.globEager('../*.json') +const modules = import.meta.glob('../*.json', { eager: true }) export const msg = 'bar' export { modules } diff --git a/packages/playground/glob-import/index.html b/packages/playground/glob-import/index.html index 64f456aeb4d6a2..8466a6d0495881 100644 --- a/packages/playground/glob-import/index.html +++ b/packages/playground/glob-import/index.html @@ -40,8 +40,9 @@