diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 961fe199582d87..629aedd122aae4 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -73,6 +73,10 @@ module.exports = defineConfig({ '@typescript-eslint/ban-ts-comment': 'off', // TODO: we should turn this on in a new PR '@typescript-eslint/ban-types': 'off', // TODO: we should turn this on in a new PR + '@typescript-eslint/explicit-module-boundary-types': [ + 'error', + { allowArgumentsExplicitlyTypedAsAny: true } + ], '@typescript-eslint/no-empty-function': [ 'error', { allow: ['arrowFunctions'] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 013794932f334c..248bb3fbedd101 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@v3 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v2.2.2 - name: Set node version to ${{ matrix.node_version }} uses: actions/setup-node@v3 @@ -87,7 +87,7 @@ jobs: fetch-depth: 0 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v2.2.2 - name: Set node version to 16 uses: actions/setup-node@v3 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cc91df0ed32f7c..5b26ca1a4697ce 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,7 +18,7 @@ jobs: uses: actions/checkout@v3 - name: Install pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v2.2.2 - name: Set node version to 16.x uses: actions/setup-node@v3 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4fdc71fe42f0f0..71a4aa09841ebe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -214,6 +214,8 @@ Vite aims to be fully usable as a dependency in a TypeScript project (e.g. it sh To get around this, we inline some of these dependencies' types in `packages/vite/types`. This way we can still expose the typing but bundle the dependency's source code. +Use `pnpm run check-dist-types` to check bundled types does not rely on types in `devDependencies`. If you are adding `dependencies`, make sure to configure `tsconfig.check.json`. + ### Think before adding yet another option We already have many config options, and we should avoid fixing an issue by adding yet another one. Before adding an option, try to think about: diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 8f0bdb8ef613f1..1a729dc3237553 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -35,7 +35,7 @@ export default defineConfig({ }, carbonAds: { - carbon: 'CEBIEK3N', + code: 'CEBIEK3N', placement: 'vitejsdev' }, @@ -53,9 +53,9 @@ export default defineConfig({ }, nav: [ - { text: 'Guide', link: '/guide/' }, - { text: 'Config', link: '/config/' }, - { text: 'Plugins', link: '/plugins/' }, + { text: 'Guide', link: '/guide/', activeMatch: '/guide/' }, + { text: 'Config', link: '/config/', activeMatch: '/config/' }, + { text: 'Plugins', link: '/plugins/', activeMatch: '/plugins/' }, { text: 'Links', items: [ diff --git a/docs/.vitepress/theme/components/AsideSponsors.vue b/docs/.vitepress/theme/components/AsideSponsors.vue new file mode 100644 index 00000000000000..9c90fcca3750a6 --- /dev/null +++ b/docs/.vitepress/theme/components/AsideSponsors.vue @@ -0,0 +1,22 @@ + + + diff --git a/docs/.vitepress/theme/components/HomeSponsors.vue b/docs/.vitepress/theme/components/HomeSponsors.vue index 5eec6e1d8cd5cb..16ea073b423820 100644 --- a/docs/.vitepress/theme/components/HomeSponsors.vue +++ b/docs/.vitepress/theme/components/HomeSponsors.vue @@ -9,6 +9,7 @@ const { data } = useSponsor() diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index ec9259a0ee08a5..3b4d7e38df76ab 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,14 +1,15 @@ import { h } from 'vue' import Theme from 'vitepress/theme' import './styles/vars.css' -import './styles/custom.css' import HomeSponsors from './components/HomeSponsors.vue' +import AsideSponsors from './components/AsideSponsors.vue' export default { ...Theme, Layout() { return h(Theme.Layout, null, { - 'home-features-after': () => h(HomeSponsors) + 'home-features-after': () => h(HomeSponsors), + 'aside-ads-before': () => h(AsideSponsors) }) } } diff --git a/docs/.vitepress/theme/styles/custom.css b/docs/.vitepress/theme/styles/custom.css deleted file mode 100644 index 69671d732acc5c..00000000000000 --- a/docs/.vitepress/theme/styles/custom.css +++ /dev/null @@ -1,15 +0,0 @@ -@media (min-width: 640px) { - .VPHero .text { - max-width: 592px; - } - - .VPHero .tagline { - max-width: 440px; - } -} - -@media (min-width: 960px) { - .VPHero .tagline { - max-width: 480px; - } -} diff --git a/docs/.vitepress/theme/styles/vars.css b/docs/.vitepress/theme/styles/vars.css index 938bf984656ec3..feacdfcd2dfd4d 100644 --- a/docs/.vitepress/theme/styles/vars.css +++ b/docs/.vitepress/theme/styles/vars.css @@ -38,6 +38,25 @@ #bd34fe 30%, #41d1ff ); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + #bd34fe 50%, + #47caff 50% + ); + --vp-home-hero-image-filter: blur(40px); +} + +@media (min-width: 640px) { + :root { + --vp-home-hero-image-filter: blur(56px); + } +} + +@media (min-width: 960px) { + :root { + --vp-home-hero-image-filter: blur(72px); + } } /** diff --git a/docs/guide/env-and-mode.md b/docs/guide/env-and-mode.md index a0b5400182fe4e..4b37e5549fcd11 100644 --- a/docs/guide/env-and-mode.md +++ b/docs/guide/env-and-mode.md @@ -16,7 +16,7 @@ Vite exposes env variables on the special **`import.meta.env`** object. Some bui During production, these env variables are **statically replaced**. It is therefore necessary to always reference them using the full static string. For example, dynamic key access like `import.meta.env[key]` will not work. -It will also replace these strings appearing in JavaScript strings and Vue templates. This should be a rare case, but it can be unintended. You may see errors like `Missing Semicolon` or `Unexpected token` in this case, for example when `"process.env.NODE_ENV: "` is transformed to `""development": "`. There are ways to work around this behavior: +It will also replace these strings appearing in JavaScript strings and Vue templates. This should be a rare case, but it can be unintended. You may see errors like `Missing Semicolon` or `Unexpected token` in this case, for example when `"process.env.``NODE_ENV"` is transformed to `""development": "`. There are ways to work around this behavior: - For JavaScript strings, you can break the string up with a Unicode zero-width space, e.g. `'import.meta\u200b.env.MODE'`. diff --git a/docs/guide/index.md b/docs/guide/index.md index ab45ceb7f85475..d5d20d80094b1e 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -116,7 +116,7 @@ Running `vite` starts the dev server using the current working directory as root In a project where Vite is installed, you can use the `vite` binary in your npm scripts, or run it directly with `npx vite`. Here are the default npm scripts in a scaffolded Vite project: -```json5 +```json { "scripts": { "dev": "vite", // start dev server, aliases: `vite dev`, `vite serve` diff --git a/docs/index.md b/docs/index.md index 05a85262022650..40e6df844db31a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,10 +1,16 @@ --- layout: home +title: Vite +titleTemplate: Next Generation Frontend Tooling + hero: name: Vite text: Next Generation Frontend Tooling tagline: Get ready for a development environment that can finally catch up with you. + image: + src: /logo-with-shadow.png + alt: Vite actions: - theme: brand text: Get Started diff --git a/docs/public/logo-with-shadow.png b/docs/public/logo-with-shadow.png new file mode 100644 index 00000000000000..8b23c919ed7b9c Binary files /dev/null and b/docs/public/logo-with-shadow.png differ diff --git a/package.json b/package.json index 6dde8708780745..5811ce3f6f519d 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "scripts": { "preinstall": "npx only-allow pnpm", "format": "prettier --write .", - "lint": "eslint packages/*/{src,types}/** playground/**/__tests__/**/*.ts scripts/**", + "lint": "eslint packages/*/{src,types,__tests__}/** playground/**/__tests__/**/*.ts scripts/**", "typecheck": "tsc -p scripts --noEmit && tsc -p playground --noEmit", "test": "run-s test-unit test-serve test-build", "test-serve": "vitest run -c vitest.config.e2e.ts", @@ -88,7 +88,7 @@ "typescript": "^4.6.4", "unbuild": "^0.7.4", "vite": "workspace:*", - "vitepress": "1.0.0-draft.4", + "vitepress": "1.0.0-draft.8", "vitest": "^0.12.9", "vue": "^3.2.35" }, diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index fbfb606f486885..d9b6bafdefa306 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -1,9 +1,8 @@ -/* eslint-disable node/no-extraneous-import */ +import { join } from 'path' import type { ExecaSyncReturnValue, SyncOptions } from 'execa' import { commandSync } from 'execa' import { mkdirpSync, readdirSync, remove, writeFileSync } from 'fs-extra' -import { join } from 'path' -import { test, expect, beforeAll, afterEach } from 'vitest' +import { afterEach, beforeAll, expect, test } from 'vitest' const CLI_PATH = join(__dirname, '..') diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts index ed2c4a24820a61..3a9fb253d4658a 100644 --- a/packages/plugin-legacy/src/index.ts +++ b/packages/plugin-legacy/src/index.ts @@ -517,7 +517,7 @@ export async function detectPolyfills( code: string, targets: any, list: Set -) { +): Promise { const babel = await loadBabel() const { ast } = babel.transform(code, { ast: true, diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md index 3a7c2d42f24eaa..c8bea7c58ca913 100644 --- a/packages/vite/CHANGELOG.md +++ b/packages/vite/CHANGELOG.md @@ -1,3 +1,19 @@ +## 3.0.0-alpha.7 (2022-05-27) + +* fix: preserve annotations during build deps optimization (#8358) ([334cd9f](https://github.com/vitejs/vite/commit/334cd9f)), closes [#8358](https://github.com/vitejs/vite/issues/8358) +* refactor: `ExportData.imports` to `ExportData.hasImports` (#8355) ([168de2d](https://github.com/vitejs/vite/commit/168de2d)), closes [#8355](https://github.com/vitejs/vite/issues/8355) + + + +## 3.0.0-alpha.6 (2022-05-27) + +* fix: missing types for `es-module-lexer` (fixes #8349) (#8352) ([df2cc3d](https://github.com/vitejs/vite/commit/df2cc3d)), closes [#8349](https://github.com/vitejs/vite/issues/8349) [#8352](https://github.com/vitejs/vite/issues/8352) +* fix(optimizer): transpile before calling `transformGlobImport` (#8343) ([1dbc7cc](https://github.com/vitejs/vite/commit/1dbc7cc)), closes [#8343](https://github.com/vitejs/vite/issues/8343) +* feat: scan free dev server (#8319) ([3f742b6](https://github.com/vitejs/vite/commit/3f742b6)), closes [#8319](https://github.com/vitejs/vite/issues/8319) +* chore: remove unused dts from dist (#8346) ([de9f556](https://github.com/vitejs/vite/commit/de9f556)), closes [#8346](https://github.com/vitejs/vite/issues/8346) + + + ## 3.0.0-alpha.5 (2022-05-26) * feat: non-blocking esbuild optimization at build time (#8280) ([909cf9c](https://github.com/vitejs/vite/commit/909cf9c)), closes [#8280](https://github.com/vitejs/vite/issues/8280) diff --git a/packages/vite/package.json b/packages/vite/package.json index 5db998d0c295dd..1d3460d58dd3dd 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "vite", - "version": "3.0.0-alpha.5", + "version": "3.0.0-alpha.7", "type": "module", "license": "MIT", "author": "Evan You", @@ -49,10 +49,11 @@ "dev": "rimraf dist && pnpm run build-bundle -w", "build": "rimraf dist && run-s build-bundle build-types", "build-bundle": "rollup --config rollup.config.ts --configPlugin typescript", - "build-types": "run-s build-temp-types patch-types roll-types", + "build-types": "run-s build-temp-types patch-types roll-types check-dist-types", "build-temp-types": "tsc --emitDeclarationOnly --outDir temp/node -p src/node", "patch-types": "esno scripts/patchTypes.ts", "roll-types": "api-extractor run && rimraf temp", + "check-dist-types": "tsc --project tsconfig.check.json", "lint": "eslint --ext .ts src/**", "format": "prettier --write --parser typescript \"src/**/*.ts\"", "prepublishOnly": "npm run build" diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index b178ba9825d4b2..d80f5a60583abc 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -871,7 +871,7 @@ async function loadConfigFromBundledFile( return config } -export function isDepsOptimizerEnabled(config: ResolvedConfig) { +export function isDepsOptimizerEnabled(config: ResolvedConfig): boolean { const { command, optimizeDeps } = config const { disabled } = optimizeDeps return !( diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index 4bf5c8b1c2152b..0c32af75219438 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -171,20 +171,15 @@ export function esbuildDepPlugin( } let contents = '' - const data = exportsData[id] - const [imports, exports] = data - if (!imports.length && !exports.length) { + const { hasImports, exports, hasReExports } = exportsData[id] + if (!hasImports && !exports.length) { // cjs contents += `export default require("${relativePath}");` } else { if (exports.includes('default')) { contents += `import d from "${relativePath}";export default d;` } - if ( - data.hasReExports || - exports.length > 1 || - exports[0] !== 'default' - ) { + if (hasReExports || exports.length > 1 || exports[0] !== 'default') { contents += `\nexport * from "${relativePath}"` } } diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 3cece89d1d7676..4f4231354e0a6a 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -31,12 +31,15 @@ const isDebugEnabled = _debug('vite:deps').enabled const jsExtensionRE = /\.js$/i const jsMapExtensionRE = /\.js\.map$/i -export type ExportsData = ReturnType & { +export type ExportsData = { + hasImports: boolean + exports: readonly string[] + facade: boolean // es-module-lexer has a facade detection but isn't always accurate for our // use case when the module has default export - hasReExports?: true + hasReExports?: boolean // hint if the dep requires loading as jsx - jsxLoader?: true + jsxLoader?: boolean } export interface DepsOptimizer { @@ -62,6 +65,13 @@ export interface DepOptimizationOptions { * vite project root. This will overwrite default entries inference. */ entries?: string | string[] + /** + * Enable esbuild based scan phase, to get back to the optimized deps discovery + * strategy used in Vite v2 + * @default false + * @experimental + */ + devScan?: boolean /** * Force optimize listed dependencies (must be resolvable import paths, * cannot be globs). @@ -475,7 +485,7 @@ export async function runOptimizeDeps( splitting: true, sourcemap: true, outdir: processingCacheDir, - ignoreAnnotations: true, + ignoreAnnotations: resolvedConfig.command !== 'build', metafile: true, define, plugins: [ @@ -585,19 +595,22 @@ export function newDepOptimizationProcessing(): DepOptimizationProcessing { // Convert to { id: src } export function depsFromOptimizedDepInfo( depsInfo: Record -) { +): Record { return Object.fromEntries( Object.entries(depsInfo).map((d) => [d[0], d[1].src!]) ) } -export function getOptimizedDepPath(id: string, config: ResolvedConfig) { +export function getOptimizedDepPath( + id: string, + config: ResolvedConfig +): string { return normalizePath( path.resolve(getDepsCacheDir(config), flattenId(id) + '.js') ) } -export function getDepsCacheDir(config: ResolvedConfig) { +export function getDepsCacheDir(config: ResolvedConfig): string { const dirName = config.command === 'build' ? 'depsBuild' : 'deps' return normalizePath(path.resolve(config.cacheDir, dirName)) } @@ -607,11 +620,16 @@ function getProcessingDepsCacheDir(config: ResolvedConfig) { return normalizePath(path.resolve(config.cacheDir, dirName)) } -export function isOptimizedDepFile(id: string, config: ResolvedConfig) { +export function isOptimizedDepFile( + id: string, + config: ResolvedConfig +): boolean { return id.startsWith(getDepsCacheDir(config)) } -export function createIsOptimizedDepUrl(config: ResolvedConfig) { +export function createIsOptimizedDepUrl( + config: ResolvedConfig +): (url: string) => boolean { const { root } = config const depsCacheDir = getDepsCacheDir(config) @@ -740,7 +758,6 @@ export async function extractExportsData( config: ResolvedConfig ): Promise { await init - let exportsData: ExportsData const esbuildOptions = config.optimizeDeps?.esbuildOptions ?? {} if (config.optimizeDeps.extensions?.some((ext) => filePath.endsWith(ext))) { @@ -753,34 +770,48 @@ export async function extractExportsData( write: false, format: 'esm' }) - exportsData = parse(result.outputFiles[0].text) as ExportsData - } else { - const entryContent = fs.readFileSync(filePath, 'utf-8') - try { - exportsData = parse(entryContent) as ExportsData - } catch { - const loader = esbuildOptions.loader?.[path.extname(filePath)] || 'jsx' - debug( - `Unable to parse: ${filePath}.\n Trying again with a ${loader} transform.` - ) - const transformed = await transformWithEsbuild(entryContent, filePath, { - loader - }) - // Ensure that optimization won't fail by defaulting '.js' to the JSX parser. - // This is useful for packages such as Gatsby. - esbuildOptions.loader = { - '.js': 'jsx', - ...esbuildOptions.loader - } - exportsData = parse(transformed.code) as ExportsData - exportsData.jsxLoader = true + const [imports, exports, facade] = parse(result.outputFiles[0].text) + return { + hasImports: imports.length > 0, + exports, + facade } - for (const { ss, se } of exportsData[0]) { - const exp = entryContent.slice(ss, se) - if (/export\s+\*\s+from/.test(exp)) { - exportsData.hasReExports = true - } + } + + let parseResult: ReturnType + let usedJsxLoader = false + + const entryContent = fs.readFileSync(filePath, 'utf-8') + try { + parseResult = parse(entryContent) + } catch { + const loader = esbuildOptions.loader?.[path.extname(filePath)] || 'jsx' + debug( + `Unable to parse: ${filePath}.\n Trying again with a ${loader} transform.` + ) + const transformed = await transformWithEsbuild(entryContent, filePath, { + loader + }) + // Ensure that optimization won't fail by defaulting '.js' to the JSX parser. + // This is useful for packages such as Gatsby. + esbuildOptions.loader = { + '.js': 'jsx', + ...esbuildOptions.loader } + parseResult = parse(transformed.code) + usedJsxLoader = true + } + + const [imports, exports, facade] = parseResult + const exportsData: ExportsData = { + hasImports: imports.length > 0, + exports, + facade, + hasReExports: imports.some(({ ss, se }) => { + const exp = entryContent.slice(ss, se) + return /export\s+\*\s+from/.test(exp) + }), + jsxLoader: usedJsxLoader } return exportsData } @@ -802,9 +833,9 @@ function needsInterop( ) { return true } - const [imports, exports] = exportsData + const { hasImports, exports } = exportsData // entry has no ESM syntax - likely CJS or UMD - if (!exports.length && !imports.length) { + if (!exports.length && !hasImports) { return true } diff --git a/packages/vite/src/node/optimizer/optimizer.ts b/packages/vite/src/node/optimizer/optimizer.ts index ed950264684663..d1846903d95269 100644 --- a/packages/vite/src/node/optimizer/optimizer.ts +++ b/packages/vite/src/node/optimizer/optimizer.ts @@ -34,7 +34,9 @@ const debounceMs = 100 const depsOptimizerMap = new WeakMap() -export function getDepsOptimizer(config: ResolvedConfig) { +export function getDepsOptimizer( + config: ResolvedConfig +): DepsOptimizer | undefined { // Workers compilation shares the DepsOptimizer from the main build return depsOptimizerMap.get(config.mainConfig || config) } @@ -46,6 +48,8 @@ export async function initDepsOptimizer( const { logger } = config const isBuild = config.command === 'build' + const scan = config.command !== 'build' && config.optimizeDeps.devScan + const sessionTimestamp = Date.now().toString() const cachedMetadata = loadCachedDepOptimizationMetadata(config) @@ -100,7 +104,7 @@ export async function initDepsOptimizer( // If there wasn't a cache or it is outdated, we need to prepare a first run let firstRunCalled = !!cachedMetadata if (!cachedMetadata) { - if (isBuild) { + if (!scan) { // Initialize discovered deps with manually added optimizeDeps.include info const discovered = await initialProjectDependencies( config, @@ -460,9 +464,14 @@ export async function initDepsOptimizer( exportsData: extractExportsData(resolved, config) }) - // Debounced rerun, let other missing dependencies be discovered before - // the running next optimizeDeps - if (!isBuild) { + // Until the first optimize run is called, avoid triggering processing + // We'll wait until the user codebase is eagerly processed by Vite so + // we can get a list of every missing dependency before giving to the + // browser a dependency that may be outdated, thus avoiding full page reloads + + if (scan || firstRunCalled) { + // Debounced rerun, let other missing dependencies be discovered before + // the running next optimizeDeps debouncedProcessing() } diff --git a/packages/vite/src/node/optimizer/scan.ts b/packages/vite/src/node/optimizer/scan.ts index 6f609991ecc7fb..63d2d265e10e27 100644 --- a/packages/vite/src/node/optimizer/scan.ts +++ b/packages/vite/src/node/optimizer/scan.ts @@ -3,7 +3,7 @@ import path from 'path' import { performance } from 'perf_hooks' import glob from 'fast-glob' import type { Loader, OnLoadResult, Plugin } from 'esbuild' -import { build } from 'esbuild' +import { build, transform } from 'esbuild' import colors from 'picocolors' import type { ResolvedConfig } from '..' import { @@ -299,17 +299,26 @@ function esbuildScanPlugin( const key = `${path}?id=${scriptId++}` if (contents.includes('import.meta.glob')) { + let transpiledContents + // transpile because `transformGlobImport` only expects js + if (loader !== 'js') { + transpiledContents = (await transform(contents, { loader })) + .code + } else { + transpiledContents = contents + } + scripts[key] = { - loader: 'js', + loader: 'js', // since it is transpiled contents: ( await transformGlobImport( - contents, + transpiledContents, path, config.root, resolve ) - )?.s.toString() || contents + )?.s.toString() || transpiledContents } } else { scripts[key] = { diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 45ff0525b1042d..a8112d48658091 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1197,7 +1197,7 @@ async function minifyCSS(css: string, config: ResolvedConfig) { } } -export async function hoistAtRules(css: string) { +export async function hoistAtRules(css: string): Promise { const s = new MagicString(css) const cleanCss = emptyCssComments(css) let match: RegExpExecArray | null diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index 93da02147ae854..5d2fce4ad13e02 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -52,7 +52,10 @@ import { optimizedDepNeedsInterop } from '../optimizer' import { checkPublicFile } from './asset' -import { ERR_OUTDATED_OPTIMIZED_DEP } from './optimizedDeps' +import { + ERR_OUTDATED_OPTIMIZED_DEP, + delayDepsOptimizerUntil +} from './optimizedDeps' import { isCSSRequest, isDirectCSSRequest } from './css' const isDebug = !!process.env.DEBUG @@ -61,7 +64,7 @@ const debug = createDebugger('vite:import-analysis') const clientDir = normalizePath(CLIENT_DIR) const skipRE = /\.(map|json)$/ -export const canSkipImportAnalysis = (id: string) => +export const canSkipImportAnalysis = (id: string): boolean => skipRE.test(id) || isDirectCSSRequest(id) const optimizedDepChunkRE = /\/chunk-[A-Z0-9]{8}\.js/ @@ -186,7 +189,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { let s: MagicString | undefined const str = () => s || (s = new MagicString(source)) const importedUrls = new Set() - const staticImportedUrls = new Set() + const staticImportedUrls = new Set<{ url: string; id: string }>() const acceptedUrls = new Set<{ url: string start: number @@ -466,7 +469,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { importedUrls.add(urlWithoutBase) if (!isDynamicImport) { // for pre-transforming - staticImportedUrls.add(urlWithoutBase) + staticImportedUrls.add({ url: urlWithoutBase, id: resolvedId }) } } else if (!importer.startsWith(clientDir) && !ssr) { // check @vite-ignore which suppresses dynamic import warning @@ -605,13 +608,14 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) // pre-transform known direct imports + // TODO: we should also crawl dynamic imports if (config.server.preTransformRequests && staticImportedUrls.size) { - staticImportedUrls.forEach((url) => { + staticImportedUrls.forEach(({ url, id }) => { url = unwrapId(removeImportQuery(url)).replace( NULL_BYTE_PLACEHOLDER, '\0' ) - transformRequest(url, server, { ssr }).catch((e) => { + const request = transformRequest(url, server, { ssr }).catch((e) => { if (e?.code === ERR_OUTDATED_OPTIMIZED_DEP) { // This are expected errors return @@ -619,6 +623,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { // Unexpected error, log the issue but avoid an unhandled exception config.logger.error(e.message) }) + if (!config.optimizeDeps.devScan) { + delayDepsOptimizerUntil(config, id, () => request) + } }) } diff --git a/packages/vite/src/node/plugins/importMetaGlob.ts b/packages/vite/src/node/plugins/importMetaGlob.ts index b624d7e609bcb1..4a6c97e09150eb 100644 --- a/packages/vite/src/node/plugins/importMetaGlob.ts +++ b/packages/vite/src/node/plugins/importMetaGlob.ts @@ -33,7 +33,10 @@ export interface ParsedImportGlob { end: number } -export function getAffectedGlobModules(file: string, server: ViteDevServer) { +export function getAffectedGlobModules( + file: string, + server: ViteDevServer +): ModuleNode[] { const modules: ModuleNode[] = [] for (const [id, allGlobs] of server._importGlobMap!) { if (allGlobs.some((glob) => isMatch(file, glob))) @@ -501,7 +504,7 @@ export function getCommonBase(globsResolved: string[]): null | string { return commonAncestor } -export function isVirtualModule(id: string) { +export function isVirtualModule(id: string): boolean { // https://vitejs.dev/guide/api-plugin.html#virtual-modules-convention return id.startsWith('virtual:') || id.startsWith('\0') || !id.includes('/') } diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index db206ef7e319e1..49bcc69bf6f25e 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -16,7 +16,7 @@ const debug = createDebugger('vite:optimize-deps') const runOptimizerIfIdleAfterMs = 100 interface RunProcessingInfo { - ids: { id: string; done: () => Promise }[] + ids: { id: string; done: () => Promise }[] seenIds: Set workersSources: Set waitingOn: string | undefined @@ -43,7 +43,10 @@ function getRunProcessingInfo(config: ResolvedConfig): RunProcessingInfo { ) } -export function registerWorkersSource(config: ResolvedConfig, id: string) { +export function registerWorkersSource( + config: ResolvedConfig, + id: string +): void { const info = getRunProcessingInfo(config) info.workersSources.add(id) if (info.waitingOn === id) { @@ -51,11 +54,11 @@ export function registerWorkersSource(config: ResolvedConfig, id: string) { } } -function delayDepsOptimizerUntil( +export function delayDepsOptimizerUntil( config: ResolvedConfig, id: string, - done: () => Promise -) { + done: () => Promise +): void { const info = getRunProcessingInfo(config) if ( !getDepsOptimizer(config)?.isOptimizedDepFile(id) && @@ -98,6 +101,22 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin { return { name: 'vite:optimized-deps', + buildStart() { + if (!config.isWorker) { + initRunProcessingInfo(config) + } + }, + + async resolveId(id) { + if (getDepsOptimizer(config)?.isOptimizedDepFile(id)) { + return id + } + }, + + // this.load({ id }) isn't implemented in PluginContainer + // The logic to register an id to wait until it is processed + // is in importAnalysis, see call to delayDepsOptimizerUntil + async load(id) { const depsOptimizer = getDepsOptimizer(config) if (depsOptimizer?.isOptimizedDepFile(id)) { diff --git a/packages/vite/src/node/plugins/splitVendorChunk.ts b/packages/vite/src/node/plugins/splitVendorChunk.ts index 1ce53eaeb5a259..bc319b01586dab 100644 --- a/packages/vite/src/node/plugins/splitVendorChunk.ts +++ b/packages/vite/src/node/plugins/splitVendorChunk.ts @@ -27,7 +27,7 @@ export class SplitVendorChunkCache { constructor() { this.cache = new Map() } - reset() { + reset(): void { this.cache = new Map() } } diff --git a/packages/vite/src/node/server/hmr.ts b/packages/vite/src/node/server/hmr.ts index 23ed627a79f3e6..5a0616dbb643e7 100644 --- a/packages/vite/src/node/server/hmr.ts +++ b/packages/vite/src/node/server/hmr.ts @@ -34,14 +34,14 @@ export interface HmrContext { server: ViteDevServer } -export function getShortName(file: string, root: string) { +export function getShortName(file: string, root: string): string { return file.startsWith(root + '/') ? path.posix.relative(root, file) : file } export async function handleHMRUpdate( file: string, server: ViteDevServer -): Promise { +): Promise { const { ws, config, moduleGraph } = server const shortFile = getShortName(file, config.root) const fileName = path.basename(file) @@ -130,7 +130,7 @@ export function updateModules( modules: ModuleNode[], timestamp: number, { config, ws }: ViteDevServer -) { +): void { const updates: Update[] = [] const invalidatedModules = new Set() let needFullReload = false @@ -425,7 +425,7 @@ export function lexAcceptedHmrDeps( function error(pos: number) { const err = new Error( - `import.meta.accept() can only accept string literals or an ` + + `import.meta.hot.accept() can only accept string literals or an ` + `Array of string literals.` ) as RollupError err.pos = pos diff --git a/packages/vite/src/node/server/sourcemap.ts b/packages/vite/src/node/server/sourcemap.ts index 97ee26668d741c..d38c992f7155a2 100644 --- a/packages/vite/src/node/server/sourcemap.ts +++ b/packages/vite/src/node/server/sourcemap.ts @@ -59,7 +59,7 @@ export async function injectSourcesContent( } } -export function genSourceMapUrl(map: SourceMap | string | undefined) { +export function genSourceMapUrl(map: SourceMap | string | undefined): string { if (typeof map !== 'string') { map = JSON.stringify(map) } @@ -70,7 +70,7 @@ export function getCodeWithSourcemap( type: 'js' | 'css', code: string, map: SourceMap | null -) { +): string { if (isDebug) { code += `\n/*${JSON.stringify(map, null, 2).replace(/\*\//g, '*\\/')}*/\n` } diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index c6be41bd990e01..512ec038a21244 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -20,7 +20,7 @@ const debug = createDebugger('vite:ssr-external') /** * Converts "parent > child" syntax to just "child" */ -export function stripNesting(packages: string[]) { +export function stripNesting(packages: string[]): string[] { return packages.map((s) => { const arr = s.split('>') return arr[arr.length - 1].trim() diff --git a/packages/vite/src/node/ssr/ssrManifestPlugin.ts b/packages/vite/src/node/ssr/ssrManifestPlugin.ts index 993fae1632ed5d..8bb9a8bcff75dc 100644 --- a/packages/vite/src/node/ssr/ssrManifestPlugin.ts +++ b/packages/vite/src/node/ssr/ssrManifestPlugin.ts @@ -59,7 +59,7 @@ export function ssrManifestPlugin(config: ResolvedConfig): Plugin { const chunk = bundle[filename] as OutputChunk | undefined if (chunk) { chunk.viteMetadata.importedCss.forEach((file) => { - deps.push(`/${file}`) + deps.push(join(config.base, file)) }) chunk.imports.forEach(addDeps) } diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 258551b838f271..db331894bb78fb 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -234,10 +234,10 @@ export const isJSRequest = (url: string): boolean => { const knownTsRE = /\.(ts|mts|cts|tsx)$/ const knownTsOutputRE = /\.(js|mjs|cjs|jsx)$/ -export const isTsRequest = (url: string) => knownTsRE.test(url) -export const isPossibleTsOutput = (url: string) => +export const isTsRequest = (url: string): boolean => knownTsRE.test(url) +export const isPossibleTsOutput = (url: string): boolean => knownTsOutputRE.test(cleanUrl(url)) -export function getPotentialTsSrcPaths(filePath: string) { +export function getPotentialTsSrcPaths(filePath: string): string[] { const [name, type, query = ''] = filePath.split(/(\.(?:[cm]?js|jsx))(\?.*)?$/) const paths = [name + type.replace('js', 'ts') + query] if (!type.endsWith('x')) { @@ -781,7 +781,7 @@ export function parseRequest(id: string): Record | null { return Object.fromEntries(new URLSearchParams(search)) } -export const blankReplacer = (match: string) => ' '.repeat(match.length) +export const blankReplacer = (match: string): string => ' '.repeat(match.length) export function getHash(text: Buffer | string): string { return createHash('sha256').update(text).digest('hex').substring(0, 8) @@ -856,7 +856,7 @@ function gracefulRemoveDir( }) } -export function emptyCssComments(raw: string) { +export function emptyCssComments(raw: string): string { return raw.replace(multilineCommentsRE, (s) => ' '.repeat(s.length)) } diff --git a/packages/vite/tsconfig.check.json b/packages/vite/tsconfig.check.json new file mode 100644 index 00000000000000..cd8f8d6eeb3f2c --- /dev/null +++ b/packages/vite/tsconfig.check.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "noEmit": true, + "moduleResolution": "classic", + // Only add entries to `paths` when you are adding/updating dependencies (not devDependencies) + // See CONTRIBUTING.md "Ensure type support" for more details + "paths": { + // direct + "rollup": ["./node_modules/rollup/dist/rollup.d.ts"], + // direct + "esbuild": ["./node_modules/esbuild/lib/main.d.ts"], + // direct + "postcss": ["./node_modules/postcss/lib/postcss.d.ts"], + // indirect: postcss depends on it + "source-map-js": ["./node_modules/source-map-js/source-map.d.ts"] + }, + "typeRoots": [] + }, + "include": ["dist/**/*.d.ts"] +} diff --git a/playground/legacy/__tests__/ssr/serve.ts b/playground/legacy/__tests__/ssr/serve.ts index fc0fba377160ac..339b95e690b83a 100644 --- a/playground/legacy/__tests__/ssr/serve.ts +++ b/playground/legacy/__tests__/ssr/serve.ts @@ -5,7 +5,7 @@ import { ports, rootDir } from '~utils' export const port = ports['legacy/ssr'] -export async function serve() { +export async function serve(): Promise<{ close(): Promise }> { const { build } = await import('vite') await build({ root: rootDir, diff --git a/playground/optimize-deps/index.astro b/playground/optimize-deps/index.astro index 95790f5bf3a0d5..4425a8b0f6b1ee 100644 --- a/playground/optimize-deps/index.astro +++ b/playground/optimize-deps/index.astro @@ -1,4 +1,6 @@ diff --git a/playground/ssr-vue/__tests__/serve.ts b/playground/ssr-vue/__tests__/serve.ts index 471929634483e8..2e80107022b625 100644 --- a/playground/ssr-vue/__tests__/serve.ts +++ b/playground/ssr-vue/__tests__/serve.ts @@ -7,12 +7,13 @@ import { hmrPorts, isBuild, ports, rootDir } from '~utils' export const port = ports['ssr-vue'] -export async function serve() { +export async function serve(): Promise { if (isBuild) { // build first const { build } = await import('vite') // client build await build({ + base: '/test/', root: rootDir, logLevel: 'silent', // exceptions are logged by Vitest build: { @@ -24,6 +25,7 @@ export async function serve() { }) // server build await build({ + base: '/test/', root: rootDir, logLevel: 'silent', build: { diff --git a/playground/ssr-vue/__tests__/ssr-vue.spec.ts b/playground/ssr-vue/__tests__/ssr-vue.spec.ts index fced36889da442..a70586a5427df5 100644 --- a/playground/ssr-vue/__tests__/ssr-vue.spec.ts +++ b/playground/ssr-vue/__tests__/ssr-vue.spec.ts @@ -10,20 +10,20 @@ import { untilUpdated } from '~utils' -const url = `http://localhost:${port}` +const url = `http://localhost:${port}/test/` test('vuex can be import succeed by named import', async () => { // wait networkidle for dynamic optimize vuex - await page.goto(url + '/store', { waitUntil: 'networkidle' }) + await page.goto(url + 'store', { waitUntil: 'networkidle' }) expect(await page.textContent('h1')).toMatch('bar') // raw http request - const storeHtml = await (await fetch(url + '/store')).text() + const storeHtml = await (await fetch(url + 'store')).text() expect(storeHtml).toMatch('bar') }) test('/about', async () => { - await page.goto(url + '/about') + await page.goto(url + 'about') expect(await page.textContent('h1')).toMatch('About') // should not have hydration mismatch browserLogs.forEach((msg) => { @@ -31,27 +31,27 @@ test('/about', async () => { }) // fetch sub route - const aboutHtml = await (await fetch(url + '/about')).text() + const aboutHtml = await (await fetch(url + 'about')).text() expect(aboutHtml).toMatch('About') if (isBuild) { // assert correct preload directive generation for async chunks and CSS expect(aboutHtml).not.toMatch( - /link rel="modulepreload".*?href="\/assets\/Home\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/Home\.\w{8}\.js"/ ) expect(aboutHtml).not.toMatch( - /link rel="stylesheet".*?href="\/assets\/Home\.\w{8}\.css"/ + /link rel="stylesheet".*?href="\/test\/assets\/Home\.\w{8}\.css"/ ) expect(aboutHtml).toMatch( - /link rel="modulepreload".*?href="\/assets\/About\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/About\.\w{8}\.js"/ ) expect(aboutHtml).toMatch( - /link rel="stylesheet".*?href="\/assets\/About\.\w{8}\.css"/ + /link rel="stylesheet".*?href="\/test\/assets\/About\.\w{8}\.css"/ ) } }) test('/external', async () => { - await page.goto(url + '/external') + await page.goto(url + 'external') expect(await page.textContent('div')).toMatch( 'Example external component content' ) @@ -61,18 +61,18 @@ test('/external', async () => { }) // fetch sub route - const externalHtml = await (await fetch(url + '/external')).text() + const externalHtml = await (await fetch(url + 'external')).text() expect(externalHtml).toMatch('Example external component content') if (isBuild) { // assert correct preload directive generation for async chunks and CSS expect(externalHtml).not.toMatch( - /link rel="modulepreload".*?href="\/assets\/Home\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/Home\.\w{8}\.js"/ ) expect(externalHtml).not.toMatch( - /link rel="stylesheet".*?href="\/assets\/Home\.\w{8}\.css"/ + /link rel="stylesheet".*?href="\/test\/assets\/Home\.\w{8}\.css"/ ) expect(externalHtml).toMatch( - /link rel="modulepreload".*?href="\/assets\/External\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/External\.\w{8}\.js"/ ) } }) @@ -90,23 +90,23 @@ test('/', async () => { if (isBuild) { // assert correct preload directive generation for async chunks and CSS expect(html).toMatch( - /link rel="modulepreload".*?href="\/assets\/Home\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/Home\.\w{8}\.js"/ ) expect(html).toMatch( - /link rel="stylesheet".*?href="\/assets\/Home\.\w{8}\.css"/ + /link rel="stylesheet".*?href="\/test\/assets\/Home\.\w{8}\.css"/ ) // JSX component preload registration expect(html).toMatch( - /link rel="modulepreload".*?href="\/assets\/Foo\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/Foo\.\w{8}\.js"/ ) expect(html).toMatch( - /link rel="stylesheet".*?href="\/assets\/Foo\.\w{8}\.css"/ + /link rel="stylesheet".*?href="\/test\/assets\/Foo\.\w{8}\.css"/ ) expect(html).not.toMatch( - /link rel="modulepreload".*?href="\/assets\/About\.\w{8}\.js"/ + /link rel="modulepreload".*?href="\/test\/assets\/About\.\w{8}\.js"/ ) expect(html).not.toMatch( - /link rel="stylesheet".*?href="\/assets\/About\.\w{8}\.css"/ + /link rel="stylesheet".*?href="\/test\/assets\/About\.\w{8}\.css"/ ) } }) @@ -132,7 +132,7 @@ test('asset', async () => { }) const img = await page.$('img') expect(await img.getAttribute('src')).toMatch( - isBuild ? /\/assets\/logo\.\w{8}\.png/ : '/src/assets/logo.png' + isBuild ? /\/test\/assets\/logo\.\w{8}\.png/ : '/src/assets/logo.png' ) }) @@ -166,13 +166,13 @@ test('hmr', async () => { test('client navigation', async () => { await page.goto(url) - await untilUpdated(() => page.textContent('a[href="/about"]'), 'About') - await page.click('a[href="/about"]') + await untilUpdated(() => page.textContent('a[href="/test/about"]'), 'About') + await page.click('a[href="/test/about"]') await untilUpdated(() => page.textContent('h1'), 'About') editFile('src/pages/About.vue', (code) => code.replace('About', 'changed')) await untilUpdated(() => page.textContent('h1'), 'changed') - await page.click('a[href="/"]') - await untilUpdated(() => page.textContent('a[href="/"]'), 'Home') + await page.click('a[href="/test/"]') + await untilUpdated(() => page.textContent('a[href="/test/"]'), 'Home') }) test('import.meta.url', async () => { @@ -183,7 +183,8 @@ test('import.meta.url', async () => { test.runIf(isBuild)('dynamic css file should be preloaded', async () => { await page.goto(url) const homeHtml = await (await fetch(url)).text() - const re = /link rel="modulepreload".*?href="\/assets\/(Home\.\w{8}\.js)"/ + const re = + /link rel="modulepreload".*?href="\/test\/assets\/(Home\.\w{8}\.js)"/ const filename = re.exec(homeHtml)[1] const manifest = ( await import( diff --git a/playground/ssr-vue/server.js b/playground/ssr-vue/server.js index fb0fd58554b276..5e4e6718bff7bf 100644 --- a/playground/ssr-vue/server.js +++ b/playground/ssr-vue/server.js @@ -33,6 +33,7 @@ export async function createServer( vite = await ( await import('vite') ).createServer({ + base: '/test/', root, logLevel: isTest ? 'error' : 'info', server: { @@ -53,6 +54,7 @@ export async function createServer( } else { app.use((await import('compression')).default()) app.use( + '/test/', (await import('serve-static')).default(resolve('dist/client'), { index: false }) @@ -61,7 +63,7 @@ export async function createServer( app.use('*', async (req, res) => { try { - const url = req.originalUrl + const url = req.originalUrl.replace('/test/', '/') let template, render if (!isProd) { @@ -94,8 +96,8 @@ export async function createServer( if (!isTest) { createServer().then(({ app }) => - app.listen(5173, () => { - console.log('http://localhost:5173') + app.listen(6173, () => { + console.log('http://localhost:6173') }) ) } diff --git a/playground/ssr-vue/src/router.js b/playground/ssr-vue/src/router.js index 2c4f23f7b07e62..814098102d7899 100644 --- a/playground/ssr-vue/src/router.js +++ b/playground/ssr-vue/src/router.js @@ -20,7 +20,9 @@ export function createRouter() { return _createRouter({ // use appropriate history implementation for server/client // import.meta.env.SSR is injected by Vite. - history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(), + history: import.meta.env.SSR + ? createMemoryHistory('/test/') + : createWebHistory('/test/'), routes }) } diff --git a/playground/ssr-vue/vite.config.js b/playground/ssr-vue/vite.config.js index e9fc4c1e309e0f..d57a11972d449e 100644 --- a/playground/ssr-vue/vite.config.js +++ b/playground/ssr-vue/vite.config.js @@ -7,6 +7,7 @@ const nestedVirtualFile = '@nested-virtual-file' const nestedVirtualId = '\0' + nestedVirtualFile export default defineConfig({ + base: '/test/', plugins: [ vuePlugin(), vueJsx(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b3a949e094db47..4495b294a0b344 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,7 +64,7 @@ importers: typescript: ^4.6.4 unbuild: ^0.7.4 vite: workspace:* - vitepress: 1.0.0-draft.4 + vitepress: 1.0.0-draft.8 vitest: ^0.12.9 vue: ^3.2.35 devDependencies: @@ -122,7 +122,7 @@ importers: typescript: 4.6.4 unbuild: 0.7.4 vite: link:packages/vite - vitepress: 1.0.0-draft.4 + vitepress: 1.0.0-draft.8 vitest: 0.12.9 vue: 3.2.36 @@ -1626,12 +1626,14 @@ packages: /@cspotcode/source-map-consumer/0.8.0: resolution: {integrity: sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==} engines: {node: '>= 12'} + dev: true /@cspotcode/source-map-support/0.7.0: resolution: {integrity: sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==} engines: {node: '>=12'} dependencies: '@cspotcode/source-map-consumer': 0.8.0 + dev: true /@docsearch/css/3.0.0: resolution: {integrity: sha512-1kkV7tkAsiuEd0shunYRByKJe3xQDG2q7wYg24SOw1nV9/2lwEd4WrUYRJC/ukGTl2/kHeFxsaUvtiOy0y6fFA==} @@ -2121,15 +2123,19 @@ packages: /@tsconfig/node10/1.0.8: resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} + dev: true /@tsconfig/node12/1.0.9: resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} + dev: true /@tsconfig/node14/1.0.1: resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} + dev: true /@tsconfig/node16/1.0.2: resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} + dev: true /@types/argparse/1.0.38: resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} @@ -2711,6 +2717,7 @@ packages: /acorn-walk/8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} + dev: true /acorn/7.4.1: resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} @@ -2721,6 +2728,7 @@ packages: resolution: {integrity: sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==} engines: {node: '>=0.4.0'} hasBin: true + dev: true /add-stream/1.0.0: resolution: {integrity: sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=} @@ -2825,6 +2833,7 @@ packages: /arg/4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true /arg/5.0.1: resolution: {integrity: sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==} @@ -3613,6 +3622,7 @@ packages: /create-require/1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true /cross-env/7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} @@ -3858,6 +3868,7 @@ packages: /diff/4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + dev: true /dir-glob/3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} @@ -5890,6 +5901,7 @@ packages: /make-error/1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true /map-obj/1.0.1: resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=} @@ -6853,11 +6865,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /prismjs/1.28.0: - resolution: {integrity: sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw==} - engines: {node: '>=6'} - dev: true - /process-nextick-args/2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true @@ -7541,6 +7548,14 @@ packages: resolution: {integrity: sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==} dev: true + /shiki/0.10.1: + resolution: {integrity: sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==} + dependencies: + jsonc-parser: 3.0.0 + vscode-oniguruma: 1.6.2 + vscode-textmate: 5.2.0 + dev: true + /side-channel/1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -8182,6 +8197,7 @@ packages: make-error: 1.3.6 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + dev: true /tsconfck/2.0.0: resolution: {integrity: sha512-GVDTXF4MdNBBxKfUfjs/wkb7LHd8Ho8WLavESCddTFQFG9AUZOZEm6kODBGmQopQ9OG+EHpkT6dBaIIGhYVt+Q==} @@ -8423,6 +8439,7 @@ packages: /v8-compile-cache-lib/3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true /v8-compile-cache/2.3.0: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} @@ -8449,9 +8466,9 @@ packages: engines: {node: '>= 0.8'} dev: true - /vitepress/1.0.0-draft.4: - resolution: {integrity: sha512-ViWGXaNFdILpCtC0iOiyNT8zsNYoWZTwZIK7rCrPJWyDD2sIeYuI9uK87pPGJo2XN+OuP7u68Ui86CJRuTtqpw==} - engines: {node: '>=14.0.0'} + /vitepress/1.0.0-draft.8: + resolution: {integrity: sha512-r1cphHgtJ/KFwtph3cyusGWjRyX0NHvwfBboKnG5mRJpOP/JyvX5q5+NIiRYElPgdFXU7Roxkl8BcJbxWht56Q==} + engines: {node: '>=14.6.0'} hasBin: true dependencies: '@docsearch/css': 3.0.0 @@ -8459,7 +8476,7 @@ packages: '@vitejs/plugin-vue': link:packages/plugin-vue '@vueuse/core': 8.5.0_vue@3.2.33 body-scroll-lock: 4.0.0-beta.0 - prismjs: 1.28.0 + shiki: 0.10.1 vite: link:packages/vite vue: 3.2.33 transitivePeerDependencies: @@ -8506,6 +8523,14 @@ packages: engines: {node: '>=0.10.0'} dev: true + /vscode-oniguruma/1.6.2: + resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} + dev: true + + /vscode-textmate/5.2.0: + resolution: {integrity: sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==} + dev: true + /vue-demi/0.12.5_vue@3.2.33: resolution: {integrity: sha512-BREuTgTYlUr0zw0EZn3hnhC3I6gPWv+Kwh4MCih6QcAeaTlaIX0DwOVN0wHej7hSvDPecz4jygy/idsgKfW58Q==} engines: {node: '>=12'} @@ -8742,6 +8767,7 @@ packages: /yn/3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} + dev: true /youch/2.2.2: resolution: {integrity: sha512-/FaCeG3GkuJwaMR34GHVg0l8jCbafZLHiFowSjqLlqhC6OMyf2tPJBu8UirF7/NI9X/R5ai4QfEKUCOxMAGxZQ==} diff --git a/scripts/releaseUtils.ts b/scripts/releaseUtils.ts index 272ab799fbc732..ea6987e1fe5c27 100644 --- a/scripts/releaseUtils.ts +++ b/scripts/releaseUtils.ts @@ -4,7 +4,7 @@ import { existsSync, readdirSync, writeFileSync } from 'fs' import path from 'path' import colors from 'picocolors' -import type { Options as ExecaOptions } from 'execa' +import type { Options as ExecaOptions, ExecaReturnValue } from 'execa' import execa from 'execa' import type { ReleaseType } from 'semver' import semver from 'semver' @@ -39,7 +39,18 @@ export const versionIncrements: ReleaseType[] = [ // 'prerelease' ] -export function getPackageInfo(pkgName: string) { +interface Pkg { + name: string + version: string + private?: boolean +} +export function getPackageInfo(pkgName: string): { + pkg: Pkg + pkgName: string + pkgDir: string + pkgPath: string + currentVersion: string +} { const pkgDir = path.resolve(__dirname, '../packages/' + pkgName) if (!existsSync(pkgDir)) { @@ -47,11 +58,7 @@ export function getPackageInfo(pkgName: string) { } const pkgPath = path.resolve(pkgDir, 'package.json') - const pkg: { - name: string - version: string - private?: boolean - } = require(pkgPath) + const pkg: Pkg = require(pkgPath) const currentVersion = pkg.version if (pkg.private) { @@ -71,7 +78,7 @@ export async function run( bin: string, args: string[], opts: ExecaOptions = {} -) { +): Promise> { return execa(bin, args, { stdio: 'inherit', ...opts }) } @@ -79,7 +86,7 @@ export async function dryRun( bin: string, args: string[], opts?: ExecaOptions -) { +): Promise { return console.log( colors.blue(`[dryrun] ${bin} ${args.join(' ')}`), opts || '' @@ -88,11 +95,15 @@ export async function dryRun( export const runIfNotDry = isDryRun ? dryRun : run -export function step(msg: string) { +export function step(msg: string): void { return console.log(colors.cyan(msg)) } -export function getVersionChoices(currentVersion: string) { +interface VersionChoice { + title: string + value: string +} +export function getVersionChoices(currentVersion: string): VersionChoice[] { const currentBeta = currentVersion.includes('beta') const currentAlpha = currentVersion.includes('alpha') const isStable = !currentBeta && !currentAlpha @@ -101,7 +112,7 @@ export function getVersionChoices(currentVersion: string) { return semver.inc(currentVersion, i, tag)! } - let versionChoices = [ + let versionChoices: VersionChoice[] = [ { title: 'next', value: inc(isStable ? 'patch' : 'prerelease') @@ -175,7 +186,7 @@ export async function publishPackage( }) } -export async function getLatestTag(pkgName: string) { +export async function getLatestTag(pkgName: string): Promise { const tags = (await run('git', ['tag'], { stdio: 'pipe' })).stdout .split(/\n/) .filter(Boolean) @@ -186,7 +197,7 @@ export async function getLatestTag(pkgName: string) { .reverse()[0] } -export async function logRecentCommits(pkgName: string) { +export async function logRecentCommits(pkgName: string): Promise { const tag = await getLatestTag(pkgName) if (!tag) return const sha = await run('git', ['rev-list', '-n', '1', tag], { @@ -214,7 +225,7 @@ export async function logRecentCommits(pkgName: string) { console.log() } -export async function updateTemplateVersions() { +export async function updateTemplateVersions(): Promise { const viteVersion = (await fs.readJSON('../packages/vite/package.json')) .version if (/beta|alpha|rc/.test(viteVersion)) return