diff --git a/.eslintrc.cjs b/.eslintrc.cjs index edc202b5e539df..f0b3be9e03a8bb 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -155,7 +155,7 @@ module.exports = defineConfig({ } }, { - files: ['*.js'], + files: ['playground/**', '*.js'], rules: { '@typescript-eslint/explicit-module-boundary-types': 'off' } diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 05c1c02ab4cb12..0014c768519180 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -19,15 +19,9 @@ "typescript", // breaking changes - "cac", // `cac:v6.7.10+` has breaking changes - "react-router", // `react-router:v6.0.0+` has breaking changes - "react-router-dom", // `react-router-dom:v6.0.0+` has breaking changes "source-map", // `source-map:v0.7.0+` needs more investigation "dotenv-expand", // `dotenv-expand:6.0.0+` has breaking changes (#6858) - - // ESM Only => https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#how-can-i-move-my-commonjs-project-to-esm - "node-fetch", - "periscopic", - "strip-ansi" + "kill-port", // `kill-port:^2.0.0 has perf issues (#8392) + "miniflare" // `miniflare:v2.0.0+` only supports node 16.7 ] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 248bb3fbedd101..f190529faa247d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,6 +4,8 @@ env: # 7 GiB by default on GitHub, setting to 6 GiB # https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources NODE_OPTIONS: --max-old-space-size=6144 + # install playwright binary manually (because pnpm only runs install script once) + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" on: push: @@ -38,10 +40,6 @@ jobs: node_version: 16 fail-fast: false - env: - # Install playwright's binray under node_modules so it will be cached together - PLAYWRIGHT_BROWSERS_PATH: "0" - name: "Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}" steps: - name: Checkout @@ -59,8 +57,25 @@ jobs: - name: Install deps run: pnpm install + # Install playwright's binary under custom directory to cache + - name: Set Playwright path (non-windows) + if: runner.os != 'Windows' + run: echo "PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin" >> $GITHUB_ENV + - name: Set Playwright path (windows) + if: runner.os == 'Windows' + run: echo "PLAYWRIGHT_BROWSERS_PATH=$HOME\.cache\playwright-bin" >> $env:GITHUB_ENV + + - name: Cache Playwright's binary + uses: actions/cache@v3 + with: + # Playwright removes unused browsers automatically + # So does not need to add playwright version to key + key: ${{ runner.os }}-playwright-bin-v1 + path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }} + - name: Install Playwright - run: pnpm playwright install + # does not need to explictly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved + run: pnpm playwright install chromium - name: Build run: pnpm run build @@ -97,8 +112,6 @@ jobs: - name: Install deps run: pnpm install - env: - PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1" - name: Build run: pnpm run build diff --git a/.gitignore b/.gitignore index 9194d44b544c4e..7f1cab0e1f4356 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ node_modules playground-temp temp TODOs.md +.eslintcache diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 9c3150eb1d0c1b..55b4657af24288 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -14,9 +14,7 @@ export default defineConfig({ logo: '/logo.svg', editLink: { - repo: 'vitejs/vite', - branch: 'main', - dir: 'docs', + pattern: 'https://github.com/vitejs/vite/edit/main/docs/:path', text: 'Suggest changes to this page' }, diff --git a/docs/config/build-options.md b/docs/config/build-options.md index 11b4685aa72555..f0f213d5d44428 100644 --- a/docs/config/build-options.md +++ b/docs/config/build-options.md @@ -147,6 +147,12 @@ Set to `false` to disable minification, or specify the minifier to use. The defa Note the `build.minify` option is not available when using the `'es'` format in lib mode. +Terser must be installed when it is set to `'terser'`. + +```sh +npm add -D terser +``` + ## build.terserOptions - **Type:** `TerserOptions` diff --git a/docs/config/index.md b/docs/config/index.md index 31e341a399756e..73a20082295304 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -24,14 +24,14 @@ vite --config my-config.js ``` ::: tip NOTE -Vite will replace `__filename`, `__dirname`, and `import.meta.url` in config files and its deps. Using these as variable names or passing as a parameter to a function with string double quote (example `console.log`) will result in an error: +Vite will inject `__filename`, `__dirname` in config files and its deps. Declaring these variables at top level will result in an error: ```js -const __filename = "value" -// will be transformed to -const "path/vite.config.js" = "value" +const __filename = 'value' // SyntaxError: Identifier '__filename' has already been declared -console.log("import.meta.url") // break error on build +const func = () => { + const __filename = 'value' // no error +} ``` ::: @@ -41,14 +41,10 @@ console.log("import.meta.url") // break error on build Since Vite ships with TypeScript typings, you can leverage your IDE's intellisense with jsdoc type hints: ```js -/** - * @type {import('vite').UserConfig} - */ -const config = { +/** @type {import('vite').UserConfig} */ +export default { // ... } - -export default config ``` Alternatively, you can use the `defineConfig` helper which should provide intellisense without the need for jsdoc annotations: diff --git a/docs/config/server-options.md b/docs/config/server-options.md index e6a9377e98593f..03b747d9525f3c 100644 --- a/docs/config/server-options.md +++ b/docs/config/server-options.md @@ -3,7 +3,7 @@ ## server.host - **Type:** `string | boolean` -- **Default:** `'127.0.0.1'` +- **Default:** `'localhost'` Specify which IP addresses the server should listen on. Set this to `0.0.0.0` or `true` to listen on all addresses, including LAN and public addresses. diff --git a/docs/config/worker-options.md b/docs/config/worker-options.md index c0c13bf4133adb..c506d249a24932 100644 --- a/docs/config/worker-options.md +++ b/docs/config/worker-options.md @@ -11,7 +11,7 @@ Output format for worker bundle. - **Type:** [`(Plugin | Plugin[])[]`](./shared-options#plugins) -Vite plugins that apply to worker bundle +Vite plugins that apply to worker bundle. Note that [config.plugins](./shared-options#plugins) does not apply to workers, it should be configured here instead. ## worker.rollupOptions diff --git a/docs/guide/api-plugin.md b/docs/guide/api-plugin.md index 735a30d3266909..51dc3ef6e0f78f 100644 --- a/docs/guide/api-plugin.md +++ b/docs/guide/api-plugin.md @@ -517,6 +517,10 @@ normalizePath('foo\\bar') // 'foo/bar' normalizePath('foo/bar') // 'foo/bar' ``` +## Filtering, include/exclude pattern + +Vite exposes [`@rollup/pluginutils`'s `createFilter`](https://github.com/rollup/plugins/tree/master/packages/pluginutils#createfilter) function to encourage Vite specific plugins and integrations to use the standard include/exclude filtering pattern, which is also used in Vite core itself. + ## Client-server Communication Since Vite 2.9, we provide some utilities for plugins to help handle the communication with clients. diff --git a/docs/guide/features.md b/docs/guide/features.md index d58a09e4cbf2cb..65d01f9b6c7239 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -34,7 +34,7 @@ Vite only performs transpilation on `.ts` files and does **NOT** perform type ch Vite uses [esbuild](https://github.com/evanw/esbuild) to transpile TypeScript into JavaScript which is about 20~30x faster than vanilla `tsc`, and HMR updates can reflect in the browser in under 50ms. -Use the [Type-Only Imports and Export](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax to avoid potential problems like type-only imports being incorrectly bundled. for example: +Use the [Type-Only Imports and Export](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) syntax to avoid potential problems like type-only imports being incorrectly bundled, for example: ```ts import type { T } from 'only/types' @@ -511,6 +511,12 @@ By default, the worker script will be emitted as a separate chunk in the product import MyWorker from './worker?worker&inline' ``` +If you wish to retrieve the worker as a URL, add the `url` query: + +```js +import MyWorker from './worker?worker&url' +``` + See [Worker Options](/config/#worker-options) for details on configuring the bundling of all workers. ## Build Optimizations diff --git a/docs/guide/migration.md b/docs/guide/migration.md index 78b738afb82ddf..9885dec7117742 100644 --- a/docs/guide/migration.md +++ b/docs/guide/migration.md @@ -31,6 +31,8 @@ A small fraction of users will now require using [@vitejs/plugin-legacy](https:/ Vite's default dev server port is now 5173. You can use [`server.port`](../config/server-options.md#server-port) to set it to 3000. +Vite's default dev server host is now `localhost`. You can use [`server.host`](../config/server-options.md#server-host) to set it to `127.0.0.1`. + Vite optimizes dependencies with esbuild to both convert CJS-only deps to ESM and to reduce the number of modules the browser needs to request. In v3, the default strategy to discover and batch dependencies has changed. Vite no longer pre-scans user code with esbuild to get an initial list of dependencies on cold start. Instead, it delays the first dependency optimization run until every imported user module on load is processed. To get back the v2 strategy, you can use [`optimizeDeps.devScan`](../config/dep-optimization-options.md#optimizedepsdevscan). @@ -50,6 +52,10 @@ If using ESM for SSR isn't possible in your project, you can set `ssr.format: 'c ## General Changes - JS file extensions in SSR and lib mode now use a valid extension (`js`, `mjs`, or `cjs`) for output JS entries and chunks based on their format and the package type. +- Terser is now an optional dependency. If you are using `build.minify: 'terser'`, you need to install it. + ```shell + npm add -D terser + ``` ### `import.meta.glob` @@ -93,6 +99,8 @@ There are some changes which only affects plugin/tool creators. - `printHttpServerUrls` is removed - `server.app`, `server.transformWithEsbuild` are removed - `import.meta.hot.acceptDeps` is removed +- [[#6901] fix: sequential injection of tags in transformIndexHtml](https://github.com/vitejs/vite/pull/6901) + - `transformIndexHtml` now gets the correct content modified by earlier plugins, so the order of the injected tags now works as expected. - [[#7995] chore: do not fixStacktrace](https://github.com/vitejs/vite/pull/7995) - `ssrLoadModule`'s `fixStacktrace` option's default is now `false` - [[#8178] feat!: migrate to ESM](https://github.com/vitejs/vite/pull/8178) @@ -105,8 +113,12 @@ Also there are other breaking changes which only affect few users. - Transpile to ES5 is now necessary even if the user code only includes ES5. - [[#7877] fix: vite client types](https://github.com/vitejs/vite/pull/7877) - `/// ` is removed from `vite/client.d.ts`. `{ "lib": ["dom"] }` or `{ "lib": ["webworker"] }` is necessary in `tsconfig.json`. +- [[#8090] feat: preserve process env vars in lib build](https://github.com/vitejs/vite/pull/8090) + - `process.env.*` is now preserved in library mode - [[#8280] feat: non-blocking esbuild optimization at build time](https://github.com/vitejs/vite/pull/8280) - `server.force` option was removed in favor of `force` option. +- [[#8550] fix: dont handle sigterm in middleware mode](https://github.com/vitejs/vite/pull/8550) + - When running in middleware mode, Vite no longer kills process on `SIGTERM`. ## Migration from v1 diff --git a/docs/guide/static-deploy.md b/docs/guide/static-deploy.md index 7b732cb990cbf6..97ebae14372340 100644 --- a/docs/guide/static-deploy.md +++ b/docs/guide/static-deploy.md @@ -266,12 +266,17 @@ You can also deploy to a [custom domain](http://surge.sh/help/adding-a-custom-do # creates a new app with a specified name $ heroku apps:create example + ``` + +6. Set buildpacks. We use `heroku/nodejs` to build the project and `heroku-buildpack-static` to serve it. - # set buildpack for static sites - $ heroku buildpacks:set https://github.com/heroku/heroku-buildpack-static.git + ```bash + # set buildpacks + $ heroku buildpacks:set heroku/nodejs + $ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-static.git ``` -6. Deploy your site: +7. Deploy your site: ```bash # publish site diff --git a/package.json b/package.json index aafd42d91f7cf6..d9923fa7b80bf4 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ ], "scripts": { "preinstall": "npx only-allow pnpm", - "format": "prettier --write .", - "lint": "eslint packages/*/{src,types,__tests__}/** playground/**/__tests__/**/*.ts scripts/**", + "format": "prettier --write --cache .", + "lint": "eslint --cache 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", @@ -35,8 +35,8 @@ }, "devDependencies": { "@babel/types": "^7.18.4", - "@microsoft/api-extractor": "^7.24.2", - "@rollup/plugin-typescript": "^8.3.2", + "@microsoft/api-extractor": "^7.25.0", + "@rollup/plugin-typescript": "^8.3.3", "@types/babel__core": "^7.1.19", "@types/babel__standalone": "^7.1.4", "@types/convert-source-map": "^1.5.2", @@ -50,37 +50,37 @@ "@types/micromatch": "^4.0.2", "@types/mime": "^2.0.3", "@types/minimist": "^1.2.2", - "@types/node": "^17.0.31", + "@types/node": "^17.0.42", "@types/prompts": "^2.4.0", "@types/resolve": "^1.20.2", "@types/sass": "~1.43.1", "@types/semver": "^7.3.9", "@types/stylus": "^0.48.38", "@types/ws": "^8.5.3", - "@typescript-eslint/eslint-plugin": "^5.27.0", - "@typescript-eslint/parser": "^5.27.0", + "@typescript-eslint/eslint-plugin": "^5.27.1", + "@typescript-eslint/parser": "^5.27.1", "conventional-changelog-cli": "^2.2.2", "cross-env": "^7.0.3", - "esbuild": "^0.14.38", - "eslint": "^8.16.0", - "eslint-define-config": "^1.5.0", + "esbuild": "^0.14.43", + "eslint": "^8.17.0", + "eslint-define-config": "^1.5.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-node": "^11.1.0", "esno": "^0.16.3", - "execa": "^5.1.1", + "execa": "^6.1.0", "fs-extra": "^10.1.0", "kill-port": "^1.6.1", - "lint-staged": "^12.4.3", + "lint-staged": "^13.0.1", "minimist": "^1.2.6", - "node-fetch": "^2.6.7", + "node-fetch": "^3.2.6", "npm-run-all": "^4.1.5", "picocolors": "^1.0.0", "playwright-chromium": "^1.22.2", - "pnpm": "^7.1.7", - "prettier": "2.6.2", + "pnpm": "^7.2.1", + "prettier": "2.7.0", "prompts": "^2.4.2", "rimraf": "^3.0.2", - "rollup": "^2.72.1", + "rollup": "^2.75.6", "semver": "^7.3.7", "simple-git-hooks": "^2.8.0", "sirv": "^2.0.2", @@ -88,9 +88,9 @@ "typescript": "^4.6.4", "unbuild": "^0.7.4", "vite": "workspace:*", - "vitepress": "1.0.0-draft.8", - "vitest": "^0.13.0", - "vue": "^3.2.36" + "vitepress": "^1.0.0-alpha.2", + "vitest": "^0.14.2", + "vue": "^3.2.37" }, "simple-git-hooks": { "pre-commit": "pnpm exec lint-staged --concurrent false", @@ -98,19 +98,19 @@ }, "lint-staged": { "*": [ - "prettier --write --ignore-unknown" + "prettier --write --cache --ignore-unknown" ], "packages/*/{src,types}/**/*.ts": [ - "eslint --fix" + "eslint --cache --fix" ], "packages/**/*.d.ts": [ - "eslint --fix" + "eslint --cache --fix" ], "playground/**/__tests__/**/*.ts": [ - "eslint --fix" + "eslint --cache --fix" ] }, - "packageManager": "pnpm@7.1.7", + "packageManager": "pnpm@7.2.1", "pnpm": { "overrides": { "vite": "workspace:*", diff --git a/packages/create-vite/README.md b/packages/create-vite/README.md index e22c268ab99f9c..7c753d212bd302 100644 --- a/packages/create-vite/README.md +++ b/packages/create-vite/README.md @@ -56,6 +56,8 @@ Currently supported template presets include: - `svelte` - `svelte-ts` +You can use `.` for the project name to scaffold in the current directory. + ## Community Templates create-vite is a tool to quickly start a project from a basic template for popular frameworks. Check out Awesome Vite for [community maintained templates](https://github.com/vitejs/awesome-vite#templates) that include other tools or target different frameworks. You can use a tool like [degit](https://github.com/Rich-Harris/degit) to scaffold your project with one of the templates. diff --git a/packages/create-vite/__tests__/cli.spec.ts b/packages/create-vite/__tests__/cli.spec.ts index d9b6bafdefa306..39ac7e1e547a36 100644 --- a/packages/create-vite/__tests__/cli.spec.ts +++ b/packages/create-vite/__tests__/cli.spec.ts @@ -1,6 +1,6 @@ import { join } from 'path' import type { ExecaSyncReturnValue, SyncOptions } from 'execa' -import { commandSync } from 'execa' +import { execaCommandSync } from 'execa' import { mkdirpSync, readdirSync, remove, writeFileSync } from 'fs-extra' import { afterEach, beforeAll, expect, test } from 'vitest' @@ -13,7 +13,7 @@ const run = ( args: string[], options: SyncOptions = {} ): ExecaSyncReturnValue => { - return commandSync(`node ${CLI_PATH} ${args.join(' ')}`, options) + return execaCommandSync(`node ${CLI_PATH} ${args.join(' ')}`, options) } // Helper to create a non-empty directory @@ -40,6 +40,12 @@ test('prompts for the project name if none supplied', () => { expect(stdout).toContain('Project name:') }) +test('prompts for the framework if none supplied when target dir is current directory', () => { + mkdirpSync(genPath) + const { stdout } = run(['.'], { cwd: genPath }) + expect(stdout).toContain('Select a framework:') +}) + test('prompts for the framework if none supplied', () => { const { stdout } = run([projectName]) expect(stdout).toContain('Select a framework:') @@ -65,7 +71,7 @@ test('asks to overwrite non-empty target directory', () => { test('asks to overwrite non-empty current directory', () => { createNonEmptyDir() - const { stdout } = run(['.'], { cwd: genPath, input: 'test-app\n' }) + const { stdout } = run(['.'], { cwd: genPath }) expect(stdout).toContain(`Current directory is not empty.`) }) diff --git a/packages/create-vite/index.js b/packages/create-vite/index.js index 93ddb3c3f027a1..ec084e8327d603 100755 --- a/packages/create-vite/index.js +++ b/packages/create-vite/index.js @@ -130,12 +130,12 @@ const renameFiles = { } async function init() { - let targetDir = argv._[0] + let targetDir = formatTargetDir(argv._[0]) let template = argv.template || argv.t - const defaultProjectName = !targetDir - ? 'vite-project' - : targetDir.trim().replace(/\/+$/g, '') + const defaultTargetDir = 'vite-project' + const getProjectName = () => + targetDir === '.' ? path.basename(path.resolve()) : targetDir let result = {} @@ -146,10 +146,10 @@ async function init() { type: targetDir ? null : 'text', name: 'projectName', message: reset('Project name:'), - initial: defaultProjectName, - onState: (state) => - (targetDir = - state.value.trim().replace(/\/+$/g, '') || defaultProjectName) + initial: defaultTargetDir, + onState: (state) => { + targetDir = formatTargetDir(state.value) || defaultTargetDir + } }, { type: () => @@ -171,10 +171,10 @@ async function init() { name: 'overwriteChecker' }, { - type: () => (isValidPackageName(targetDir) ? null : 'text'), + type: () => (isValidPackageName(getProjectName()) ? null : 'text'), name: 'packageName', message: reset('Package name:'), - initial: () => toValidPackageName(targetDir), + initial: () => toValidPackageName(getProjectName()), validate: (dir) => isValidPackageName(dir) || 'Invalid package.json name' }, @@ -265,7 +265,7 @@ async function init() { fs.readFileSync(path.join(templateDir, `package.json`), 'utf-8') ) - pkg.name = packageName || targetDir + pkg.name = packageName || getProjectName() write('package.json', JSON.stringify(pkg, null, 2)) @@ -289,6 +289,13 @@ async function init() { console.log() } +/** + * @param {string | undefined} targetDir + */ +function formatTargetDir(targetDir) { + return targetDir?.trim().replace(/\/+$/g, '') +} + function copy(src, dest) { const stat = fs.statSync(src) if (stat.isDirectory()) { diff --git a/packages/create-vite/template-lit-ts/index.html b/packages/create-vite/template-lit-ts/index.html index d8846e99db1d36..fdee573db235f3 100644 --- a/packages/create-vite/template-lit-ts/index.html +++ b/packages/create-vite/template-lit-ts/index.html @@ -2,14 +2,15 @@ - + - Vite + Lit App + Vite + Lit + TS + -

This is child content

+

Vite + Lit

diff --git a/packages/create-vite/template-lit-ts/package.json b/packages/create-vite/template-lit-ts/package.json index 57358902f93458..42b05efd7e8a5d 100644 --- a/packages/create-vite/template-lit-ts/package.json +++ b/packages/create-vite/template-lit-ts/package.json @@ -3,9 +3,9 @@ "private": true, "version": "0.0.0", "type": "module", - "main": "dist/my-element.es.mjs", + "main": "dist/my-element.es.js", "exports": { - ".": "./dist/my-element.es.mjs" + ".": "./dist/my-element.es.js" }, "types": "types/my-element.d.ts", "files": [ @@ -21,6 +21,6 @@ }, "devDependencies": { "typescript": "^4.6.4", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-lit-ts/public/vite.svg b/packages/create-vite/template-lit-ts/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-lit-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-lit-ts/src/assets/lit.svg b/packages/create-vite/template-lit-ts/src/assets/lit.svg new file mode 100644 index 00000000000000..4a9c1fe662ea4e --- /dev/null +++ b/packages/create-vite/template-lit-ts/src/assets/lit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-lit-ts/src/favicon.svg b/packages/create-vite/template-lit-ts/src/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-lit-ts/src/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-lit-ts/src/index.css b/packages/create-vite/template-lit-ts/src/index.css new file mode 100644 index 00000000000000..d39ac2e34eebe8 --- /dev/null +++ b/packages/create-vite/template-lit-ts/src/index.css @@ -0,0 +1,40 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } +} diff --git a/packages/create-vite/template-lit-ts/src/my-element.ts b/packages/create-vite/template-lit-ts/src/my-element.ts index c7fd4c6d6982f4..ba01ce52154a0d 100644 --- a/packages/create-vite/template-lit-ts/src/my-element.ts +++ b/packages/create-vite/template-lit-ts/src/my-element.ts @@ -1,5 +1,7 @@ import { html, css, LitElement } from 'lit' import { customElement, property } from 'lit/decorators.js' +import viteLogo from '/vite.svg' +import litLogo from './assets/lit.svg' /** * An example element. @@ -9,20 +11,11 @@ import { customElement, property } from 'lit/decorators.js' */ @customElement('my-element') export class MyElement extends LitElement { - static styles = css` - :host { - display: block; - border: solid 1px gray; - padding: 16px; - max-width: 800px; - } - ` - /** - * The name to say "Hello" to. + * Copy for the read the docs hint. */ @property() - name = 'World' + docsHint = 'Click on the Vite and Lit logos to learn more' /** * The number of times the button has been clicked. @@ -32,11 +25,21 @@ export class MyElement extends LitElement { render() { return html` -

Hello, ${this.name}!

- +
+ + + + + + +
+
+ +
+

${this.docsHint}

` } @@ -44,9 +47,76 @@ export class MyElement extends LitElement { this.count++ } - foo(): string { - return 'foo' - } + static styles = css` + :host { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; + } + + .logo { + height: 6em; + padding: 1.5em; + will-change: filter; + } + .logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); + } + .logo.lit:hover { + filter: drop-shadow(0 0 2em #325cffaa); + } + + .card { + padding: 2em; + } + + .read-the-docs { + color: #888; + } + + h1 { + font-size: 3.2em; + line-height: 1.1; + } + + a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; + } + a:hover { + color: #535bf2; + } + + button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; + } + button:hover { + border-color: #646cff; + } + button:focus, + button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; + } + + @media (prefers-color-scheme: light) { + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } + } + ` } declare global { diff --git a/packages/create-vite/template-lit/index.html b/packages/create-vite/template-lit/index.html index 2c9742f1c3bcff..e8be0205b1d8cf 100644 --- a/packages/create-vite/template-lit/index.html +++ b/packages/create-vite/template-lit/index.html @@ -2,14 +2,15 @@ - + - Vite + Lit App + Vite + Lit + -

This is child content

+

Vite + Lit

diff --git a/packages/create-vite/template-lit/package.json b/packages/create-vite/template-lit/package.json index 0ef4af046dfa8d..5d5ed85a4fc57c 100644 --- a/packages/create-vite/template-lit/package.json +++ b/packages/create-vite/template-lit/package.json @@ -3,9 +3,9 @@ "private": true, "version": "0.0.0", "type": "module", - "main": "dist/my-element.es.mjs", + "main": "dist/my-element.es.js", "exports": { - ".": "./dist/my-element.es.mjs" + ".": "./dist/my-element.es.js" }, "files": [ "dist" @@ -18,6 +18,6 @@ "lit": "^2.2.5" }, "devDependencies": { - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-lit/public/vite.svg b/packages/create-vite/template-lit/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-lit/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-lit/src/assets/lit.svg b/packages/create-vite/template-lit/src/assets/lit.svg new file mode 100644 index 00000000000000..4a9c1fe662ea4e --- /dev/null +++ b/packages/create-vite/template-lit/src/assets/lit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-lit/src/favicon.svg b/packages/create-vite/template-lit/src/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-lit/src/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-lit/src/index.css b/packages/create-vite/template-lit/src/index.css new file mode 100644 index 00000000000000..b52d4c639b5e5f --- /dev/null +++ b/packages/create-vite/template-lit/src/index.css @@ -0,0 +1,31 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } +} diff --git a/packages/create-vite/template-lit/src/my-element.js b/packages/create-vite/template-lit/src/my-element.js index 83b11fa869c26c..74fde11f608122 100644 --- a/packages/create-vite/template-lit/src/my-element.js +++ b/packages/create-vite/template-lit/src/my-element.js @@ -1,4 +1,6 @@ import { html, css, LitElement } from 'lit' +import viteLogo from '/vite.svg' +import litLogo from './assets/lit.svg' /** * An example element. @@ -7,23 +9,12 @@ import { html, css, LitElement } from 'lit' * @csspart button - The button */ export class MyElement extends LitElement { - static get styles() { - return css` - :host { - display: block; - border: solid 1px gray; - padding: 16px; - max-width: 800px; - } - ` - } - static get properties() { return { /** - * The name to say "Hello" to. + * Copy for the read the docs hint. */ - name: { type: String }, + docsHint: { type: String }, /** * The number of times the button has been clicked. @@ -34,23 +25,106 @@ export class MyElement extends LitElement { constructor() { super() - this.name = 'World' + this.docsHint = 'Click on the Vite and Lit logos to learn more' this.count = 0 } render() { return html` -

Hello, ${this.name}!

- +
+ + + + + + +
+
+ +
+

${this.docsHint}

` } _onClick() { this.count++ } + + static get styles() { + return css` + :host { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; + } + + .logo { + height: 6em; + padding: 1.5em; + will-change: filter; + } + .logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); + } + .logo.lit:hover { + filter: drop-shadow(0 0 2em #325cffaa); + } + + .card { + padding: 2em; + } + + .read-the-docs { + color: #888; + } + + a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; + } + a:hover { + color: #535bf2; + } + + h1 { + font-size: 3.2em; + line-height: 1.1; + } + + button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; + } + button:hover { + border-color: #646cff; + } + button:focus, + button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; + } + + @media (prefers-color-scheme: light) { + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } + } + ` + } } window.customElements.define('my-element', MyElement) diff --git a/packages/create-vite/template-preact-ts/index.html b/packages/create-vite/template-preact-ts/index.html index 5dd45a1e2ab404..ed0f5bbd72520b 100644 --- a/packages/create-vite/template-preact-ts/index.html +++ b/packages/create-vite/template-preact-ts/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + Preact + TS
diff --git a/packages/create-vite/template-preact-ts/package.json b/packages/create-vite/template-preact-ts/package.json index daa47a76c434bc..ff7efa97a7b0ae 100644 --- a/packages/create-vite/template-preact-ts/package.json +++ b/packages/create-vite/template-preact-ts/package.json @@ -9,11 +9,11 @@ "preview": "vite preview" }, "dependencies": { - "preact": "^10.7.2" + "preact": "^10.7.3" }, "devDependencies": { "@preact/preset-vite": "^2.2.0", "typescript": "^4.6.4", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-preact-ts/public/vite.svg b/packages/create-vite/template-preact-ts/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-preact-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-preact-ts/src/app.css b/packages/create-vite/template-preact-ts/src/app.css new file mode 100644 index 00000000000000..088ed3ace55196 --- /dev/null +++ b/packages/create-vite/template-preact-ts/src/app.css @@ -0,0 +1,25 @@ +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.preact:hover { + filter: drop-shadow(0 0 2em #673ab8aa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/packages/create-vite/template-preact-ts/src/app.tsx b/packages/create-vite/template-preact-ts/src/app.tsx index 64fe3eda94c933..13cf0b1b01f2fc 100644 --- a/packages/create-vite/template-preact-ts/src/app.tsx +++ b/packages/create-vite/template-preact-ts/src/app.tsx @@ -1,19 +1,32 @@ -import { Logo } from './logo' +import { useState } from 'preact/hooks' +import viteLogo from '/vite.svg' +import preactLogo from './assets/preact.svg' +import './app.css' export function App() { + const [count, setCount] = useState(0) + return ( <> - -

Hello Vite + Preact!

-

- - Learn Preact +

+ + + + + +
+

Vite + Preact

+
+ +

+ Edit src/app.tsx and save to test HMR +

+
+

+ Click on the Vite and Preact logos to learn more

) diff --git a/packages/create-vite/template-preact-ts/src/assets/preact.svg b/packages/create-vite/template-preact-ts/src/assets/preact.svg new file mode 100644 index 00000000000000..908f17def0b5a4 --- /dev/null +++ b/packages/create-vite/template-preact-ts/src/assets/preact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-preact-ts/src/favicon.svg b/packages/create-vite/template-preact-ts/src/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-preact-ts/src/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-preact-ts/src/index.css b/packages/create-vite/template-preact-ts/src/index.css index 3d36f1648343ec..917888c1d1115a 100644 --- a/packages/create-vite/template-preact-ts/src/index.css +++ b/packages/create-vite/template-preact-ts/src/index.css @@ -1,30 +1,70 @@ -html, -body { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - background: #fafafa; - font-family: 'Helvetica Neue', arial, sans-serif; +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; font-weight: 400; - color: #444; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; } -* { - box-sizing: border-box; +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; } -#app { - height: 100%; - text-align: center; - background-color: #673ab8; - color: #fff; - font-size: 1.5em; - padding-top: 100px; +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; } -.link { - color: #fff; +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } } diff --git a/packages/create-vite/template-preact-ts/src/logo.tsx b/packages/create-vite/template-preact-ts/src/logo.tsx deleted file mode 100644 index dee6f347a90a54..00000000000000 --- a/packages/create-vite/template-preact-ts/src/logo.tsx +++ /dev/null @@ -1,47 +0,0 @@ -export const Logo = () => ( - -) diff --git a/packages/create-vite/template-preact-ts/src/main.tsx b/packages/create-vite/template-preact-ts/src/main.tsx index 812f602e33bc95..e0ce3e9980eecd 100644 --- a/packages/create-vite/template-preact-ts/src/main.tsx +++ b/packages/create-vite/template-preact-ts/src/main.tsx @@ -2,4 +2,4 @@ import { render } from 'preact' import { App } from './app' import './index.css' -render(, document.getElementById('app')!) +render(, document.getElementById('app') as HTMLElement) diff --git a/packages/create-vite/template-preact/index.html b/packages/create-vite/template-preact/index.html index c06e9fce67a28f..9f89c1bcc0ddef 100644 --- a/packages/create-vite/template-preact/index.html +++ b/packages/create-vite/template-preact/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + Preact
diff --git a/packages/create-vite/template-preact/package.json b/packages/create-vite/template-preact/package.json index 438307a4c75b61..327f2d0e1dcaa4 100644 --- a/packages/create-vite/template-preact/package.json +++ b/packages/create-vite/template-preact/package.json @@ -9,10 +9,10 @@ "preview": "vite preview" }, "dependencies": { - "preact": "^10.7.2" + "preact": "^10.7.3" }, "devDependencies": { "@preact/preset-vite": "^2.2.0", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-preact/public/vite.svg b/packages/create-vite/template-preact/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-preact/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-preact/src/app.css b/packages/create-vite/template-preact/src/app.css new file mode 100644 index 00000000000000..088ed3ace55196 --- /dev/null +++ b/packages/create-vite/template-preact/src/app.css @@ -0,0 +1,25 @@ +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.preact:hover { + filter: drop-shadow(0 0 2em #673ab8aa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/packages/create-vite/template-preact/src/app.jsx b/packages/create-vite/template-preact/src/app.jsx index 64fe3eda94c933..717cc480198df8 100644 --- a/packages/create-vite/template-preact/src/app.jsx +++ b/packages/create-vite/template-preact/src/app.jsx @@ -1,19 +1,32 @@ -import { Logo } from './logo' +import { useState } from 'preact/hooks' +import viteLogo from '/vite.svg' +import preactLogo from './assets/preact.svg' +import './app.css' export function App() { + const [count, setCount] = useState(0) + return ( <> - -

Hello Vite + Preact!

-

- - Learn Preact +

+

Vite + Preact

+
+ +

+ Edit src/app.jsx and save to test HMR +

+
+

+ Click on the Vite and Preact logos to learn more

) diff --git a/packages/create-vite/template-preact/src/assets/preact.svg b/packages/create-vite/template-preact/src/assets/preact.svg new file mode 100644 index 00000000000000..908f17def0b5a4 --- /dev/null +++ b/packages/create-vite/template-preact/src/assets/preact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-preact/src/favicon.svg b/packages/create-vite/template-preact/src/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-preact/src/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-preact/src/index.css b/packages/create-vite/template-preact/src/index.css index 3d36f1648343ec..917888c1d1115a 100644 --- a/packages/create-vite/template-preact/src/index.css +++ b/packages/create-vite/template-preact/src/index.css @@ -1,30 +1,70 @@ -html, -body { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - background: #fafafa; - font-family: 'Helvetica Neue', arial, sans-serif; +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; font-weight: 400; - color: #444; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; } -* { - box-sizing: border-box; +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; } -#app { - height: 100%; - text-align: center; - background-color: #673ab8; - color: #fff; - font-size: 1.5em; - padding-top: 100px; +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; } -.link { - color: #fff; +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } } diff --git a/packages/create-vite/template-preact/src/logo.jsx b/packages/create-vite/template-preact/src/logo.jsx deleted file mode 100644 index dee6f347a90a54..00000000000000 --- a/packages/create-vite/template-preact/src/logo.jsx +++ /dev/null @@ -1,47 +0,0 @@ -export const Logo = () => ( - -) diff --git a/packages/create-vite/template-react-ts/index.html b/packages/create-vite/template-react-ts/index.html index 38f386110323c3..e0d1c840806ee7 100644 --- a/packages/create-vite/template-react-ts/index.html +++ b/packages/create-vite/template-react-ts/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + React + TS
diff --git a/packages/create-vite/template-react-ts/package.json b/packages/create-vite/template-react-ts/package.json index 7e91f9c6589b16..ce427c4eb447a5 100644 --- a/packages/create-vite/template-react-ts/package.json +++ b/packages/create-vite/template-react-ts/package.json @@ -13,10 +13,10 @@ "react-dom": "^18.1.0" }, "devDependencies": { - "@types/react": "^18.0.9", + "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", "@vitejs/plugin-react": "^1.3.2", "typescript": "^4.6.4", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-react-ts/public/vite.svg b/packages/create-vite/template-react-ts/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-react-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-react-ts/src/App.css b/packages/create-vite/template-react-ts/src/App.css index 8da3fde63d9e7d..2c5e2ef5cd1a2e 100644 --- a/packages/create-vite/template-react-ts/src/App.css +++ b/packages/create-vite/template-react-ts/src/App.css @@ -1,34 +1,23 @@ -.App { +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; text-align: center; } -.App-logo { - height: 40vmin; - pointer-events: none; +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; } - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); } - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); } -@keyframes App-logo-spin { +@keyframes logo-spin { from { transform: rotate(0deg); } @@ -37,6 +26,16 @@ } } -button { - font-size: calc(10px + 2vmin); +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; } diff --git a/packages/create-vite/template-react-ts/src/App.tsx b/packages/create-vite/template-react-ts/src/App.tsx index 3d9bd71e51303e..dfe8ceddf40982 100644 --- a/packages/create-vite/template-react-ts/src/App.tsx +++ b/packages/create-vite/template-react-ts/src/App.tsx @@ -1,5 +1,6 @@ import { useState } from 'react' -import logo from './logo.svg' +import viteLogo from '/vite.svg' +import reactLogo from './assets/react.svg' import './App.css' function App() { @@ -7,37 +8,26 @@ function App() { return (
-
- logo -

Hello Vite + React!

+ +

Vite + React

+
+

- + Edit src/App.tsx and save to test HMR

-

- Edit App.tsx and save to test HMR updates. -

-

- - Learn React - - {' | '} - - Vite Docs - -

-
+
+

+ Click on the Vite and React logos to learn more +

) } diff --git a/packages/create-vite/template-react-ts/src/assets/react.svg b/packages/create-vite/template-react-ts/src/assets/react.svg new file mode 100644 index 00000000000000..6c87de9bb33584 --- /dev/null +++ b/packages/create-vite/template-react-ts/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-react-ts/src/favicon.svg b/packages/create-vite/template-react-ts/src/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-react-ts/src/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-react-ts/src/index.css b/packages/create-vite/template-react-ts/src/index.css index ec2585e8c0bb81..917888c1d1115a 100644 --- a/packages/create-vite/template-react-ts/src/index.css +++ b/packages/create-vite/template-react-ts/src/index.css @@ -1,13 +1,70 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; } -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } } diff --git a/packages/create-vite/template-react-ts/src/logo.svg b/packages/create-vite/template-react-ts/src/logo.svg deleted file mode 100644 index 6b60c1042f58d9..00000000000000 --- a/packages/create-vite/template-react-ts/src/logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/packages/create-vite/template-react/index.html b/packages/create-vite/template-react/index.html index b46ab83364e374..79c470191164e9 100644 --- a/packages/create-vite/template-react/index.html +++ b/packages/create-vite/template-react/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + React
diff --git a/packages/create-vite/template-react/package.json b/packages/create-vite/template-react/package.json index b79e9889800e06..e49194201425da 100644 --- a/packages/create-vite/template-react/package.json +++ b/packages/create-vite/template-react/package.json @@ -13,9 +13,9 @@ "react-dom": "^18.1.0" }, "devDependencies": { - "@types/react": "^18.0.9", + "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", "@vitejs/plugin-react": "^1.3.2", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-react/public/vite.svg b/packages/create-vite/template-react/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-react/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-react/src/App.css b/packages/create-vite/template-react/src/App.css index 8da3fde63d9e7d..2c5e2ef5cd1a2e 100644 --- a/packages/create-vite/template-react/src/App.css +++ b/packages/create-vite/template-react/src/App.css @@ -1,34 +1,23 @@ -.App { +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; text-align: center; } -.App-logo { - height: 40vmin; - pointer-events: none; +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; } - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); } - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); } -@keyframes App-logo-spin { +@keyframes logo-spin { from { transform: rotate(0deg); } @@ -37,6 +26,16 @@ } } -button { - font-size: calc(10px + 2vmin); +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; } diff --git a/packages/create-vite/template-react/src/App.jsx b/packages/create-vite/template-react/src/App.jsx index 7d4eb10ff833d1..14be1971f75675 100644 --- a/packages/create-vite/template-react/src/App.jsx +++ b/packages/create-vite/template-react/src/App.jsx @@ -1,5 +1,6 @@ import { useState } from 'react' -import logo from './logo.svg' +import viteLogo from '/vite.svg' +import reactLogo from './assets/react.svg' import './App.css' function App() { @@ -7,37 +8,26 @@ function App() { return (
-
- logo -

Hello Vite + React!

+ +

Vite + React

+
+

- + Edit src/App.jsx and save to test HMR

-

- Edit App.jsx and save to test HMR updates. -

-

- - Learn React - - {' | '} - - Vite Docs - -

-
+
+

+ Click on the Vite and React logos to learn more +

) } diff --git a/packages/create-vite/template-react/src/assets/react.svg b/packages/create-vite/template-react/src/assets/react.svg new file mode 100644 index 00000000000000..6c87de9bb33584 --- /dev/null +++ b/packages/create-vite/template-react/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-react/src/favicon.svg b/packages/create-vite/template-react/src/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-react/src/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-react/src/index.css b/packages/create-vite/template-react/src/index.css index ec2585e8c0bb81..917888c1d1115a 100644 --- a/packages/create-vite/template-react/src/index.css +++ b/packages/create-vite/template-react/src/index.css @@ -1,13 +1,70 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; } -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } } diff --git a/packages/create-vite/template-react/src/logo.svg b/packages/create-vite/template-react/src/logo.svg deleted file mode 100644 index 6b60c1042f58d9..00000000000000 --- a/packages/create-vite/template-react/src/logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/packages/create-vite/template-svelte-ts/index.html b/packages/create-vite/template-svelte-ts/index.html index d2f6839bab176c..b5b125269662aa 100644 --- a/packages/create-vite/template-svelte-ts/index.html +++ b/packages/create-vite/template-svelte-ts/index.html @@ -2,9 +2,9 @@ - + - Svelte + TS + Vite App + Vite + Svelte + TS
diff --git a/packages/create-vite/template-svelte-ts/package.json b/packages/create-vite/template-svelte-ts/package.json index 53a4c5ea8e01a0..35754a8efcd2e1 100644 --- a/packages/create-vite/template-svelte-ts/package.json +++ b/packages/create-vite/template-svelte-ts/package.json @@ -10,13 +10,13 @@ "check": "svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^1.0.0-next.46", + "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", "@tsconfig/svelte": "^3.0.0", "svelte": "^3.48.0", - "svelte-check": "^2.7.1", - "svelte-preprocess": "^4.10.6", + "svelte-check": "^2.7.2", + "svelte-preprocess": "^4.10.7", "tslib": "^2.4.0", "typescript": "^4.6.4", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-svelte-ts/public/favicon.ico b/packages/create-vite/template-svelte-ts/public/favicon.ico deleted file mode 100644 index d75d248ef0b150..00000000000000 Binary files a/packages/create-vite/template-svelte-ts/public/favicon.ico and /dev/null differ diff --git a/packages/create-vite/template-svelte-ts/public/vite.svg b/packages/create-vite/template-svelte-ts/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-svelte-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-svelte-ts/src/App.svelte b/packages/create-vite/template-svelte-ts/src/App.svelte index 4023b8b9774246..480e1d072d5a2e 100644 --- a/packages/create-vite/template-svelte-ts/src/App.svelte +++ b/packages/create-vite/template-svelte-ts/src/App.svelte @@ -1,65 +1,46 @@
- Svelte Logo -

Hello Typescript!

- - + +

Vite + Svelte

+ +
+ +

- Visit svelte.dev to learn how to build Svelte - apps. + Check out SvelteKit, the official Svelte app framework powered by Vite!

-

- Check out SvelteKit for - the officially supported framework, also powered by Vite! +

+ Click on the Vite and Svelte logos to learn more

+ \ No newline at end of file diff --git a/packages/create-vite/template-svelte-ts/src/app.css b/packages/create-vite/template-svelte-ts/src/app.css new file mode 100644 index 00000000000000..bcc7233dd1ca85 --- /dev/null +++ b/packages/create-vite/template-svelte-ts/src/app.css @@ -0,0 +1,81 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/create-vite/template-svelte-ts/src/assets/svelte.png b/packages/create-vite/template-svelte-ts/src/assets/svelte.png deleted file mode 100644 index e673c91c7bcb0e..00000000000000 Binary files a/packages/create-vite/template-svelte-ts/src/assets/svelte.png and /dev/null differ diff --git a/packages/create-vite/template-svelte-ts/src/assets/svelte.svg b/packages/create-vite/template-svelte-ts/src/assets/svelte.svg new file mode 100644 index 00000000000000..c5e08481f8aede --- /dev/null +++ b/packages/create-vite/template-svelte-ts/src/assets/svelte.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-svelte-ts/src/lib/Counter.svelte b/packages/create-vite/template-svelte-ts/src/lib/Counter.svelte index b8e7524c2232aa..979b4dfc91c86e 100644 --- a/packages/create-vite/template-svelte-ts/src/lib/Counter.svelte +++ b/packages/create-vite/template-svelte-ts/src/lib/Counter.svelte @@ -6,29 +6,5 @@ - - diff --git a/packages/create-vite/template-svelte-ts/src/main.ts b/packages/create-vite/template-svelte-ts/src/main.ts index d8200ac4fe3078..5c1f795f9f55a6 100644 --- a/packages/create-vite/template-svelte-ts/src/main.ts +++ b/packages/create-vite/template-svelte-ts/src/main.ts @@ -1,3 +1,4 @@ +import './app.css' import App from './App.svelte' const app = new App({ diff --git a/packages/create-vite/template-svelte/index.html b/packages/create-vite/template-svelte/index.html index 4a3886b62cf793..26c29c45b2689e 100644 --- a/packages/create-vite/template-svelte/index.html +++ b/packages/create-vite/template-svelte/index.html @@ -2,9 +2,9 @@ - + - Svelte + Vite App + Vite + Svelte
diff --git a/packages/create-vite/template-svelte/package.json b/packages/create-vite/template-svelte/package.json index 5d469f55d796b9..7b4bb4e615b5a7 100644 --- a/packages/create-vite/template-svelte/package.json +++ b/packages/create-vite/template-svelte/package.json @@ -9,8 +9,8 @@ "preview": "vite preview" }, "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^1.0.0-next.46", + "@sveltejs/vite-plugin-svelte": "^1.0.0-next.49", "svelte": "^3.48.0", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-svelte/public/favicon.ico b/packages/create-vite/template-svelte/public/favicon.ico deleted file mode 100644 index d75d248ef0b150..00000000000000 Binary files a/packages/create-vite/template-svelte/public/favicon.ico and /dev/null differ diff --git a/packages/create-vite/template-svelte/public/vite.svg b/packages/create-vite/template-svelte/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-svelte/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-svelte/src/App.svelte b/packages/create-vite/template-svelte/src/App.svelte index 90ca0665a7416a..b2eb01b52ac2de 100644 --- a/packages/create-vite/template-svelte/src/App.svelte +++ b/packages/create-vite/template-svelte/src/App.svelte @@ -1,65 +1,46 @@
- Svelte Logo -

Hello world!

- - + +

Vite + Svelte

+ +
+ +

- Visit svelte.dev to learn how to build Svelte - apps. + Check out SvelteKit, the official Svelte app framework powered by Vite!

-

- Check out SvelteKit for - the officially supported framework, also powered by Vite! +

+ Click on the Vite and Svelte logos to learn more

diff --git a/packages/create-vite/template-svelte/src/app.css b/packages/create-vite/template-svelte/src/app.css new file mode 100644 index 00000000000000..bcc7233dd1ca85 --- /dev/null +++ b/packages/create-vite/template-svelte/src/app.css @@ -0,0 +1,81 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/create-vite/template-svelte/src/assets/svelte.png b/packages/create-vite/template-svelte/src/assets/svelte.png deleted file mode 100644 index e673c91c7bcb0e..00000000000000 Binary files a/packages/create-vite/template-svelte/src/assets/svelte.png and /dev/null differ diff --git a/packages/create-vite/template-svelte/src/assets/svelte.svg b/packages/create-vite/template-svelte/src/assets/svelte.svg new file mode 100644 index 00000000000000..c5e08481f8aede --- /dev/null +++ b/packages/create-vite/template-svelte/src/assets/svelte.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-svelte/src/lib/Counter.svelte b/packages/create-vite/template-svelte/src/lib/Counter.svelte index 37a92cbf4bbd10..e45f903109790d 100644 --- a/packages/create-vite/template-svelte/src/lib/Counter.svelte +++ b/packages/create-vite/template-svelte/src/lib/Counter.svelte @@ -6,29 +6,5 @@ - - diff --git a/packages/create-vite/template-svelte/src/main.js b/packages/create-vite/template-svelte/src/main.js index d8200ac4fe3078..5c1f795f9f55a6 100644 --- a/packages/create-vite/template-svelte/src/main.js +++ b/packages/create-vite/template-svelte/src/main.js @@ -1,3 +1,4 @@ +import './app.css' import App from './App.svelte' const app = new App({ diff --git a/packages/create-vite/template-vanilla-ts/index.html b/packages/create-vite/template-vanilla-ts/index.html index 867581c5124fa1..f86e483c942e8d 100644 --- a/packages/create-vite/template-vanilla-ts/index.html +++ b/packages/create-vite/template-vanilla-ts/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + TS
diff --git a/packages/create-vite/template-vanilla-ts/package.json b/packages/create-vite/template-vanilla-ts/package.json index ff74d1a70ac3aa..d1df1e67eeb8b6 100644 --- a/packages/create-vite/template-vanilla-ts/package.json +++ b/packages/create-vite/template-vanilla-ts/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "typescript": "^4.6.4", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-vanilla-ts/public/vite.svg b/packages/create-vite/template-vanilla-ts/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-vanilla-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vanilla-ts/src/counter.ts b/packages/create-vite/template-vanilla-ts/src/counter.ts new file mode 100644 index 00000000000000..a3529e1f26bfc8 --- /dev/null +++ b/packages/create-vite/template-vanilla-ts/src/counter.ts @@ -0,0 +1,9 @@ +export function setupCounter(element: HTMLButtonElement) { + let counter = 0 + const setCounter = (count: number) => { + counter = count + element.innerHTML = `count is ${counter}` + } + element.addEventListener('click', () => setCounter(++counter)) + setCounter(0) +} diff --git a/packages/create-vite/template-vanilla-ts/src/main.ts b/packages/create-vite/template-vanilla-ts/src/main.ts index f77db7a8fcab13..b4a91405cdee25 100644 --- a/packages/create-vite/template-vanilla-ts/src/main.ts +++ b/packages/create-vite/template-vanilla-ts/src/main.ts @@ -1,8 +1,24 @@ import './style.css' +import viteLogo from '/vite.svg' +import typescriptLogo from './typescript.svg' +import { setupCounter } from './counter' -const app = document.querySelector('#app')! - -app.innerHTML = ` -

Hello Vite!

- Documentation +document.querySelector('#app')!.innerHTML = ` +
+ + + + + + +

Vite + TypeScript

+
+ +
+

+ Click on the Vite and TypeScript logos to learn more +

+
` + +setupCounter(document.querySelector('#counter')!) diff --git a/packages/create-vite/template-vanilla-ts/src/style.css b/packages/create-vite/template-vanilla-ts/src/style.css index 852de7aa2ae573..12320801d3635d 100644 --- a/packages/create-vite/template-vanilla-ts/src/style.css +++ b/packages/create-vite/template-vanilla-ts/src/style.css @@ -1,8 +1,97 @@ -#app { - font-family: Avenir, Helvetica, Arial, sans-serif; +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; text-align: center; - color: #2c3e50; - margin-top: 60px; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.vanilla:hover { + filter: drop-shadow(0 0 2em #f7df1eaa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } } diff --git a/packages/create-vite/template-vanilla-ts/src/typescript.svg b/packages/create-vite/template-vanilla-ts/src/typescript.svg new file mode 100644 index 00000000000000..d91c910cc30bf4 --- /dev/null +++ b/packages/create-vite/template-vanilla-ts/src/typescript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vanilla/counter.js b/packages/create-vite/template-vanilla/counter.js new file mode 100644 index 00000000000000..12ae65abfaea09 --- /dev/null +++ b/packages/create-vite/template-vanilla/counter.js @@ -0,0 +1,9 @@ +export function setupCounter(element) { + let counter = 0 + const setCounter = (count) => { + counter = count + element.innerHTML = `count is ${counter}` + } + element.addEventListener('click', () => setCounter(++counter)) + setCounter(0) +} diff --git a/packages/create-vite/template-vanilla/favicon.svg b/packages/create-vite/template-vanilla/favicon.svg deleted file mode 100644 index de4aeddc12bdfe..00000000000000 --- a/packages/create-vite/template-vanilla/favicon.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/packages/create-vite/template-vanilla/index.html b/packages/create-vite/template-vanilla/index.html index f1dedb52dba233..2ad7b1ab9e691d 100644 --- a/packages/create-vite/template-vanilla/index.html +++ b/packages/create-vite/template-vanilla/index.html @@ -2,7 +2,7 @@ - + Vite App diff --git a/packages/create-vite/template-vanilla/javascript.svg b/packages/create-vite/template-vanilla/javascript.svg new file mode 100644 index 00000000000000..f9abb2b728d73b --- /dev/null +++ b/packages/create-vite/template-vanilla/javascript.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vanilla/main.js b/packages/create-vite/template-vanilla/main.js index 4c0070f03c7ba0..bbdb9004d5f3d8 100644 --- a/packages/create-vite/template-vanilla/main.js +++ b/packages/create-vite/template-vanilla/main.js @@ -1,6 +1,24 @@ import './style.css' +import viteLogo from '/vite.svg' +import javascriptLogo from './javascript.svg' +import { setupCounter } from './counter.js' document.querySelector('#app').innerHTML = ` -

Hello Vite!

- Documentation +
+ + + + + + +

Hello Vite!

+
+ +
+

+ Click on the Vite logo to learn more +

+
` + +setupCounter(document.querySelector('#counter')) diff --git a/packages/create-vite/template-vanilla/package.json b/packages/create-vite/template-vanilla/package.json index 470ae1e4770149..52837e6d7c0ecc 100644 --- a/packages/create-vite/template-vanilla/package.json +++ b/packages/create-vite/template-vanilla/package.json @@ -9,6 +9,6 @@ "preview": "vite preview" }, "devDependencies": { - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-vanilla/public/vite.svg b/packages/create-vite/template-vanilla/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-vanilla/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vanilla/style.css b/packages/create-vite/template-vanilla/style.css index 852de7aa2ae573..12320801d3635d 100644 --- a/packages/create-vite/template-vanilla/style.css +++ b/packages/create-vite/template-vanilla/style.css @@ -1,8 +1,97 @@ -#app { - font-family: Avenir, Helvetica, Arial, sans-serif; +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; text-align: center; - color: #2c3e50; - margin-top: 60px; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.vanilla:hover { + filter: drop-shadow(0 0 2em #f7df1eaa); +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } } diff --git a/packages/create-vite/template-vue-ts/index.html b/packages/create-vite/template-vue-ts/index.html index 11603f878f1226..143557b5286bc1 100644 --- a/packages/create-vite/template-vue-ts/index.html +++ b/packages/create-vite/template-vue-ts/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + Vue + TS
diff --git a/packages/create-vite/template-vue-ts/package.json b/packages/create-vite/template-vue-ts/package.json index 5f352e2519aa25..208f8126f74c7a 100644 --- a/packages/create-vite/template-vue-ts/package.json +++ b/packages/create-vite/template-vue-ts/package.json @@ -9,12 +9,12 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.2.36" + "vue": "^3.2.37" }, "devDependencies": { "@vitejs/plugin-vue": "^2.3.3", "typescript": "^4.6.4", - "vite": "^2.9.9", - "vue-tsc": "^0.35.2" + "vite": "^2.9.12", + "vue-tsc": "^0.37.5" } } diff --git a/packages/create-vite/template-vue-ts/public/favicon.ico b/packages/create-vite/template-vue-ts/public/favicon.ico deleted file mode 100644 index df36fcfb72584e..00000000000000 Binary files a/packages/create-vite/template-vue-ts/public/favicon.ico and /dev/null differ diff --git a/packages/create-vite/template-vue-ts/public/vite.svg b/packages/create-vite/template-vue-ts/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-vue-ts/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vue-ts/src/App.vue b/packages/create-vite/template-vue-ts/src/App.vue index 1503baf999e683..76ebf08602f448 100644 --- a/packages/create-vite/template-vue-ts/src/App.vue +++ b/packages/create-vite/template-vue-ts/src/App.vue @@ -5,17 +5,27 @@ import HelloWorld from './components/HelloWorld.vue' - diff --git a/packages/create-vite/template-vue-ts/src/assets/logo.png b/packages/create-vite/template-vue-ts/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b..00000000000000 Binary files a/packages/create-vite/template-vue-ts/src/assets/logo.png and /dev/null differ diff --git a/packages/create-vite/template-vue-ts/src/assets/vue.svg b/packages/create-vite/template-vue-ts/src/assets/vue.svg new file mode 100644 index 00000000000000..770e9d333ee70e --- /dev/null +++ b/packages/create-vite/template-vue-ts/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue b/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue index 38dae70739a15a..5230910336b442 100644 --- a/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue +++ b/packages/create-vite/template-vue-ts/src/components/HelloWorld.vue @@ -9,44 +9,30 @@ const count = ref(0) diff --git a/packages/create-vite/template-vue-ts/src/main.ts b/packages/create-vite/template-vue-ts/src/main.ts index 01433bca2ac765..2425c0f745bef4 100644 --- a/packages/create-vite/template-vue-ts/src/main.ts +++ b/packages/create-vite/template-vue-ts/src/main.ts @@ -1,4 +1,5 @@ import { createApp } from 'vue' +import './style.css' import App from './App.vue' createApp(App).mount('#app') diff --git a/packages/create-vite/template-vue-ts/src/style.css b/packages/create-vite/template-vue-ts/src/style.css new file mode 100644 index 00000000000000..0192f9aac987dc --- /dev/null +++ b/packages/create-vite/template-vue-ts/src/style.css @@ -0,0 +1,81 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/create-vite/template-vue/index.html b/packages/create-vite/template-vue/index.html index 030a6ff51bfc6f..795e4fbadb8831 100644 --- a/packages/create-vite/template-vue/index.html +++ b/packages/create-vite/template-vue/index.html @@ -2,9 +2,9 @@ - + - Vite App + Vite + Vue
diff --git a/packages/create-vite/template-vue/package.json b/packages/create-vite/template-vue/package.json index c519cb36270f61..f2f7dee1baaf9d 100644 --- a/packages/create-vite/template-vue/package.json +++ b/packages/create-vite/template-vue/package.json @@ -9,10 +9,10 @@ "preview": "vite preview" }, "dependencies": { - "vue": "^3.2.36" + "vue": "^3.2.37" }, "devDependencies": { "@vitejs/plugin-vue": "^2.3.3", - "vite": "^2.9.9" + "vite": "^2.9.12" } } diff --git a/packages/create-vite/template-vue/public/favicon.ico b/packages/create-vite/template-vue/public/favicon.ico deleted file mode 100644 index df36fcfb72584e..00000000000000 Binary files a/packages/create-vite/template-vue/public/favicon.ico and /dev/null differ diff --git a/packages/create-vite/template-vue/public/vite.svg b/packages/create-vite/template-vue/public/vite.svg new file mode 100644 index 00000000000000..e7b8dfb1b2a60b --- /dev/null +++ b/packages/create-vite/template-vue/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vue/src/App.vue b/packages/create-vite/template-vue/src/App.vue index 09bbb6a561285f..6febdb7581ea83 100644 --- a/packages/create-vite/template-vue/src/App.vue +++ b/packages/create-vite/template-vue/src/App.vue @@ -5,17 +5,27 @@ import HelloWorld from './components/HelloWorld.vue' - diff --git a/packages/create-vite/template-vue/src/assets/logo.png b/packages/create-vite/template-vue/src/assets/logo.png deleted file mode 100644 index f3d2503fc2a44b..00000000000000 Binary files a/packages/create-vite/template-vue/src/assets/logo.png and /dev/null differ diff --git a/packages/create-vite/template-vue/src/assets/vue.svg b/packages/create-vite/template-vue/src/assets/vue.svg new file mode 100644 index 00000000000000..770e9d333ee70e --- /dev/null +++ b/packages/create-vite/template-vue/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/create-vite/template-vue/src/components/HelloWorld.vue b/packages/create-vite/template-vue/src/components/HelloWorld.vue index aa607e31e0ad7c..91f9bfcbcb305d 100644 --- a/packages/create-vite/template-vue/src/components/HelloWorld.vue +++ b/packages/create-vite/template-vue/src/components/HelloWorld.vue @@ -11,30 +11,30 @@ const count = ref(0) diff --git a/packages/create-vite/template-vue/src/main.js b/packages/create-vite/template-vue/src/main.js index 01433bca2ac765..2425c0f745bef4 100644 --- a/packages/create-vite/template-vue/src/main.js +++ b/packages/create-vite/template-vue/src/main.js @@ -1,4 +1,5 @@ import { createApp } from 'vue' +import './style.css' import App from './App.vue' createApp(App).mount('#app') diff --git a/packages/create-vite/template-vue/src/style.css b/packages/create-vite/template-vue/src/style.css new file mode 100644 index 00000000000000..a566a347d0d5ee --- /dev/null +++ b/packages/create-vite/template-vue/src/style.css @@ -0,0 +1,90 @@ +:root { + font-family: Inter, Avenir, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 24px; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +.card { + padding: 2em; +} + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/plugin-legacy/README.md b/packages/plugin-legacy/README.md index f7cd62b4dbe15c..4cec856f95d7af 100644 --- a/packages/plugin-legacy/README.md +++ b/packages/plugin-legacy/README.md @@ -27,6 +27,12 @@ export default { } ``` +Terser must be installed because plugin-legacy uses Terser for minification. + +```sh +npm add -D terser +``` + ## Options ### `targets` diff --git a/packages/plugin-legacy/package.json b/packages/plugin-legacy/package.json index 3321c4de7815c7..9f854eb34d4228 100644 --- a/packages/plugin-legacy/package.json +++ b/packages/plugin-legacy/package.json @@ -35,17 +35,18 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme", "dependencies": { - "@babel/standalone": "^7.18.4", - "core-js": "^3.22.7", + "@babel/standalone": "^7.18.5", + "core-js": "^3.22.8", "magic-string": "^0.26.2", "regenerator-runtime": "^0.13.9", "systemjs": "^6.12.1" }, "peerDependencies": { + "terser": "^5.4.0", "vite": "^3.0.0-alpha" }, "devDependencies": { - "vite": "workspace:*", - "@babel/core": "^7.18.2" + "@babel/core": "^7.18.5", + "vite": "workspace:*" } } diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts index 4aaab1aab2412d..0c9fb1c8c68d33 100644 --- a/packages/plugin-legacy/src/index.ts +++ b/packages/plugin-legacy/src/index.ts @@ -134,7 +134,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { config.build, 'es', opts, - options.externalSystemJS + true ) return } @@ -566,7 +566,7 @@ async function buildPolyfillChunk( buildOptions: BuildOptions, format: 'iife' | 'es', rollupOutputOptions: NormalizedOutputOptions, - externalSystemJS?: boolean + excludeSystemJS?: boolean ) { let { minify, assetsDir } = buildOptions minify = minify ? 'terser' : false @@ -575,7 +575,7 @@ async function buildPolyfillChunk( root: path.dirname(fileURLToPath(import.meta.url)), configFile: false, logLevel: 'error', - plugins: [polyfillsPlugin(imports, externalSystemJS)], + plugins: [polyfillsPlugin(imports, excludeSystemJS)], build: { write: false, target: false, @@ -614,7 +614,7 @@ const polyfillId = '\0vite/legacy-polyfills' function polyfillsPlugin( imports: Set, - externalSystemJS?: boolean + excludeSystemJS?: boolean ): Plugin { return { name: 'vite:legacy-polyfills', @@ -627,7 +627,7 @@ function polyfillsPlugin( if (id === polyfillId) { return ( [...imports].map((i) => `import "${i}";`).join('') + - (externalSystemJS ? '' : `import "systemjs/dist/s.min.js";`) + (excludeSystemJS ? '' : `import "systemjs/dist/s.min.js";`) ) } } diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index d5f0d5195e707a..2690d9fb85a4f1 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.0.0-alpha.3 (2022-06-12) + +* fix(deps): update all non-major dependencies (#8391) ([842f995](https://github.com/vitejs/vite/commit/842f995)), closes [#8391](https://github.com/vitejs/vite/issues/8391) +* fix(plugin-react): apply manual runtime interop (#8546) ([f09299c](https://github.com/vitejs/vite/commit/f09299c)), closes [#8546](https://github.com/vitejs/vite/issues/8546) +* fix(plugin-react): support import namespace in `parseReactAlias` (#5313) ([05b91cd](https://github.com/vitejs/vite/commit/05b91cd)), closes [#5313](https://github.com/vitejs/vite/issues/5313) +* refactor: remove hooks ssr param support (#8491) ([f59adf8](https://github.com/vitejs/vite/commit/f59adf8)), closes [#8491](https://github.com/vitejs/vite/issues/8491) + + + ## 2.0.0-alpha.2 (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/plugin-react/package.json b/packages/plugin-react/package.json index 25ab4a39d72044..40cf3e60d72d6a 100644 --- a/packages/plugin-react/package.json +++ b/packages/plugin-react/package.json @@ -1,6 +1,6 @@ { "name": "@vitejs/plugin-react", - "version": "2.0.0-alpha.2", + "version": "2.0.0-alpha.3", "license": "MIT", "author": "Evan You", "contributors": [ @@ -39,14 +39,12 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-react#readme", "dependencies": { - "@babel/core": "^7.18.2", + "@babel/core": "^7.18.5", "@babel/plugin-transform-react-jsx": "^7.17.12", "@babel/plugin-transform-react-jsx-development": "^7.16.7", "@babel/plugin-transform-react-jsx-self": "^7.17.12", "@babel/plugin-transform-react-jsx-source": "^7.16.7", - "@rollup/pluginutils": "^4.2.1", - "react-refresh": "^0.13.0", - "resolve": "^1.22.0" + "react-refresh": "^0.13.0" }, "peerDependencies": { "vite": "^3.0.0-alpha" diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 562b8291112297..77ce68a630f631 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -1,8 +1,7 @@ import path from 'path' import type { ParserOptions, TransformOptions, types as t } from '@babel/core' import * as babel from '@babel/core' -import { createFilter } from '@rollup/pluginutils' -import { normalizePath } from 'vite' +import { createFilter, normalizePath } from 'vite' import type { Plugin, PluginOption, ResolvedConfig } from 'vite' import { addRefreshWrapper, @@ -165,7 +164,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] { } }, async transform(code, id, options) { - const ssr = typeof options === 'boolean' ? options : options?.ssr === true + const ssr = options?.ssr === true // File extension could be mocked/overridden in querystring. const [filepath, querystring = ''] = id.split('?') const [extension = ''] = @@ -361,7 +360,10 @@ export default function viteReact(opts: Options = {}): PluginOption[] { } } - // const runtimeId = 'react/jsx-runtime' + const reactJsxRuntimeId = 'react/jsx-runtime' + const reactJsxDevRuntimeId = 'react/jsx-dev-runtime' + const virtualReactJsxRuntimeId = '\0' + reactJsxRuntimeId + const virtualReactJsxDevRuntimeId = '\0' + reactJsxDevRuntimeId // Adapted from https://github.com/alloc/vite-react-jsx const viteReactJsx: Plugin = { name: 'vite:react-jsx', @@ -369,32 +371,42 @@ export default function viteReact(opts: Options = {}): PluginOption[] { config() { return { optimizeDeps: { - include: ['react/jsx-dev-runtime'] + include: [reactJsxRuntimeId, reactJsxDevRuntimeId] } } - } - // TODO: this optimization may not be necesary and it is breacking esbuild+rollup compat, - // see https://github.com/vitejs/vite/pull/7246#discussion_r861552185 - // We could still do the same trick and resolve to the optimized dependency here - /* - resolveId(id: string) { - return id === runtimeId ? id : null - }, - load(id: string) { - if (id === runtimeId) { - const runtimePath = resolve.sync(runtimeId, { - basedir: projectRoot - }) - const exports = ['jsx', 'jsxs', 'Fragment'] + }, + resolveId(id, importer) { + // Resolve runtime to a virtual path to be interoped. + // Since the interop code re-imports `id`, we need to prevent re-resolving + // to the virtual id if the importer is already the virtual id. + if (id === reactJsxRuntimeId && importer !== virtualReactJsxRuntimeId) { + return virtualReactJsxRuntimeId + } + if ( + id === reactJsxDevRuntimeId && + importer !== virtualReactJsxDevRuntimeId + ) { + return virtualReactJsxDevRuntimeId + } + }, + load(id) { + // Apply manual interop + if (id === virtualReactJsxRuntimeId) { return [ - `import * as jsxRuntime from ${JSON.stringify(runtimePath)}`, - // We can't use `export * from` or else any callsite that uses - // this module will be compiled to `jsxRuntime.exports.jsx` - // instead of the more concise `jsx` alias. - ...exports.map((name) => `export const ${name} = jsxRuntime.${name}`) + `import * as jsxRuntime from ${JSON.stringify(reactJsxRuntimeId)}`, + `export const Fragment = jsxRuntime.Fragment`, + `export const jsx = jsxRuntime.jsx`, + `export const jsxs = jsxRuntime.jsxs` ].join('\n') } - } */ + if (id === virtualReactJsxDevRuntimeId) { + return [ + `import * as jsxRuntime from ${JSON.stringify(reactJsxDevRuntimeId)}`, + `export const Fragment = jsxRuntime.Fragment`, + `export const jsxDEV = jsxRuntime.jsxDEV` + ].join('\n') + } + } } return [viteBabel, viteReactRefresh, useAutomaticRuntime && viteReactJsx] diff --git a/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts b/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts index fcad0f78c3373b..7d5b14bfc9cfd4 100644 --- a/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts +++ b/packages/plugin-react/src/jsx-runtime/restore-jsx.spec.ts @@ -1,6 +1,67 @@ import * as babel from '@babel/core' import { describe, expect, it } from 'vitest' -import { restoreJSX } from './restore-jsx' +import { parseReactAlias, restoreJSX } from './restore-jsx' + +describe('parseReactAlias', () => { + it('handles cjs require', () => { + expect(parseReactAlias(`const React = require("react")`)) + .toMatchInlineSnapshot(` + [ + "React", + true, + ] + `) + }) + + it('handles cjs require (minified)', () => { + expect(parseReactAlias(`var F=require('foo');var R=require('react')`)) + .toMatchInlineSnapshot(` + [ + "R", + true, + ] + `) + }) + + it('does not handle destructured cjs require', () => { + expect(parseReactAlias(`var {createElement} = require("react")`)) + .toMatchInlineSnapshot(` + [ + undefined, + false, + ] + `) + }) + + it('handles esm import', () => { + expect(parseReactAlias(`import React from 'react'`)).toMatchInlineSnapshot(` + [ + "React", + false, + ] + `) + }) + + it('handles esm import namespace', () => { + expect(parseReactAlias(`import * as React from "react"`)) + .toMatchInlineSnapshot(` + [ + "React", + false, + ] + `) + }) + + it('does not handle destructured esm import', () => { + expect(parseReactAlias(`import {createElement} from "react"`)) + .toMatchInlineSnapshot(` + [ + undefined, + false, + ] + `) + }) +}) async function jsx(sourceCode: string) { const [ast] = await restoreJSX(babel, sourceCode, 'test.js') diff --git a/packages/plugin-react/src/jsx-runtime/restore-jsx.ts b/packages/plugin-react/src/jsx-runtime/restore-jsx.ts index 4acb6bb64f5e1b..d67a54e8f08aad 100644 --- a/packages/plugin-react/src/jsx-runtime/restore-jsx.ts +++ b/packages/plugin-react/src/jsx-runtime/restore-jsx.ts @@ -79,16 +79,16 @@ export async function restoreJSX( return [result?.ast, isCommonJS] } -function parseReactAlias( +export function parseReactAlias( code: string ): [alias: string | undefined, isCommonJS: boolean] { let match = code.match( - /\b(var|let|const) +(\w+) *= *require\(["']react["']\)/ + /\b(var|let|const)\s+([^=\{\s]+)\s*=\s*require\(["']react["']\)/ ) if (match) { return [match[2], true] } - match = code.match(/^import (\w+).+? from ["']react["']/m) + match = code.match(/^import\s+(?:\*\s+as\s+)?(\w+).+?\bfrom\s*["']react["']/m) if (match) { return [match[1], false] } diff --git a/packages/plugin-vue-jsx/README.md b/packages/plugin-vue-jsx/README.md index f6159cf3a82cab..c75e6d786f67b6 100644 --- a/packages/plugin-vue-jsx/README.md +++ b/packages/plugin-vue-jsx/README.md @@ -17,7 +17,23 @@ export default { ## Options -See [@vue/babel-plugin-jsx](https://github.com/vuejs/jsx-next). +### include + +Type: `(string | RegExp)[] | string | RegExp | null` + +Default: `/\.[jt]sx$/` + +A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patterns, which specifies the files the plugin should operate on. + +### exclude + +Type: `(string | RegExp)[] | string | RegExp | null` + +Default: `undefined` + +A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patterns, which specifies the files to be ignored by the plugin. + +> See [@vue/babel-plugin-jsx](https://github.com/vuejs/jsx-next) for other options. ## HMR Detection diff --git a/packages/plugin-vue-jsx/package.json b/packages/plugin-vue-jsx/package.json index 1e345081113256..e4e483dda373f6 100644 --- a/packages/plugin-vue-jsx/package.json +++ b/packages/plugin-vue-jsx/package.json @@ -35,10 +35,9 @@ }, "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-vue-jsx#readme", "dependencies": { - "@babel/core": "^7.18.2", + "@babel/core": "^7.18.5", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-transform-typescript": "^7.18.4", - "@rollup/pluginutils": "^4.2.1", "@vue/babel-plugin-jsx": "^1.1.1" }, "devDependencies": { diff --git a/packages/plugin-vue-jsx/src/index.ts b/packages/plugin-vue-jsx/src/index.ts index 302cb323849ad6..48de3da46448ce 100644 --- a/packages/plugin-vue-jsx/src/index.ts +++ b/packages/plugin-vue-jsx/src/index.ts @@ -5,7 +5,7 @@ import * as babel from '@babel/core' import jsx from '@vue/babel-plugin-jsx' // @ts-expect-error missing type import importMeta from '@babel/plugin-syntax-import-meta' -import { createFilter, normalizePath } from '@rollup/pluginutils' +import { createFilter, normalizePath } from 'vite' import type { ComponentOptions } from 'vue' import type { Plugin } from 'vite' import type { Options } from './types' @@ -74,7 +74,7 @@ function vueJsxPlugin(options: Options = {}): Plugin { }, async transform(code, id, opt) { - const ssr = typeof opt === 'boolean' ? opt : (opt && opt.ssr) === true + const ssr = opt?.ssr === true const { include, exclude, diff --git a/packages/plugin-vue-jsx/src/types.ts b/packages/plugin-vue-jsx/src/types.ts index aa30b7435329f4..a3be580859ea00 100644 --- a/packages/plugin-vue-jsx/src/types.ts +++ b/packages/plugin-vue-jsx/src/types.ts @@ -1,5 +1,5 @@ import type { VueJSXPluginOptions } from '@vue/babel-plugin-jsx' -import type { FilterPattern } from '@rollup/pluginutils' +import type { FilterPattern } from 'vite' export interface FilterOptions { include?: FilterPattern diff --git a/packages/plugin-vue/package.json b/packages/plugin-vue/package.json index 999cda6486ad9f..7a5195fbf36703 100644 --- a/packages/plugin-vue/package.json +++ b/packages/plugin-vue/package.json @@ -42,13 +42,10 @@ "@jridgewell/gen-mapping": "^0.3.1", "@jridgewell/trace-mapping": "^0.3.13", "debug": "^4.3.4", - "rollup": "^2.72.1", + "rollup": "^2.75.6", "slash": "^4.0.0", "source-map": "^0.6.1", "vite": "workspace:*", - "vue": "^3.2.36" - }, - "dependencies": { - "@rollup/pluginutils": "^4.2.1" + "vue": "^3.2.37" } } diff --git a/packages/plugin-vue/src/index.ts b/packages/plugin-vue/src/index.ts index 805df6fec674d0..3e1b2c3be1b7f5 100644 --- a/packages/plugin-vue/src/index.ts +++ b/packages/plugin-vue/src/index.ts @@ -1,6 +1,6 @@ import fs from 'fs' import type { Plugin, ViteDevServer } from 'vite' -import { createFilter } from '@rollup/pluginutils' +import { createFilter } from 'vite' /* eslint-disable import/no-duplicates */ import type { SFCBlock, @@ -107,14 +107,6 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { devToolsEnabled: process.env.NODE_ENV !== 'production' } - // Temporal handling for 2.7 breaking change - const isSSR = (opt: { ssr?: boolean } | boolean | undefined) => - opt === undefined - ? false - : typeof opt === 'boolean' - ? opt - : opt?.ssr === true - return { name: 'vite:vue', @@ -169,7 +161,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { }, load(id, opt) { - const ssr = isSSR(opt) + const ssr = opt?.ssr === true if (id === EXPORT_HELPER_ID) { return helperCode } @@ -202,7 +194,7 @@ export default function vuePlugin(rawOptions: Options = {}): Plugin { }, transform(code, id, opt) { - const ssr = isSSR(opt) + const ssr = opt?.ssr === true const { filename, query } = parseVueRequest(id) if (query.raw) { return diff --git a/packages/plugin-vue/src/main.ts b/packages/plugin-vue/src/main.ts index be11de7e33a23a..e92c48673a680e 100644 --- a/packages/plugin-vue/src/main.ts +++ b/packages/plugin-vue/src/main.ts @@ -1,13 +1,12 @@ import path from 'path' import type { SFCBlock, SFCDescriptor } from 'vue/compiler-sfc' -import type { PluginContext, SourceMap, TransformPluginContext } from 'rollup' -import { normalizePath } from '@rollup/pluginutils' +import type { PluginContext, TransformPluginContext } from 'rollup' import type { RawSourceMap } from 'source-map' import type { EncodedSourceMap as TraceEncodedSourceMap } from '@jridgewell/trace-mapping' import { TraceMap, eachMapping } from '@jridgewell/trace-mapping' import type { EncodedSourceMap as GenEncodedSourceMap } from '@jridgewell/gen-mapping' import { addMapping, fromMap, toEncodedMap } from '@jridgewell/gen-mapping' -import { transformWithEsbuild } from 'vite' +import { normalizePath, transformWithEsbuild } from 'vite' import { createDescriptor, getPrevDescriptor, @@ -47,7 +46,7 @@ export async function transformMain( const hasScoped = descriptor.styles.some((s) => s.scoped) // script - const { code: scriptCode, map } = await genScriptCode( + const { code: scriptCode, map: scriptMap } = await genScriptCode( descriptor, options, pluginContext, @@ -59,7 +58,7 @@ export async function transformMain( descriptor.template && !isUseInlineTemplate(descriptor, !devServer) let templateCode = '' - let templateMap: RawSourceMap | undefined + let templateMap: RawSourceMap | undefined = undefined if (hasTemplateImport) { ;({ code: templateCode, map: templateMap } = await genTemplateCode( descriptor, @@ -157,40 +156,46 @@ export async function transformMain( ) } - // if the template is inlined into the main module (indicated by the presence - // of templateMap, we need to concatenate the two source maps. - let resolvedMap = options.sourceMap ? map : undefined - if (resolvedMap && templateMap) { - const gen = fromMap( - // version property of result.map is declared as string - // but actually it is `3` - map as Omit as TraceEncodedSourceMap - ) - const tracer = new TraceMap( - // same above - templateMap as Omit as TraceEncodedSourceMap - ) - const offset = (scriptCode.match(/\r?\n/g)?.length ?? 0) + 1 - eachMapping(tracer, (m) => { - if (m.source == null) return - addMapping(gen, { - source: m.source, - original: { line: m.originalLine, column: m.originalColumn }, - generated: { - line: m.generatedLine + offset, - column: m.generatedColumn - } + let resolvedMap: RawSourceMap | undefined = undefined + if (options.sourceMap) { + if (scriptMap && templateMap) { + // if the template is inlined into the main module (indicated by the presence + // of templateMap, we need to concatenate the two source maps. + + const gen = fromMap( + // version property of result.map is declared as string + // but actually it is `3` + scriptMap as Omit as TraceEncodedSourceMap + ) + const tracer = new TraceMap( + // same above + templateMap as Omit as TraceEncodedSourceMap + ) + const offset = (scriptCode.match(/\r?\n/g)?.length ?? 0) + 1 + eachMapping(tracer, (m) => { + if (m.source == null) return + addMapping(gen, { + source: m.source, + original: { line: m.originalLine, column: m.originalColumn }, + generated: { + line: m.generatedLine + offset, + column: m.generatedColumn + } + }) }) - }) - // same above - resolvedMap = toEncodedMap(gen) as Omit< - GenEncodedSourceMap, - 'version' - > as RawSourceMap - // if this is a template only update, we will be reusing a cached version - // of the main module compile result, which has outdated sourcesContent. - resolvedMap.sourcesContent = templateMap.sourcesContent + // same above + resolvedMap = toEncodedMap(gen) as Omit< + GenEncodedSourceMap, + 'version' + > as RawSourceMap + // if this is a template only update, we will be reusing a cached version + // of the main module compile result, which has outdated sourcesContent. + resolvedMap.sourcesContent = templateMap.sourcesContent + } else { + // if one of `scriptMap` and `templateMap` is empty, use the other one + resolvedMap = scriptMap ?? templateMap + } } if (!attachedProps.length) { @@ -288,10 +293,10 @@ async function genScriptCode( ssr: boolean ): Promise<{ code: string - map: RawSourceMap + map: RawSourceMap | undefined }> { let scriptCode = `const _sfc_main = {}` - let map: RawSourceMap | SourceMap | undefined + let map: RawSourceMap | undefined const script = resolveScript(descriptor, options, ssr) if (script) { @@ -323,7 +328,7 @@ async function genScriptCode( } return { code: scriptCode, - map: map as any + map } } diff --git a/packages/vite/CHANGELOG.md b/packages/vite/CHANGELOG.md index 7711aee6dc3b1f..03b7be90f66c65 100644 --- a/packages/vite/CHANGELOG.md +++ b/packages/vite/CHANGELOG.md @@ -1,3 +1,59 @@ +## 3.0.0-alpha.12 (2022-06-16) + +* chore: correct typo in console message (#8618) ([13d05bd](https://github.com/vitejs/vite/commit/13d05bd)), closes [#8618](https://github.com/vitejs/vite/issues/8618) +* chore: enable eslint and prettier cache (#8585) ([d7beaeb](https://github.com/vitejs/vite/commit/d7beaeb)), closes [#8585](https://github.com/vitejs/vite/issues/8585) +* chore: tweak server start output (#8582) ([3439132](https://github.com/vitejs/vite/commit/3439132)), closes [#8582](https://github.com/vitejs/vite/issues/8582) +* fix: allow cache overlap in parallel builds (#8592) ([2dd0b49](https://github.com/vitejs/vite/commit/2dd0b49)), closes [#8592](https://github.com/vitejs/vite/issues/8592) +* fix: avoid replacing defines and NODE_ENV in optimized deps (fix #8593) (#8606) ([739175b](https://github.com/vitejs/vite/commit/739175b)), closes [#8593](https://github.com/vitejs/vite/issues/8593) [#8606](https://github.com/vitejs/vite/issues/8606) +* fix: sequential injection of tags in transformIndexHtml (#5851) (#6901) ([649c7f6](https://github.com/vitejs/vite/commit/649c7f6)), closes [#5851](https://github.com/vitejs/vite/issues/5851) [#6901](https://github.com/vitejs/vite/issues/6901) +* fix(asset): respect assetFileNames if rollupOptions.output is an array (#8561) ([4e6c26f](https://github.com/vitejs/vite/commit/4e6c26f)), closes [#8561](https://github.com/vitejs/vite/issues/8561) +* fix(css): escape pattern chars from base path in postcss dir-dependency messages (#7081) ([5151e74](https://github.com/vitejs/vite/commit/5151e74)), closes [#7081](https://github.com/vitejs/vite/issues/7081) +* fix(optimizer): browser mapping for yarn pnp (#6493) ([c1c7af3](https://github.com/vitejs/vite/commit/c1c7af3)), closes [#6493](https://github.com/vitejs/vite/issues/6493) +* feat: 500 response if the node proxy request fails (#7398) ([73e1775](https://github.com/vitejs/vite/commit/73e1775)), closes [#7398](https://github.com/vitejs/vite/issues/7398) +* docs: worker related notes (#8554) ([c0c5e1a](https://github.com/vitejs/vite/commit/c0c5e1a)), closes [#8554](https://github.com/vitejs/vite/issues/8554) + + + +## 3.0.0-alpha.11 (2022-06-14) + +* fix: add missed JPEG file extensions to `KNOWN_ASSET_TYPES` (#8565) ([2dfc015](https://github.com/vitejs/vite/commit/2dfc015)), closes [#8565](https://github.com/vitejs/vite/issues/8565) +* fix: default export module transformation for vitest spy (#8567) ([d357e33](https://github.com/vitejs/vite/commit/d357e33)), closes [#8567](https://github.com/vitejs/vite/issues/8567) +* fix: default host to `localhost` instead of `127.0.0.1` (#8543) ([49c0896](https://github.com/vitejs/vite/commit/49c0896)), closes [#8543](https://github.com/vitejs/vite/issues/8543) +* fix: dont handle sigterm in middleware mode (#8550) ([c6f43dd](https://github.com/vitejs/vite/commit/c6f43dd)), closes [#8550](https://github.com/vitejs/vite/issues/8550) +* fix: mime missing extensions (#8568) ([acf3024](https://github.com/vitejs/vite/commit/acf3024)), closes [#8568](https://github.com/vitejs/vite/issues/8568) +* fix: objurl for type module, and concurrent tests (#8541) ([26ecd5a](https://github.com/vitejs/vite/commit/26ecd5a)), closes [#8541](https://github.com/vitejs/vite/issues/8541) +* fix: outdated optimized dep removed from module graph (#8533) ([3f4d22d](https://github.com/vitejs/vite/commit/3f4d22d)), closes [#8533](https://github.com/vitejs/vite/issues/8533) +* fix(config): only rewrite .js loader in `loadConfigFromBundledFile` (#8556) ([2548dd3](https://github.com/vitejs/vite/commit/2548dd3)), closes [#8556](https://github.com/vitejs/vite/issues/8556) +* fix(deps): update all non-major dependencies (#8558) ([9a1fd4c](https://github.com/vitejs/vite/commit/9a1fd4c)), closes [#8558](https://github.com/vitejs/vite/issues/8558) +* fix(ssr): dont replace rollup input (#7275) ([9a88afa](https://github.com/vitejs/vite/commit/9a88afa)), closes [#7275](https://github.com/vitejs/vite/issues/7275) +* chore: include 2.9.10-2.9.12 changelog in main (#8535) ([87f58ad](https://github.com/vitejs/vite/commit/87f58ad)), closes [#8535](https://github.com/vitejs/vite/issues/8535) +* chore: refactor interop named imports (#8544) ([63b523a](https://github.com/vitejs/vite/commit/63b523a)), closes [#8544](https://github.com/vitejs/vite/issues/8544) +* chore: remove rollup `namespaceToStringTag` (#8569) ([b85802a](https://github.com/vitejs/vite/commit/b85802a)), closes [#8569](https://github.com/vitejs/vite/issues/8569) +* chore: remove unused timestamp option (#8545) ([d641860](https://github.com/vitejs/vite/commit/d641860)), closes [#8545](https://github.com/vitejs/vite/issues/8545) +* chore: update major deps (#8572) ([0e20949](https://github.com/vitejs/vite/commit/0e20949)), closes [#8572](https://github.com/vitejs/vite/issues/8572) +* feat: expose createFilter util (#8562) ([c5c424a](https://github.com/vitejs/vite/commit/c5c424a)), closes [#8562](https://github.com/vitejs/vite/issues/8562) + + + +## 3.0.0-alpha.10 (2022-06-10) + +* fix: deps optimizer idle logic for workers (fix #8479) (#8511) ([1e05548](https://github.com/vitejs/vite/commit/1e05548)), closes [#8479](https://github.com/vitejs/vite/issues/8479) [#8511](https://github.com/vitejs/vite/issues/8511) +* fix: not match \n when injecting esbuild helpers (#8414) ([5a57626](https://github.com/vitejs/vite/commit/5a57626)), closes [#8414](https://github.com/vitejs/vite/issues/8414) +* fix: respect optimize deps entries (#8489) ([fba82d0](https://github.com/vitejs/vite/commit/fba82d0)), closes [#8489](https://github.com/vitejs/vite/issues/8489) +* fix(optimizer): encode `_` and `.` in different way (#8508) ([9065b37](https://github.com/vitejs/vite/commit/9065b37)), closes [#8508](https://github.com/vitejs/vite/issues/8508) +* fix(optimizer): external require-import conversion (fixes #2492, #3409) (#8459) ([1061bbd](https://github.com/vitejs/vite/commit/1061bbd)), closes [#2492](https://github.com/vitejs/vite/issues/2492) [#3409](https://github.com/vitejs/vite/issues/3409) [#8459](https://github.com/vitejs/vite/issues/8459) +* feat: better config `__dirname` support (#8442) ([51e9195](https://github.com/vitejs/vite/commit/51e9195)), closes [#8442](https://github.com/vitejs/vite/issues/8442) +* feat: expose `version` (#8456) ([e992594](https://github.com/vitejs/vite/commit/e992594)), closes [#8456](https://github.com/vitejs/vite/issues/8456) +* feat: handle named imports of builtin modules (#8338) ([e2e44ff](https://github.com/vitejs/vite/commit/e2e44ff)), closes [#8338](https://github.com/vitejs/vite/issues/8338) +* feat: preserve process env vars in lib build (#8090) ([908c9e4](https://github.com/vitejs/vite/commit/908c9e4)), closes [#8090](https://github.com/vitejs/vite/issues/8090) +* refactor!: make terser an optional dependency (#8049) ([164f528](https://github.com/vitejs/vite/commit/164f528)), closes [#8049](https://github.com/vitejs/vite/issues/8049) +* chore: generate vite sourcemap when not production (#8453) ([129b499](https://github.com/vitejs/vite/commit/129b499)), closes [#8453](https://github.com/vitejs/vite/issues/8453) +* chore: resolve ssr options (#8455) ([d97e402](https://github.com/vitejs/vite/commit/d97e402)), closes [#8455](https://github.com/vitejs/vite/issues/8455) +* chore(deps): update all non-major dependencies (#8474) ([6d0ede7](https://github.com/vitejs/vite/commit/6d0ede7)), closes [#8474](https://github.com/vitejs/vite/issues/8474) +* perf: disable postcss sourcemap when unused (#8451) ([64fc61c](https://github.com/vitejs/vite/commit/64fc61c)), closes [#8451](https://github.com/vitejs/vite/issues/8451) + + + ## 3.0.0-alpha.9 (2022-06-01) * fix: make array `acornInjectPlugins` work (fixes #8410) (#8415) ([08d594b](https://github.com/vitejs/vite/commit/08d594b)), closes [#8410](https://github.com/vitejs/vite/issues/8410) [#8415](https://github.com/vitejs/vite/issues/8415) @@ -69,11 +125,9 @@ * fix: correctly replace process.env.NODE_ENV (#8283) ([ec52baa](https://github.com/vitejs/vite/commit/ec52baa)), closes [#8283](https://github.com/vitejs/vite/issues/8283) * fix: dev sourcemap (#8269) ([505f75e](https://github.com/vitejs/vite/commit/505f75e)), closes [#8269](https://github.com/vitejs/vite/issues/8269) -* fix: EPERM error on Windows when processing dependencies (#8235) ([67743a3](https://github.com/vitejs/vite/commit/67743a3)), closes [#8235](https://github.com/vitejs/vite/issues/8235) * fix: glob types (#8257) ([03b227e](https://github.com/vitejs/vite/commit/03b227e)), closes [#8257](https://github.com/vitejs/vite/issues/8257) * fix: srcset handling in html (#6419) ([a0ee4ff](https://github.com/vitejs/vite/commit/a0ee4ff)), closes [#6419](https://github.com/vitejs/vite/issues/6419) * fix: support set NODE_ENV in scripts when custom mode option (#8218) ([adcf041](https://github.com/vitejs/vite/commit/adcf041)), closes [#8218](https://github.com/vitejs/vite/issues/8218) -* fix(css): remove `?used` hack (fixes #6421, #8245) (#8278) ([0b25cc1](https://github.com/vitejs/vite/commit/0b25cc1)), closes [#6421](https://github.com/vitejs/vite/issues/6421) [#8245](https://github.com/vitejs/vite/issues/8245) [#8278](https://github.com/vitejs/vite/issues/8278) * fix(hmr): catch thrown errors when connecting to hmr websocket (#7111) ([4bc9284](https://github.com/vitejs/vite/commit/4bc9284)), closes [#7111](https://github.com/vitejs/vite/issues/7111) * fix(plugin-legacy): respect `entryFileNames` for polyfill chunks (#8247) ([baa9632](https://github.com/vitejs/vite/commit/baa9632)), closes [#8247](https://github.com/vitejs/vite/issues/8247) * fix(plugin-react): broken optimized deps dir check (#8255) ([9e2a1ea](https://github.com/vitejs/vite/commit/9e2a1ea)), closes [#8255](https://github.com/vitejs/vite/issues/8255) @@ -106,9 +160,7 @@ * feat: allow any JS identifier in define, not ASCII-only (#5972) ([95eb45b](https://github.com/vitejs/vite/commit/95eb45b)), closes [#5972](https://github.com/vitejs/vite/issues/5972) * feat: enable `generatedCode: 'es2015'` for rollup build (#5018) ([46d5e67](https://github.com/vitejs/vite/commit/46d5e67)), closes [#5018](https://github.com/vitejs/vite/issues/5018) -* feat: new hook `configurePreviewServer` (#7658) ([20ea999](https://github.com/vitejs/vite/commit/20ea999)), closes [#7658](https://github.com/vitejs/vite/issues/7658) * feat: rework `dynamic-import-vars` (#7756) ([80d113b](https://github.com/vitejs/vite/commit/80d113b)), closes [#7756](https://github.com/vitejs/vite/issues/7756) -* feat: treat Astro file scripts as TS (#8151) ([559c952](https://github.com/vitejs/vite/commit/559c952)), closes [#8151](https://github.com/vitejs/vite/issues/8151) * feat: worker emit fileName with config (#7804) ([04c2edd](https://github.com/vitejs/vite/commit/04c2edd)), closes [#7804](https://github.com/vitejs/vite/issues/7804) * feat(glob-import): support `{ import: '*' }` (#8071) ([0b78b2a](https://github.com/vitejs/vite/commit/0b78b2a)), closes [#8071](https://github.com/vitejs/vite/issues/8071) * fix: add hash to lib chunk names (#7190) ([c81cedf](https://github.com/vitejs/vite/commit/c81cedf)), closes [#7190](https://github.com/vitejs/vite/issues/7190) @@ -146,7 +198,6 @@ * chore: using Unicode instead of unicode in doc and tests (#6852) ([c2bf62b](https://github.com/vitejs/vite/commit/c2bf62b)), closes [#6852](https://github.com/vitejs/vite/issues/6852) * chore(deps): update tsconfck to 2.0.0 built for node14+ (#8144) ([0513d13](https://github.com/vitejs/vite/commit/0513d13)), closes [#8144](https://github.com/vitejs/vite/issues/8144) * chore(deps): use `esno` to replace `ts-node` (#8152) ([2363bd3](https://github.com/vitejs/vite/commit/2363bd3)), closes [#8152](https://github.com/vitejs/vite/issues/8152) -* chore(lint): sort for imports (#8113) ([43a58dd](https://github.com/vitejs/vite/commit/43a58dd)), closes [#8113](https://github.com/vitejs/vite/issues/8113) * build!: remove node v12 support (#7833) ([eeac2d2](https://github.com/vitejs/vite/commit/eeac2d2)), closes [#7833](https://github.com/vitejs/vite/issues/7833) * feat!: rework `import.meta.glob` (#7537) ([330e0a9](https://github.com/vitejs/vite/commit/330e0a9)), closes [#7537](https://github.com/vitejs/vite/issues/7537) * feat!: vite dev default port is now 5173 (#8148) ([1cc2e2d](https://github.com/vitejs/vite/commit/1cc2e2d)), closes [#8148](https://github.com/vitejs/vite/issues/8148) @@ -158,6 +209,30 @@ +## 2.9.12 (2022-06-10) + +* fix: outdated optimized dep removed from module graph (#8534) ([c0d6c60](https://github.com/vitejs/vite/commit/c0d6c60)), closes [#8534](https://github.com/vitejs/vite/issues/8534) + + + +## 2.9.11 (2022-06-10) + +* fix: respect server.headers in static middlewares (#8481) ([ab7dc1c](https://github.com/vitejs/vite/commit/ab7dc1c)), closes [#8481](https://github.com/vitejs/vite/issues/8481) +* fix(dev): avoid FOUC when swapping out link tag (fix #7973) (#8495) ([01fa807](https://github.com/vitejs/vite/commit/01fa807)), closes [#7973](https://github.com/vitejs/vite/issues/7973) [#8495](https://github.com/vitejs/vite/issues/8495) + + + +## 2.9.10 (2022-06-06) + +* feat: treat Astro file scripts as TS (#8151) ([9fdd0a3](https://github.com/vitejs/vite/commit/9fdd0a3)), closes [#8151](https://github.com/vitejs/vite/issues/8151) +* feat: new hook `configurePreviewServer` (#7658) (#8437) ([7b972bc](https://github.com/vitejs/vite/commit/7b972bc)), closes [#7658](https://github.com/vitejs/vite/issues/7658) [#8437](https://github.com/vitejs/vite/issues/8437) +* fix: remove empty chunk css imports when using esnext (#8345) ([9fbc1a9](https://github.com/vitejs/vite/commit/9fbc1a9)), closes [#8345](https://github.com/vitejs/vite/issues/8345) +* fix: EPERM error on Windows when processing dependencies (#8235) ([dfe4307](https://github.com/vitejs/vite/commit/dfe4307)), closes [#8235](https://github.com/vitejs/vite/issues/8235) +* fix(css): remove `?used` hack (fixes #6421, #8245) (#8278) (#8471) ([8d7bac4](https://github.com/vitejs/vite/commit/8d7bac4)), closes [#6421](https://github.com/vitejs/vite/issues/6421) [#8245](https://github.com/vitejs/vite/issues/8245) [#8278](https://github.com/vitejs/vite/issues/8278) [#8471](https://github.com/vitejs/vite/issues/8471) +* chore(lint): sort for imports (#8113) ([4bd1531](https://github.com/vitejs/vite/commit/4bd1531)), closes [#8113](https://github.com/vitejs/vite/issues/8113) + + + ## 2.9.9 (2022-05-11) * fix: add direct query to html-proxy css (fixes #8091) (#8094) ([a24b5e3](https://github.com/vitejs/vite/commit/a24b5e3)), closes [#8091](https://github.com/vitejs/vite/issues/8091) [#8094](https://github.com/vitejs/vite/issues/8094) diff --git a/packages/vite/LICENSE.md b/packages/vite/LICENSE.md index e65a09826f0f4a..995c28ad9fad20 100644 --- a/packages/vite/LICENSE.md +++ b/packages/vite/LICENSE.md @@ -535,6 +535,28 @@ License: MIT By: Rich Harris Repository: rollup/plugins +> The MIT License (MIT) +> +> Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors) +> +> Permission is hereby granted, free of charge, to any person obtaining a copy +> of this software and associated documentation files (the "Software"), to deal +> in the Software without restriction, including without limitation the rights +> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +> copies of the Software, and to permit persons to whom the Software is +> furnished to do so, subject to the following conditions: +> +> The above copyright notice and this permission notice shall be included in +> all copies or substantial portions of the Software. +> +> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +> THE SOFTWARE. + --------------------------------------- ## @vue/compiler-core @@ -660,7 +682,7 @@ Repository: chalk/ansi-regex > MIT License > -> Copyright (c) Sindre Sorhus (sindresorhus.com) +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) > > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > @@ -3455,7 +3477,7 @@ Repository: chalk/strip-ansi > MIT License > -> Copyright (c) Sindre Sorhus (sindresorhus.com) +> Copyright (c) Sindre Sorhus (https://sindresorhus.com) > > Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: > @@ -3832,7 +3854,7 @@ License: ISC By: Eemeli Aro Repository: github:eemeli/yaml -> Copyright 2018 Eemeli Aro +> Copyright Eemeli Aro > > Permission to use, copy, modify, and/or distribute this software for any purpose > with or without fee is hereby granted, provided that the above copyright notice diff --git a/packages/vite/client.d.ts b/packages/vite/client.d.ts index 948d66d1d7ad74..e99b4a526b7a58 100644 --- a/packages/vite/client.d.ts +++ b/packages/vite/client.d.ts @@ -74,6 +74,18 @@ declare module '*.jpeg' { const src: string export default src } +declare module '*.jfif' { + const src: string + export default src +} +declare module '*.pjpeg' { + const src: string + export default src +} +declare module '*.pjp' { + const src: string + export default src +} declare module '*.png' { const src: string export default src diff --git a/packages/vite/package.json b/packages/vite/package.json index 3b20f0e566d28b..805d6485d53acd 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "vite", - "version": "3.0.0-alpha.9", + "version": "3.0.0-alpha.12", "type": "module", "license": "MIT", "author": "Evan You", @@ -20,10 +20,7 @@ "./client": { "types": "./client.d.ts" }, - "./dist/client/*": "./dist/client/*", - "./terser": { - "require": "./dist/node-cjs/terser.cjs" - } + "./dist/client/*": "./dist/client/*" }, "files": [ "bin", @@ -54,23 +51,23 @@ "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\"", + "lint": "eslint --cache --ext .ts src/**", + "format": "prettier --write --cache --parser typescript \"src/**/*.ts\"", "prepublishOnly": "npm run build" }, "//": "READ CONTRIBUTING.md to understand what to put under deps vs. devDeps!", "dependencies": { - "esbuild": "^0.14.38", + "esbuild": "^0.14.43", "postcss": "^8.4.14", "resolve": "^1.22.0", - "rollup": "^2.72.1" + "rollup": "^2.75.6" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "devDependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/parser": "^7.18.4", + "@babel/parser": "^7.18.5", "@babel/types": "^7.18.4", "@jridgewell/trace-mapping": "^0.3.13", "@rollup/plugin-alias": "^3.1.9", @@ -78,11 +75,11 @@ "@rollup/plugin-dynamic-import-vars": "^1.4.3", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "13.3.0", - "@rollup/plugin-typescript": "^8.3.2", + "@rollup/plugin-typescript": "^8.3.3", "@rollup/pluginutils": "^4.2.1", - "@vue/compiler-dom": "^3.2.36", + "@vue/compiler-dom": "^3.2.37", "acorn": "^8.7.1", - "cac": "6.7.9", + "cac": "^6.7.12", "chokidar": "^3.5.3", "connect": "^3.7.0", "connect-history-api-fallback": "^1.6.0", @@ -94,7 +91,7 @@ "dotenv-expand": "^5.1.0", "es-module-lexer": "^0.10.5", "esno": "^0.16.3", - "estree-walker": "^2.0.2", + "estree-walker": "^3.0.1", "etag": "^1.8.1", "fast-glob": "^3.2.11", "http-proxy": "^1.18.1", @@ -102,33 +99,33 @@ "launch-editor-middleware": "^2.4.0", "magic-string": "^0.26.2", "micromatch": "^4.0.5", - "mrmime": "^1.0.0", + "mrmime": "^1.0.1", "node-forge": "^1.3.1", "okie": "^1.0.1", "open": "^8.4.0", - "periscopic": "^2.0.3", + "periscopic": "^3.0.4", "picocolors": "^1.0.0", "postcss-import": "^14.1.0", - "postcss-load-config": "^3.1.4", + "postcss-load-config": "^4.0.1", "postcss-modules": "^4.3.1", "resolve.exports": "^1.1.0", - "rollup-plugin-license": "^2.8.0", + "rollup-plugin-license": "^2.8.1", "sirv": "^2.0.2", "source-map-js": "^1.0.2", "source-map-support": "^0.5.21", - "strip-ansi": "^6.0.1", + "strip-ansi": "^7.0.1", "strip-literal": "^0.3.0", - "terser": "^5.14.0", "tsconfck": "^2.0.1", "tslib": "^2.4.0", "types": "link:./types", "ufo": "^0.8.4", - "ws": "^8.7.0" + "ws": "^8.8.0" }, "peerDependencies": { "less": "*", "sass": "*", - "stylus": "*" + "stylus": "*", + "terser": "^5.4.0" }, "peerDependenciesMeta": { "sass": { @@ -139,6 +136,9 @@ }, "less": { "optional": true + }, + "terser": { + "optional": true } } } diff --git a/packages/vite/rollup.config.ts b/packages/vite/rollup.config.ts index 6759ede01d14c2..0e321956a0d287 100644 --- a/packages/vite/rollup.config.ts +++ b/packages/vite/rollup.config.ts @@ -118,20 +118,11 @@ function createNodePlugins( // Shim them with eval() so rollup can skip these calls. isProduction && shimDepsPlugin({ - 'plugins/terser.ts': { - src: `require.resolve('terser'`, - replacement: `require.resolve('vite/terser'` - }, // chokidar -> fsevents 'fsevents-handler.js': { src: `require('fsevents')`, replacement: `__require('fsevents')` }, - // cac re-assigns module.exports even in its mjs dist - 'cac/dist/index.mjs': { - src: `if (typeof module !== "undefined") {`, - replacement: `if (false) {` - }, // postcss-import -> sugarss 'process-content.js': { src: 'require("sugarss")', @@ -183,7 +174,7 @@ function createNodeConfig(isProduction: boolean) { ], plugins: createNodePlugins( isProduction, - false, + !isProduction, // in production we use api-extractor for dts generation // in development we need to rely on the rollup ts plugin isProduction ? false : path.resolve(__dirname, 'dist/node') @@ -191,27 +182,6 @@ function createNodeConfig(isProduction: boolean) { }) } -/** - * Terser needs to be run inside a worker, so it cannot be part of the main - * bundle. We produce a separate bundle for it and shims plugin/terser.ts to - * use the production path during build. - */ -const terserConfig = defineConfig({ - ...sharedNodeOptions, - output: { - ...sharedNodeOptions.output, - entryFileNames: `node-cjs/[name].cjs`, - exports: 'default', - format: 'cjs', - sourcemap: false - }, - input: { - // eslint-disable-next-line node/no-restricted-require - terser: require.resolve('terser') - }, - plugins: [nodeResolve(), commonjs()] -}) - function createCjsConfig(isProduction: boolean) { return defineConfig({ ...sharedNodeOptions, @@ -233,7 +203,7 @@ function createCjsConfig(isProduction: boolean) { ...Object.keys(pkg.dependencies), ...(isProduction ? [] : Object.keys(pkg.devDependencies)) ], - plugins: [...createNodePlugins(false, false, false), bundleSizeLimit(55)] + plugins: [...createNodePlugins(false, false, false), bundleSizeLimit(120)] }) } @@ -245,8 +215,7 @@ export default (commandLineArgs: any) => { envConfig, clientConfig, createNodeConfig(isProduction), - createCjsConfig(isProduction), - ...(isProduction ? [terserConfig] : []) + createCjsConfig(isProduction) ]) } diff --git a/packages/vite/src/client/client.ts b/packages/vite/src/client/client.ts index 5aec1eae9c5bc0..8f39164e05a774 100644 --- a/packages/vite/src/client/client.ts +++ b/packages/vite/src/client/client.ts @@ -101,7 +101,18 @@ async function handleMessage(payload: HMRPayload) { const newPath = `${base}${searchUrl.slice(1)}${ searchUrl.includes('?') ? '&' : '?' }t=${timestamp}` - el.href = new URL(newPath, el.href).href + + // rather than swapping the href on the existing tag, we will + // create a new link tag. Once the new stylesheet has loaded we + // will remove the existing link tag. This removes a Flash Of + // Unstyled Content that can occur when swapping out the tag href + // directly, as the new stylesheet has not yet been loaded. + const newLinkTag = el.cloneNode() as HTMLLinkElement + newLinkTag.href = new URL(newPath, el.href).href + const removeOldEl = () => el.remove() + newLinkTag.addEventListener('load', removeOldEl) + newLinkTag.addEventListener('error', removeOldEl) + el.after(newLinkTag) } console.log(`[vite] css hot updated: ${searchUrl}`) } diff --git a/packages/vite/src/node/__tests__/utils.spec.ts b/packages/vite/src/node/__tests__/utils.spec.ts index c8a824bbb3d28f..5a6ea4d55de30c 100644 --- a/packages/vite/src/node/__tests__/utils.spec.ts +++ b/packages/vite/src/node/__tests__/utils.spec.ts @@ -49,9 +49,9 @@ describe('injectQuery', () => { }) describe('resolveHostname', () => { - test('defaults to 127.0.0.1', () => { + test('defaults to localhost', () => { expect(resolveHostname(undefined)).toEqual({ - host: '127.0.0.1', + host: 'localhost', name: 'localhost' }) }) @@ -62,6 +62,27 @@ describe('resolveHostname', () => { name: 'localhost' }) }) + + test('accepts 0.0.0.0', () => { + expect(resolveHostname('0.0.0.0')).toEqual({ + host: '0.0.0.0', + name: 'localhost' + }) + }) + + test('accepts ::', () => { + expect(resolveHostname('::')).toEqual({ + host: '::', + name: 'localhost' + }) + }) + + test('accepts 0000:0000:0000:0000:0000:0000:0000:0000', () => { + expect(resolveHostname('0000:0000:0000:0000:0000:0000:0000:0000')).toEqual({ + host: '0000:0000:0000:0000:0000:0000:0000:0000', + name: 'localhost' + }) + }) }) test('ts import of file with .js extension', () => { diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 705465400ca5ca..c3d59d88a0549b 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -407,7 +407,6 @@ async function doBuild( } const rollupOptions: RollupOptions = { - input, context: 'globalThis', preserveEntrySignatures: ssr ? 'allow-extension' @@ -415,6 +414,7 @@ async function doBuild( ? 'strict' : false, ...options.rollupOptions, + input, plugins, external, onwarn(warning, warn) { @@ -460,6 +460,9 @@ async function doBuild( exports: cjsSsrBuild ? 'named' : 'auto', sourcemap: options.sourcemap, name: libOptions ? libOptions.name : undefined, + // es2015 enables `generatedCode.symbols` + // - #764 add `Symbol.toStringTag` when build es module into cjs chunk + // - #1048 add `Symbol.toStringTag` for module default export generatedCode: 'es2015', entryFileNames: ssr ? `[name].${jsExt}` @@ -472,9 +475,6 @@ async function doBuild( assetFileNames: libOptions ? `[name].[ext]` : path.posix.join(options.assetsDir, `[name].[hash].[ext]`), - // #764 add `Symbol.toStringTag` when build es module into cjs chunk - // #1048 add `Symbol.toStringTag` for module default export - namespaceToStringTag: true, inlineDynamicImports: output.format === 'umd' || output.format === 'iife' || diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index b7f90c162fd475..c8ede65abfd2b4 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -5,7 +5,6 @@ import { performance } from 'perf_hooks' import { createRequire } from 'module' import colors from 'picocolors' import type { Alias, AliasOptions } from 'types/alias' -import { createFilter } from '@rollup/pluginutils' import aliasPlugin from '@rollup/plugin-alias' import { build } from 'esbuild' import type { RollupOptions } from 'rollup' @@ -19,6 +18,7 @@ import { resolvePreviewOptions } from './preview' import type { CSSOptions } from './plugins/css' import { createDebugger, + createFilter, dynamicImport, isExternalUrl, isObject, @@ -41,6 +41,8 @@ import type { PluginContainer } from './server/pluginContainer' import { createPluginContainer } from './server/pluginContainer' import type { PackageCache } from './packages' import { loadEnv, resolveEnvPrefix } from './env' +import type { ResolvedSSROptions, SSROptions } from './ssr' +import { resolveSSROptions } from './ssr' const debug = createDebugger('vite:config') @@ -236,29 +238,6 @@ export interface ExperimentalOptions { importGlobRestoreExtension?: boolean } -export type SSRTarget = 'node' | 'webworker' - -export type SSRFormat = 'esm' | 'cjs' - -export interface SSROptions { - external?: string[] - noExternal?: string | RegExp | (string | RegExp)[] | true - /** - * Define the target for the ssr build. The browser field in package.json - * is ignored for node but used if webworker is the target - * Default: 'node' - */ - target?: SSRTarget - /** - * Define the format for the ssr build. Since Vite v3 the SSR build generates ESM by default. - * `'cjs'` can be selected to generate a CJS build, but it isn't recommended. This option is - * left marked as experimental to give users more time to update to ESM. CJS builds requires - * complex externalization heuristics that aren't present in the ESM format. - * @experimental - */ - format?: SSRFormat -} - export interface ResolveWorkerOptions { format: 'es' | 'iife' plugins: Plugin[] @@ -282,6 +261,7 @@ export type ResolvedConfig = Readonly< command: 'build' | 'serve' mode: string isWorker: boolean + // in nested worker bundle to find the main config /** @internal */ mainConfig: ResolvedConfig | null isProduction: boolean @@ -293,6 +273,7 @@ export type ResolvedConfig = Readonly< server: ResolvedServerOptions build: ResolvedBuildOptions preview: ResolvedPreviewOptions + ssr: ResolvedSSROptions | undefined assetsInclude: (file: string) => boolean logger: Logger createResolver: (options?: Partial) => ResolveFn @@ -499,6 +480,7 @@ export async function resolveConfig( : '' const server = resolveServerOptions(resolvedRoot, config.server, logger) + const ssr = resolveSSROptions(config.ssr) const optimizeDeps = config.optimizeDeps || {} @@ -516,6 +498,7 @@ export async function resolveConfig( cacheDir, command, mode, + ssr, isWorker: false, mainConfig: null, isProduction, @@ -550,7 +533,9 @@ export async function resolveConfig( : 'spa' } - // flat config.worker.plugin + // Some plugins that aren't intended to work in the bundling of workers (doing post-processing at build time for example). + // And Plugins may also have cached that could be corrupted by being used in these extra rollup calls. + // So we need to separate the worker plugin from the plugin that vite needs to run. const [workerPrePlugins, workerNormalPlugins, workerPostPlugins] = sortUserPlugins(config.worker?.plugins as Plugin[]) const workerResolved: ResolvedConfig = { @@ -595,6 +580,29 @@ export async function resolveConfig( ) } + // Check if all assetFileNames have the same reference. + // If not, display a warn for user. + const outputOption = config.build?.rollupOptions?.output ?? [] + // Use isArray to narrow its type to array + if (Array.isArray(outputOption)) { + const assetFileNamesList = outputOption.map( + (output) => output.assetFileNames + ) + if (assetFileNamesList.length > 1) { + const firstAssetFileNames = assetFileNamesList[0] + const hasDifferentReference = assetFileNamesList.some( + (assetFileNames) => assetFileNames !== firstAssetFileNames + ) + if (hasDifferentReference) { + resolved.logger.warn( + colors.yellow(` +assetFileNames isn't equal for every build.rollupOptions.output. A single pattern across all outputs is supported by Vite. +`) + ) + } + } + } + return resolved } @@ -801,6 +809,7 @@ async function bundleConfigFile( fileName: string, isESM = false ): Promise<{ code: string; dependencies: string[] }> { + const importMetaUrlVarName = '__vite_injected_original_import_meta_url' const result = await build({ absWorkingDir: process.cwd(), entryPoints: [fileName], @@ -811,6 +820,9 @@ async function bundleConfigFile( format: isESM ? 'esm' : 'cjs', sourcemap: 'inline', metafile: true, + define: { + 'import.meta.url': importMetaUrlVarName + }, plugins: [ { name: 'externalize-deps', @@ -826,22 +838,20 @@ async function bundleConfigFile( } }, { - name: 'replace-import-meta', + name: 'inject-file-scope-variables', setup(build) { build.onLoad({ filter: /\.[jt]s$/ }, async (args) => { const contents = await fs.promises.readFile(args.path, 'utf8') + const injectValues = + `const __dirname = ${JSON.stringify(path.dirname(args.path))};` + + `const __filename = ${JSON.stringify(args.path)};` + + `const ${importMetaUrlVarName} = ${JSON.stringify( + pathToFileURL(args.path).href + )};` + return { loader: args.path.endsWith('.ts') ? 'ts' : 'js', - contents: contents - .replace( - /\bimport\.meta\.url\b/g, - JSON.stringify(pathToFileURL(args.path).href) - ) - .replace( - /\b__dirname\b/g, - JSON.stringify(path.dirname(args.path)) - ) - .replace(/\b__filename\b/g, JSON.stringify(args.path)) + contents: injectValues + contents } }) } @@ -864,10 +874,9 @@ async function loadConfigFromBundledFile( fileName: string, bundledCode: string ): Promise { - const extension = path.extname(fileName) const realFileName = fs.realpathSync(fileName) - const defaultLoader = _require.extensions[extension]! - _require.extensions[extension] = (module: NodeModule, filename: string) => { + const defaultLoader = _require.extensions['.js'] + _require.extensions['.js'] = (module: NodeModule, filename: string) => { if (filename === realFileName) { ;(module as NodeModuleWithCompile)._compile(bundledCode, filename) } else { @@ -877,9 +886,8 @@ async function loadConfigFromBundledFile( // clear cache in case of server restart delete _require.cache[_require.resolve(fileName)] const raw = _require(fileName) - const config = raw.__esModule ? raw.default : raw - _require.extensions[extension] = defaultLoader - return config + _require.extensions['.js'] = defaultLoader + return raw.__esModule ? raw.default : raw } export function isDepsOptimizerEnabled(config: ResolvedConfig): boolean { diff --git a/packages/vite/src/node/constants.ts b/packages/vite/src/node/constants.ts index 4e5d3da96f50da..3b4d496e30bd3c 100644 --- a/packages/vite/src/node/constants.ts +++ b/packages/vite/src/node/constants.ts @@ -62,11 +62,17 @@ export const CLIENT_DIR = path.dirname(CLIENT_ENTRY) // ** READ THIS ** before editing `KNOWN_ASSET_TYPES`. // If you add an asset to `KNOWN_ASSET_TYPES`, make sure to also add it -// to the TypeScript declaration file `packages/vite/client.d.ts`. +// to the TypeScript declaration file `packages/vite/client.d.ts` and +// add a mime type to the `registerCustomMime` in +// `packages/vite/src/node/plugin/assets.ts` if mime type cannot be +// looked up by mrmime. export const KNOWN_ASSET_TYPES = [ // images 'png', 'jpe?g', + 'jfif', + 'pjpeg', + 'pjp', 'gif', 'svg', 'ico', @@ -99,3 +105,15 @@ export const DEFAULT_ASSETS_RE = new RegExp( ) export const DEP_VERSION_RE = /[\?&](v=[\w\.-]+)\b/ + +export const loopbackHosts = new Set([ + 'localhost', + '127.0.0.1', + '::1', + '0000:0000:0000:0000:0000:0000:0000:0001' +]) +export const wildcardHosts = new Set([ + '0.0.0.0', + '::', + '0000:0000:0000:0000:0000:0000:0000:0000' +]) diff --git a/packages/vite/src/node/http.ts b/packages/vite/src/node/http.ts index 2a1c7c920b8ea9..c2757f36477600 100644 --- a/packages/vite/src/node/http.ts +++ b/packages/vite/src/node/http.ts @@ -5,6 +5,7 @@ import type { OutgoingHttpHeaders as HttpServerHeaders } from 'http' import type { ServerOptions as HttpsServerOptions } from 'https' +import { promises as dns } from 'dns' import type { Connect } from 'types/connect' import { isObject } from './utils' import type { ProxyOptions } from './server/middlewares/proxy' @@ -184,9 +185,16 @@ export async function httpServerStart( logger: Logger } ): Promise { - return new Promise((resolve, reject) => { - let { port, strictPort, host, logger } = serverOptions + let { port, strictPort, host, logger } = serverOptions + + // This could be removed when Vite only supports Node 17+ because verbatim=true is default + // https://github.com/nodejs/node/pull/39987 + if (host === 'localhost') { + const addr = await dns.lookup('localhost', { verbatim: true }) + host = addr.address + } + return new Promise((resolve, reject) => { const onError = (e: Error & { code?: string }) => { if (e.code === 'EADDRINUSE') { if (strictPort) { diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index ff8c0ebdf6abab..38952e8a466b62 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -10,6 +10,7 @@ export { resolvePackageData } from './packages' export * from './publicUtils' // additional types +export type { FilterPattern } from './utils' export type { CorsOptions, CorsOrigin, CommonServerOptions } from './http' export type { ViteDevServer, @@ -39,6 +40,12 @@ export type { DepsOptimizer, ExportsData } from './optimizer' +export type { + ResolvedSSROptions, + SSROptions, + SSRFormat, + SSRTarget +} from './ssr' export type { Plugin } from './plugin' export type { PackageCache, PackageData } from './packages' export type { diff --git a/packages/vite/src/node/logger.ts b/packages/vite/src/node/logger.ts index 1176a265a4fcbe..0518d86b271ac7 100644 --- a/packages/vite/src/node/logger.ts +++ b/packages/vite/src/node/logger.ts @@ -8,6 +8,7 @@ import type { RollupError } from 'rollup' import type { CommonServerOptions } from './http' import type { Hostname } from './utils' import { resolveHostname } from './utils' +import { loopbackHosts, wildcardHosts } from './constants' import type { ResolvedConfig } from '.' export type LogType = 'error' | 'warn' | 'info' @@ -172,19 +173,30 @@ function printServerUrls( info: Logger['info'] ): void { const urls: Array<{ label: string; url: string }> = [] + const notes: Array<{ label: string; message: string }> = [] + + if (hostname.host && loopbackHosts.has(hostname.host)) { + let hostnameName = hostname.name + if ( + hostnameName === '::1' || + hostnameName === '0000:0000:0000:0000:0000:0000:0000:0001' + ) { + hostnameName = `[${hostnameName}]` + } - if (hostname.host === '127.0.0.1') { urls.push({ label: 'Local', url: colors.cyan( - `${protocol}://${hostname.name}:${colors.bold(port)}${base}` + `${protocol}://${hostnameName}:${colors.bold(port)}${base}` ) }) - if (hostname.name !== '127.0.0.1') { - urls.push({ - label: 'Network', - url: colors.dim(`use ${colors.white(colors.bold('--host'))} to expose`) + if (hostname.name === 'localhost') { + notes.push({ + label: 'Hint', + message: colors.dim( + `Use ${colors.white(colors.bold('--host'))} to expose to network.` + ) }) } } else { @@ -208,15 +220,34 @@ function printServerUrls( }) } - const length = urls.reduce( - (length, { label }) => Math.max(length, label.length), - 0 + if (!hostname.host || wildcardHosts.has(hostname.host)) { + notes.push({ + label: 'Note', + message: colors.dim( + 'You are using a wildcard host. Ports might be overridden.' + ) + }) + } + + const length = Math.max( + ...[...urls, ...notes].map(({ label }) => label.length) ) - urls.forEach(({ label, url: text }) => { + const print = ( + iconWithColor: string, + label: string, + messageWithColor: string + ) => { info( - ` ${colors.green('➜')} ${colors.bold(label)}: ${' '.repeat( + ` ${iconWithColor} ${colors.bold(label)}: ${' '.repeat( length - label.length - )}${text}` + )}${messageWithColor}` ) + } + + urls.forEach(({ label, url: text }) => { + print(colors.green('➜'), label, text) + }) + notes.forEach(({ label, message: text }) => { + print(colors.white('❖'), label, text) }) } diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index 0c32af75219438..aacabbdf9b1a3c 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -13,6 +13,10 @@ import { import { browserExternalId } from '../plugins/resolve' import type { ExportsData } from '.' +const externalWithConversionNamespace = + 'vite:dep-pre-bundle:external-conversion' +const convertedExternalPrefix = 'vite-dep-pre-bundle-external:' + const externalTypes = [ 'css', // supported pre-processor types @@ -76,24 +80,64 @@ export function esbuildDepPlugin( return resolver(id, _importer, undefined) } + const resolveResult = (id: string, resolved: string) => { + if (resolved.startsWith(browserExternalId)) { + return { + path: id, + namespace: 'browser-external' + } + } + if (isExternalUrl(resolved)) { + return { + path: resolved, + external: true + } + } + return { + path: path.resolve(resolved) + } + } + return { name: 'vite:dep-pre-bundle', setup(build) { // externalize assets and commonly known non-js file types + // See #8459 for more details about this require-import conversion build.onResolve( { filter: new RegExp(`\\.(` + allExternalTypes.join('|') + `)(\\?.*)?$`) }, async ({ path: id, importer, kind }) => { + // if the prefix exist, it is already converted to `import`, so set `external: true` + if (id.startsWith(convertedExternalPrefix)) { + return { + path: id.slice(convertedExternalPrefix.length), + external: true + } + } + const resolved = await resolve(id, importer, kind) if (resolved) { + // here it is not set to `external: true` to convert `require` to `import` return { path: resolved, - external: true + namespace: externalWithConversionNamespace } } } ) + build.onLoad( + { filter: /./, namespace: externalWithConversionNamespace }, + (args) => { + // import itself with prefix (this is the actual part of require-import conversion) + return { + contents: + `export { default } from "${convertedExternalPrefix}${args.path}";` + + `export * from "${convertedExternalPrefix}${args.path}";`, + loader: 'js' + } + } + ) function resolveEntry(id: string) { const flatId = flattenId(id) @@ -130,21 +174,7 @@ export function esbuildDepPlugin( // use vite's own resolver const resolved = await resolve(id, importer, kind) if (resolved) { - if (resolved.startsWith(browserExternalId)) { - return { - path: id, - namespace: 'browser-external' - } - } - if (isExternalUrl(resolved)) { - return { - path: resolved, - external: true - } - } - return { - path: path.resolve(resolved) - } + return resolveResult(id, resolved) } } ) @@ -193,15 +223,43 @@ export function esbuildDepPlugin( build.onLoad( { filter: /.*/, namespace: 'browser-external' }, - ({ path: id }) => { - return { - contents: - `export default new Proxy({}, { - get() { - throw new Error('Module "${id}" has been externalized for ` + - `browser compatibility and cannot be accessed in client code.') + ({ path }) => { + if (config.isProduction) { + return { + contents: 'module.exports = {}' + } + } else { + return { + // Return in CJS to intercept named imports. Use `Object.create` to + // create the Proxy in the prototype to workaround esbuild issue. Why? + // + // In short, esbuild cjs->esm flow: + // 1. Create empty object using `Object.create(Object.getPrototypeOf(module.exports))`. + // 2. Assign props of `module.exports` to the object. + // 3. Return object for ESM use. + // + // If we do `module.exports = new Proxy({}, {})`, step 1 returns empty object, + // step 2 does nothing as there's no props for `module.exports`. The final object + // is just an empty object. + // + // Creating the Proxy in the prototype satisfies step 1 immediately, which means + // the returned object is a Proxy that we can intercept. + // + // Note: Skip keys that are accessed by esbuild and browser devtools. + contents: `\ +module.exports = Object.create(new Proxy({}, { + get(_, key) { + if ( + key !== '__esModule' && + key !== '__proto__' && + key !== 'constructor' && + key !== 'splice' + ) { + throw new Error(\`Module "${path}" has been externalized for browser compatibility. Cannot access "${path}.\${key}" in client code.\`) + } } -})` +}))` + } } } ) @@ -210,11 +268,20 @@ export function esbuildDepPlugin( if (isRunningWithYarnPnp) { build.onResolve( { filter: /.*/ }, - async ({ path, importer, kind, resolveDir }) => ({ - // pass along resolveDir for entries - path: await resolve(path, importer, kind, resolveDir) - }) + async ({ path: id, importer, kind, resolveDir, namespace }) => { + const resolved = await resolve( + id, + importer, + kind, + // pass along resolveDir for entries + namespace === 'dep' ? resolveDir : undefined + ) + if (resolved) { + return resolveResult(id, resolved) + } + } ) + build.onLoad({ filter: /.*/ }, async (args) => ({ contents: await fs.readFile(args.path), loader: 'default' diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index ea291675ccc8cf..b5e3f1d0b13565 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -45,11 +45,18 @@ export type ExportsData = { export interface DepsOptimizer { metadata: DepOptimizationMetadata scanProcessing?: Promise + registerMissingImport: (id: string, resolved: string) => OptimizedDepInfo run: () => void + isOptimizedDepFile: (id: string) => boolean isOptimizedDepUrl: (url: string) => boolean getOptimizedDepId: (depInfo: OptimizedDepInfo) => string + + delayDepsOptimizerUntil: (id: string, done: () => Promise) => void + registerWorkersSource: (id: string) => void + resetRegisteredIds: () => void + options: DepOptimizationOptions } @@ -378,6 +385,7 @@ export async function runOptimizeDeps( resolvedConfig: ResolvedConfig, depsInfo: Record ): Promise { + const isBuild = resolvedConfig.command === 'build' const config: ResolvedConfig = { ...resolvedConfig, command: 'build' @@ -464,20 +472,15 @@ export async function runOptimizeDeps( flatIdToExports[flatId] = exportsData } - const define: Record = { - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode) - } - for (const key in config.define) { - const value = config.define[key] - define[key] = typeof value === 'string' ? value : JSON.stringify(value) - } - const start = performance.now() const result = await build({ absWorkingDir: process.cwd(), entryPoints: Object.keys(flatIdDeps), bundle: true, + // Ensure resolution is handled by esbuildDepPlugin and + // avoid replacing `process.env.NODE_ENV` for 'browser' + platform: 'neutral', format: 'esm', target: config.build.target || undefined, external: config.optimizeDeps?.exclude, @@ -485,9 +488,8 @@ export async function runOptimizeDeps( splitting: true, sourcemap: true, outdir: processingCacheDir, - ignoreAnnotations: resolvedConfig.command !== 'build', + ignoreAnnotations: !isBuild, metafile: true, - define, plugins: [ ...plugins, esbuildDepPlugin(flatIdDeps, flatIdToExports, config) @@ -613,7 +615,11 @@ export function getOptimizedDepPath( function getDepsCacheSuffix(config: ResolvedConfig): string { let suffix = '' if (config.command === 'build') { - suffix += '_build' + // Differentiate build caches depending on outDir to allow parallel builds + const { outDir } = config.build + const buildId = + outDir.length > 8 || outDir.includes('/') ? getHash(outDir) : outDir + suffix += `_build-${buildId}` if (config.build.ssr) { suffix += '_ssr' } @@ -880,7 +886,6 @@ export function getDepHash(config: ResolvedConfig): string { { mode: process.env.NODE_ENV || config.mode, root: config.root, - define: config.define, resolve: config.resolve, buildTarget: config.build.target, assetsInclude: config.assetsInclude, diff --git a/packages/vite/src/node/optimizer/optimizer.ts b/packages/vite/src/node/optimizer/optimizer.ts index d1846903d95269..5dbccae6a73db3 100644 --- a/packages/vite/src/node/optimizer/optimizer.ts +++ b/packages/vite/src/node/optimizer/optimizer.ts @@ -1,6 +1,8 @@ import colors from 'picocolors' import _debug from 'debug' +import glob from 'fast-glob' import { getHash } from '../utils' +import { transformRequest } from '../server/transformRequest' import type { ResolvedConfig, ViteDevServer } from '..' import { addOptimizedDepInfo, @@ -65,6 +67,9 @@ export async function initDepsOptimizer( isOptimizedDepUrl: createIsOptimizedDepUrl(config), getOptimizedDepId: (depInfo: OptimizedDepInfo) => isBuild ? depInfo.file : `${depInfo.file}?v=${depInfo.browserHash}`, + registerWorkersSource, + delayDepsOptimizerUntil, + resetRegisteredIds, options: config.optimizeDeps } @@ -101,8 +106,12 @@ export async function initDepsOptimizer( let enqueuedRerun: (() => void) | undefined let currentlyProcessing = false + // Only pretransform optimizeDeps.entries on cold start + let optimizeDepsEntriesVisited = !!cachedMetadata + // If there wasn't a cache or it is outdated, we need to prepare a first run let firstRunCalled = !!cachedMetadata + if (!cachedMetadata) { if (!scan) { // Initialize discovered deps with manually added optimizeDeps.include info @@ -126,9 +135,7 @@ export async function initDepsOptimizer( setTimeout(async () => { try { - debug(colors.green(`scanning for dependencies...`), { - timestamp: true - }) + debug(colors.green(`scanning for dependencies...`)) const { metadata } = depsOptimizer @@ -148,10 +155,7 @@ export async function initDepsOptimizer( debug( colors.green( `dependencies found: ${depsLogString(Object.keys(discovered))}` - ), - { - timestamp: true - } + ) ) scanPhaseProcessing.resolve() @@ -316,9 +320,7 @@ export async function initDepsOptimizer( logNewlyDiscoveredDeps() }, 2 * debounceMs) } else { - debug(colors.green(`✨ optimized dependencies unchanged`), { - timestamp: true - }) + debug(colors.green(`✨ optimized dependencies unchanged`)) } } else { if (newDepsDiscovered) { @@ -331,10 +333,7 @@ export async function initDepsOptimizer( debug( colors.green( `✨ delaying reload as new dependencies have been found...` - ), - { - timestamp: true - } + ) ) } else { await commitProcessing() @@ -403,9 +402,7 @@ export async function initDepsOptimizer( // optimizeDeps processing is finished const deps = Object.keys(depsOptimizer.metadata.discovered) const depsString = depsLogString(deps) - debug(colors.green(`new dependencies found: ${depsString}`), { - timestamp: true - }) + debug(colors.green(`new dependencies found: ${depsString}`)) runOptimizer() } @@ -496,5 +493,91 @@ export async function initDepsOptimizer( }, timeout) } + const runOptimizerIfIdleAfterMs = 100 + + let registeredIds: { id: string; done: () => Promise }[] = [] + let seenIds = new Set() + let workersSources = new Set() + let waitingOn: string | undefined + + function resetRegisteredIds() { + registeredIds = [] + seenIds = new Set() + workersSources = new Set() + waitingOn = undefined + } + + function registerWorkersSource(id: string): void { + workersSources.add(id) + // Avoid waiting for this id, as it may be blocked by the rollup + // bundling process of the worker that also depends on the optimizer + registeredIds = registeredIds.filter((registered) => registered.id !== id) + if (waitingOn === id) { + waitingOn = undefined + runOptimizerWhenIdle() + } + } + + function delayDepsOptimizerUntil(id: string, done: () => Promise): void { + if (!depsOptimizer.isOptimizedDepFile(id) && !seenIds.has(id)) { + seenIds.add(id) + registeredIds.push({ id, done }) + runOptimizerWhenIdle() + } + if (server && !optimizeDepsEntriesVisited) { + optimizeDepsEntriesVisited = true + preTransformOptimizeDepsEntries(server) + } + } + + function runOptimizerWhenIdle() { + if (!waitingOn) { + const next = registeredIds.pop() + if (next) { + waitingOn = next.id + const afterLoad = () => { + waitingOn = undefined + if (!workersSources.has(next.id)) { + if (registeredIds.length > 0) { + runOptimizerWhenIdle() + } else { + getDepsOptimizer(config)?.run() + } + } + } + next + .done() + .then(() => { + setTimeout( + afterLoad, + registeredIds.length > 0 ? 0 : runOptimizerIfIdleAfterMs + ) + }) + .catch(afterLoad) + } + } + } + return depsOptimizer } + +export async function preTransformOptimizeDepsEntries( + server: ViteDevServer +): Promise { + const { config } = server + const { entries } = config.optimizeDeps + if (entries) { + const explicitEntries = await glob(entries, { + cwd: config.root, + ignore: ['**/node_modules/**', `**/${config.build.outDir}/**`], + absolute: true + }) + // TODO: should we restrict the entries to JS and HTML like the + // scanner did? I think we can let the user chose any entry + for (const entry of explicitEntries) { + transformRequest(entry, server, { ssr: false }).catch((e) => { + config.logger.error(e.message) + }) + } + } +} diff --git a/packages/vite/src/node/packages.ts b/packages/vite/src/node/packages.ts index 1fb2e7b4a21c06..e1c0c18eb5a119 100644 --- a/packages/vite/src/node/packages.ts +++ b/packages/vite/src/node/packages.ts @@ -1,7 +1,6 @@ import fs from 'fs' import path from 'path' -import { createFilter } from '@rollup/pluginutils' -import { createDebugger, resolveFrom } from './utils' +import { createDebugger, createFilter, resolveFrom } from './utils' import type { ResolvedConfig } from './config' import type { Plugin } from './plugin' diff --git a/packages/vite/src/node/plugins/asset.ts b/packages/vite/src/node/plugins/asset.ts index 4c1bcfea0fd50b..2a119808a4eb72 100644 --- a/packages/vite/src/node/plugins/asset.ts +++ b/packages/vite/src/node/plugins/asset.ts @@ -23,6 +23,18 @@ const assetHashToFilenameMap = new WeakMap< // save hashes of the files that has been emitted in build watch const emittedHashMap = new WeakMap>() +// add own dictionary entry by directly assigning mrmime +export function registerCustomMime(): void { + // https://github.com/lukeed/mrmime/issues/3 + mrmime.mimes['ico'] = 'image/x-icon' + // https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers#flac + mrmime.mimes['flac'] = 'audio/flac' + // mrmime and mime-db is not released yet: https://github.com/jshttp/mime-db/commit/c9242a9b7d4bb25d7a0c9244adec74aeef08d8a1 + mrmime.mimes['aac'] = 'audio/aac' + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + mrmime.mimes['eot'] = 'application/vnd.ms-fontobject' +} + /** * Also supports loading plain strings with import text from './foo.txt?raw' */ @@ -31,9 +43,8 @@ export function assetPlugin(config: ResolvedConfig): Plugin { assetHashToFilenameMap.set(config, new Map()) const relativeBase = isRelativeBase(config.base) - // add own dictionary entry by directly assigning mrmine - // https://github.com/lukeed/mrmime/issues/3 - mrmime.mimes['ico'] = 'image/x-icon' + registerCustomMime() + return { name: 'vite:asset', @@ -338,8 +349,9 @@ async function fileToBuiltUrl( (!file.endsWith('.svg') && content.length < Number(config.build.assetsInlineLimit)) ) { + const mimeType = mrmime.lookup(file) ?? 'application/octet-stream' // base64 inlined as a string - url = `data:${mrmime.lookup(file)};base64,${content.toString('base64')}` + url = `data:${mimeType};base64,${content.toString('base64')}` } else { // emit as asset // rollup supports `import.meta.ROLLUP_FILE_URL_*`, but it generates code @@ -353,11 +365,22 @@ async function fileToBuiltUrl( const { search, hash } = parseUrl(id) const postfix = (search || '') + (hash || '') const output = config.build?.rollupOptions?.output - const assetFileNames = + + const defaultAssetFileNames = path.posix.join( + config.build.assetsDir, + '[name].[hash][extname]' + ) + // Steps to determine which assetFileNames will be actually used. + // First, if output is an object or string, use assetFileNames in it. + // And a default assetFileNames as fallback. + let assetFileNames: Exclude = (output && !Array.isArray(output) ? output.assetFileNames : undefined) ?? - // defaults to '/[name].[hash][extname]' - // slightly different from rollup's one ('assets/[name]-[hash][extname]') - path.posix.join(config.build.assetsDir, '[name].[hash][extname]') + defaultAssetFileNames + if (output && Array.isArray(output)) { + // Second, if output is an array, adopt assetFileNames in the first object. + assetFileNames = output[0].assetFileNames ?? assetFileNames + } + const fileName = assetFileNamesToFileName( assetFileNames, file, diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 1fa30f6a272ddd..45af9233bf4560 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -40,7 +40,8 @@ import { isRelativeBase, normalizePath, parseRequest, - processSrcSet + processSrcSet, + requireResolveFromRootWithFallback } from '../utils' import type { Logger } from '../logger' import { addToHTMLProxyTransformResult } from './html' @@ -837,15 +838,19 @@ async function compileCSS( ...postcssOptions, to: id, from: id, - map: { - inline: false, - annotation: false, - // postcss may return virtual files - // we cannot obtain content of them, so this needs to be enabled - sourcesContent: true - // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` - // prev: preprocessorMap, - } + ...(devSourcemap + ? { + map: { + inline: false, + annotation: false, + // postcss may return virtual files + // we cannot obtain content of them, so this needs to be enabled + sourcesContent: true + // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` + // prev: preprocessorMap, + } + } + : {}) }) // record CSS dependencies from @imports @@ -856,7 +861,9 @@ async function compileCSS( // https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md#3-dependencies const { dir, glob: globPattern = '**' } = message const pattern = - normalizePath(path.resolve(path.dirname(id), dir)) + `/` + globPattern + glob.escapePath(normalizePath(path.resolve(path.dirname(id), dir))) + + `/` + + globPattern const files = glob.sync(pattern, { ignore: ['**/node_modules/**'] }) @@ -1292,10 +1299,7 @@ function loadPreprocessor(lang: PreprocessLang, root: string): any { return loadedPreprocessors[lang] } try { - // Search for the preprocessor in the root directory first, and fall back - // to the default require paths. - const fallbackPaths = _require.resolve.paths?.(lang) || [] - const resolved = _require.resolve(lang, { paths: [root, ...fallbackPaths] }) + const resolved = requireResolveFromRootWithFallback(root, lang) return (loadedPreprocessors[lang] = _require(resolved)) } catch (e) { if (e.code === 'MODULE_NOT_FOUND') { diff --git a/packages/vite/src/node/plugins/define.ts b/packages/vite/src/node/plugins/define.ts index ca0f446cc1f58e..6edb1bd8858a11 100644 --- a/packages/vite/src/node/plugins/define.ts +++ b/packages/vite/src/node/plugins/define.ts @@ -10,15 +10,23 @@ const isNonJsRequest = (request: string): boolean => nonJsRe.test(request) export function definePlugin(config: ResolvedConfig): Plugin { const isBuild = config.command === 'build' - - const processNodeEnv: Record = { - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode), - 'global.process.env.NODE_ENV': JSON.stringify( - process.env.NODE_ENV || config.mode - ), - 'globalThis.process.env.NODE_ENV': JSON.stringify( - process.env.NODE_ENV || config.mode - ) + const isBuildLib = isBuild && config.build.lib + + // ignore replace process.env in lib build + const processEnv: Record = {} + const processNodeEnv: Record = {} + if (!isBuildLib) { + const nodeEnv = process.env.NODE_ENV || config.mode + Object.assign(processEnv, { + 'process.env.': `({}).`, + 'global.process.env.': `({}).`, + 'globalThis.process.env.': `({}).` + }) + Object.assign(processNodeEnv, { + 'process.env.NODE_ENV': JSON.stringify(nodeEnv), + 'global.process.env.NODE_ENV': JSON.stringify(nodeEnv), + 'globalThis.process.env.NODE_ENV': JSON.stringify(nodeEnv) + }) } const userDefine: Record = {} @@ -27,7 +35,8 @@ export function definePlugin(config: ResolvedConfig): Plugin { userDefine[key] = typeof val === 'string' ? val : JSON.stringify(val) } - // during dev, import.meta properties are handled by importAnalysis plugin + // during dev, import.meta properties are handled by importAnalysis plugin. + // ignore replace import.meta.env in lib build const importMetaKeys: Record = {} if (isBuild) { const env: Record = { @@ -47,22 +56,13 @@ export function definePlugin(config: ResolvedConfig): Plugin { function generatePattern( ssr: boolean ): [Record, RegExp | null] { - const processEnv: Record = {} - const isNeedProcessEnv = !ssr || config.ssr?.target === 'webworker' - - if (isNeedProcessEnv) { - Object.assign(processEnv, { - 'process.env.': `({}).`, - 'global.process.env.': `({}).`, - 'globalThis.process.env.': `({}).` - }) - } + const replaceProcessEnv = !ssr || config.ssr?.target === 'webworker' const replacements: Record = { - ...(isNeedProcessEnv ? processNodeEnv : {}), + ...(replaceProcessEnv ? processNodeEnv : {}), ...userDefine, ...importMetaKeys, - ...processEnv + ...(replaceProcessEnv ? processEnv : {}) } const replacementsKeys = Object.keys(replacements) diff --git a/packages/vite/src/node/plugins/dynamicImportVars.ts b/packages/vite/src/node/plugins/dynamicImportVars.ts index b6047aa59e138d..ff20c5725dc341 100644 --- a/packages/vite/src/node/plugins/dynamicImportVars.ts +++ b/packages/vite/src/node/plugins/dynamicImportVars.ts @@ -3,11 +3,11 @@ import MagicString from 'magic-string' import { init, parse as parseImports } from 'es-module-lexer' import type { ImportSpecifier } from 'es-module-lexer' import { parse as parseJS } from 'acorn' -import { createFilter } from '@rollup/pluginutils' import { dynamicImportToGlob } from '@rollup/plugin-dynamic-import-vars' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '../config' import { + createFilter, normalizePath, parseRequest, requestQuerySplitRE, diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index 11f5ea4dd6cec0..c423edca92f9c1 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -9,13 +9,13 @@ import type { import { transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import type { SourceMap } from 'rollup' -import { createFilter } from '@rollup/pluginutils' import type { TSConfckParseOptions, TSConfckParseResult } from 'tsconfck' import { TSConfckParseError, findAll, parse } from 'tsconfck' import { cleanUrl, combineSourcemaps, createDebugger, + createFilter, ensureWatchedFile, generateCodeFrame, toUpperCaseDriveLetter diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index 9d06d6e168f2e1..a66a6288f8e8c2 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -767,11 +767,6 @@ export async function applyHtmlTransforms( hooks: IndexHtmlTransformHook[], ctx: IndexHtmlTransformContext ): Promise { - const headTags: HtmlTagDescriptor[] = [] - const headPrependTags: HtmlTagDescriptor[] = [] - const bodyTags: HtmlTagDescriptor[] = [] - const bodyPrependTags: HtmlTagDescriptor[] = [] - for (const hook of hooks) { const res = await hook(html, ctx) if (!res) { @@ -787,6 +782,12 @@ export async function applyHtmlTransforms( html = res.html || html tags = res.tags } + + const headTags: HtmlTagDescriptor[] = [] + const headPrependTags: HtmlTagDescriptor[] = [] + const bodyTags: HtmlTagDescriptor[] = [] + const bodyPrependTags: HtmlTagDescriptor[] = [] + for (const tag of tags) { if (tag.injectTo === 'body') { bodyTags.push(tag) @@ -798,21 +799,12 @@ export async function applyHtmlTransforms( headPrependTags.push(tag) } } - } - } - // inject tags - if (headPrependTags.length) { - html = injectToHead(html, headPrependTags, true) - } - if (headTags.length) { - html = injectToHead(html, headTags) - } - if (bodyPrependTags.length) { - html = injectToBody(html, bodyPrependTags, true) - } - if (bodyTags.length) { - html = injectToBody(html, bodyTags) + html = injectToHead(html, headPrependTags, true) + html = injectToHead(html, headTags) + html = injectToBody(html, bodyPrependTags, true) + html = injectToBody(html, bodyTags) + } } return html @@ -859,6 +851,8 @@ function injectToHead( tags: HtmlTagDescriptor[], prepend = false ) { + if (tags.length === 0) return html + if (prepend) { // inject as the first element of head if (headPrependInjectRE.test(html)) { @@ -893,6 +887,8 @@ function injectToBody( tags: HtmlTagDescriptor[], prepend = false ) { + if (tags.length === 0) return html + if (prepend) { // inject after body open if (bodyPrependInjectRE.test(html)) { diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index ba221b4b1d5283..22797c1c0d8230 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -36,6 +36,7 @@ import { normalizePath, prettifyUrl, removeImportQuery, + stripBomTag, timeFrom, transformResult, unwrapId @@ -55,9 +56,10 @@ import { import { checkPublicFile } from './asset' import { ERR_OUTDATED_OPTIMIZED_DEP, - delayDepsOptimizerUntil + throwOutdatedRequest } from './optimizedDeps' import { isCSSRequest, isDirectCSSRequest } from './css' +import { browserExternalId } from './resolve' const isDebug = !!process.env.DEBUG const debug = createDebugger('vite:import-analysis') @@ -141,10 +143,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const start = performance.now() await init let imports: readonly ImportSpecifier[] = [] - // strip UTF-8 BOM - if (source.charCodeAt(0) === 0xfeff) { - source = source.slice(1) - } + source = stripBomTag(source) try { imports = parseImports(source)[0] } catch (e: any) { @@ -169,10 +168,19 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) } + const depsOptimizer = getDepsOptimizer(config) + const { moduleGraph } = server // since we are already in the transform phase of the importer, it must // have been loaded so its entry is guaranteed in the module graph. const importerModule = moduleGraph.getModuleById(importer)! + if (!importerModule && depsOptimizer?.isOptimizedDepFile(importer)) { + // Ids of optimized deps could be invalidated and removed from the graph + // Return without transforming, this request is no longer valid, a full reload + // is going to request this id again. Throwing an outdated error so we + // properly finish the request with a 504 sent to the browser. + throwOutdatedRequest(importer) + } if (!imports.length) { importerModule.isSelfAccepting = false @@ -199,8 +207,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { const toAbsoluteUrl = (url: string) => path.posix.resolve(path.posix.dirname(importerModule.url), url) - const depsOptimizer = getDepsOptimizer(config) - const normalizeUrl = async ( url: string, pos: number @@ -322,11 +328,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { s: start, e: end, ss: expStart, - se: expEnd, d: dynamicIndex, // #2083 User may use escape path, // so use imports[index].n to get the unescaped string - // @ts-ignore n: specifier } = imports[index] @@ -434,29 +438,20 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } } else if (needsInterop) { debug(`${url} needs interop`) - if (isDynamicImport) { - // rewrite `import('package')` to expose the default directly - str().overwrite( - expStart, - expEnd, - `import('${url}').then(m => m.default && m.default.__esModule ? m.default : ({ ...m.default, default: m.default }))`, - { contentOnly: true } - ) - } else { - const exp = source.slice(expStart, expEnd) - const rewritten = transformCjsImport(exp, url, rawUrl, index) - if (rewritten) { - str().overwrite(expStart, expEnd, rewritten, { - contentOnly: true - }) - } else { - // #1439 export * from '...' - str().overwrite(start, end, url, { contentOnly: true }) - } - } + interopNamedImports(str(), imports[index], url, index) rewriteDone = true } } + // If source code imports builtin modules via named imports, the stub proxy export + // would fail as it's `export default` only. Apply interop for builtin modules to + // correctly throw the error message. + else if ( + url.includes(browserExternalId) && + source.slice(expStart, start).includes('{') + ) { + interopNamedImports(str(), imports[index], url, index) + rewriteDone = true + } if (!rewriteDone) { str().overwrite(start, end, isDynamicImport ? `'${url}'` : url, { contentOnly: true @@ -609,7 +604,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { ) // pre-transform known direct imports - // TODO: we should also crawl dynamic imports + // TODO: should we also crawl dynamic imports? or the experience is good enough to allow + // users to chose their tradeoffs by explicitily setting optimizeDeps.entries for the + // most common dynamic imports if (config.server.preTransformRequests && staticImportedUrls.size) { staticImportedUrls.forEach(({ url, id }) => { url = unwrapId(removeImportQuery(url)).replace( @@ -624,8 +621,8 @@ 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) + if (depsOptimizer && !config.optimizeDeps.devScan) { + depsOptimizer.delayDepsOptimizerUntil(id, () => request) } }) } @@ -639,6 +636,41 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { } } +export function interopNamedImports( + str: MagicString, + importSpecifier: ImportSpecifier, + rewrittenUrl: string, + importIndex: number +): void { + const source = str.original + const { + s: start, + e: end, + ss: expStart, + se: expEnd, + d: dynamicIndex + } = importSpecifier + if (dynamicIndex > -1) { + // rewrite `import('package')` to expose the default directly + str.overwrite( + expStart, + expEnd, + `import('${rewrittenUrl}').then(m => m.default && m.default.__esModule ? m.default : ({ ...m.default, default: m.default }))`, + { contentOnly: true } + ) + } else { + const exp = source.slice(expStart, expEnd) + const rawUrl = source.slice(start, end) + const rewritten = transformCjsImport(exp, rewrittenUrl, rawUrl, importIndex) + if (rewritten) { + str.overwrite(expStart, expEnd, rewritten, { contentOnly: true }) + } else { + // #1439 export * from '...' + str.overwrite(start, end, rewrittenUrl, { contentOnly: true }) + } + } +} + type ImportNameSpecifier = { importedName: string; localName: string } /** diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index 9de2e066624e2a..0895bf5cb8f8a4 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -19,7 +19,7 @@ import type { ResolvedConfig } from '../config' import { genSourceMapUrl } from '../server/sourcemap' import { getDepsOptimizer, optimizedDepNeedsInterop } from '../optimizer' import { removedPureCssFilesCache } from './css' -import { transformCjsImport } from './importAnalysis' +import { interopNamedImports } from './importAnalysis' /** * A flag for injected helpers. This flag will be set to `false` if the output @@ -283,31 +283,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { } } else if (needsInterop) { // config.logger.info(`${url} needs interop`) - if (isDynamicImport) { - // rewrite `import('package')` to expose the default directly - str().overwrite( - expStart, - expEnd, - `import('${file}').then(m => m.default && m.default.__esModule ? m.default : ({ ...m.default, default: m.default }))`, - { contentOnly: true } - ) - } else { - const exp = source.slice(expStart, expEnd) - const rewritten = transformCjsImport( - exp, - file, - specifier, - index - ) - if (rewritten) { - str().overwrite(expStart, expEnd, rewritten, { - contentOnly: true - }) - } else { - // #1439 export * from '...' - str().overwrite(start, end, file, { contentOnly: true }) - } - } + interopNamedImports(str(), imports[index], url, index) rewriteDone = true } if (!rewriteDone) { diff --git a/packages/vite/src/node/plugins/json.ts b/packages/vite/src/node/plugins/json.ts index 9c142501ff651e..216679a22148cd 100644 --- a/packages/vite/src/node/plugins/json.ts +++ b/packages/vite/src/node/plugins/json.ts @@ -9,6 +9,7 @@ import { dataToEsm } from '@rollup/pluginutils' import { SPECIAL_QUERY_RE } from '../constants' import type { Plugin } from '../plugin' +import { stripBomTag } from '../utils' export interface JsonOptions { /** @@ -43,6 +44,8 @@ export function jsonPlugin( if (!jsonExtRE.test(id)) return null if (SPECIAL_QUERY_RE.test(id)) return null + json = stripBomTag(json) + try { if (options.stringify) { if (isBuild) { diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index 49bcc69bf6f25e..b50294f9e64b9b 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -13,100 +13,10 @@ export const ERR_OUTDATED_OPTIMIZED_DEP = 'ERR_OUTDATED_OPTIMIZED_DEP' const isDebug = process.env.DEBUG const debug = createDebugger('vite:optimize-deps') -const runOptimizerIfIdleAfterMs = 100 - -interface RunProcessingInfo { - ids: { id: string; done: () => Promise }[] - seenIds: Set - workersSources: Set - waitingOn: string | undefined -} - -const runProcessingInfoMap = new WeakMap() - -function initRunProcessingInfo(config: ResolvedConfig) { - config = config.mainConfig || config - const runProcessingInfo = { - ids: [], - seenIds: new Set(), - workersSources: new Set(), - waitingOn: undefined - } - runProcessingInfoMap.set(config, runProcessingInfo) - return runProcessingInfo -} - -function getRunProcessingInfo(config: ResolvedConfig): RunProcessingInfo { - return ( - runProcessingInfoMap.get(config.mainConfig || config) ?? - initRunProcessingInfo(config) - ) -} - -export function registerWorkersSource( - config: ResolvedConfig, - id: string -): void { - const info = getRunProcessingInfo(config) - info.workersSources.add(id) - if (info.waitingOn === id) { - info.waitingOn = undefined - } -} - -export function delayDepsOptimizerUntil( - config: ResolvedConfig, - id: string, - done: () => Promise -): void { - const info = getRunProcessingInfo(config) - if ( - !getDepsOptimizer(config)?.isOptimizedDepFile(id) && - !info.seenIds.has(id) - ) { - info.seenIds.add(id) - info.ids.push({ id, done }) - runOptimizerWhenIdle(config) - } -} - -function runOptimizerWhenIdle(config: ResolvedConfig) { - const info = getRunProcessingInfo(config) - if (!info.waitingOn) { - const next = info.ids.pop() - if (next) { - info.waitingOn = next.id - const afterLoad = () => { - info.waitingOn = undefined - if (info.ids.length > 0) { - runOptimizerWhenIdle(config) - } else if (!info.workersSources.has(next.id)) { - getDepsOptimizer(config)?.run() - } - } - next - .done() - .then(() => { - setTimeout( - afterLoad, - info.ids.length > 0 ? 0 : runOptimizerIfIdleAfterMs - ) - }) - .catch(afterLoad) - } - } -} - 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 @@ -174,7 +84,7 @@ export function optimizedDepsBuildPlugin(config: ResolvedConfig): Plugin { buildStart() { if (!config.isWorker) { - initRunProcessingInfo(config) + getDepsOptimizer(config)?.resetRegisteredIds() } }, @@ -185,7 +95,7 @@ export function optimizedDepsBuildPlugin(config: ResolvedConfig): Plugin { }, transform(_code, id) { - delayDepsOptimizerUntil(config, id, async () => { + getDepsOptimizer(config)?.delayDepsOptimizerUntil(id, async () => { await this.load({ id }) }) }, @@ -229,7 +139,7 @@ export function optimizedDepsBuildPlugin(config: ResolvedConfig): Plugin { } } -function throwProcessingError(id: string) { +function throwProcessingError(id: string): never { const err: any = new Error( `Something unexpected happened while optimizing "${id}". ` + `The current page should have reloaded by now` @@ -240,7 +150,7 @@ function throwProcessingError(id: string) { throw err } -function throwOutdatedRequest(id: string) { +export function throwOutdatedRequest(id: string): never { const err: any = new Error( `There is a new version of the pre-bundle for "${id}", ` + `a page reload is going to ask for it.` diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 33a5ad31efe5b4..7ccc3a7eb5cb7a 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -339,15 +339,17 @@ export function resolvePlugin(baseOptions: InternalResolveOptions): Plugin { load(id) { if (id.startsWith(browserExternalId)) { - return isProduction - ? `export default {}` - : `export default new Proxy({}, { - get() { - throw new Error('Module "${id.slice( - browserExternalId.length + 1 - )}" has been externalized for browser compatibility and cannot be accessed in client code.') + if (isProduction) { + return `export default {}` + } else { + id = id.slice(browserExternalId.length + 1) + return `\ +export default new Proxy({}, { + get(_, key) { + throw new Error(\`Module "${id}" has been externalized for browser compatibility. Cannot access "${id}.\${key}" in client code.\`) } })` + } } } } diff --git a/packages/vite/src/node/plugins/terser.ts b/packages/vite/src/node/plugins/terser.ts index 4e6b7b681a2cea..6362ca0b726fbf 100644 --- a/packages/vite/src/node/plugins/terser.ts +++ b/packages/vite/src/node/plugins/terser.ts @@ -1,26 +1,40 @@ -import { dirname } from 'path' -import { fileURLToPath } from 'url' import { Worker } from 'okie' import type { Terser } from 'types/terser' import type { Plugin } from '../plugin' import type { ResolvedConfig } from '..' +import { requireResolveFromRootWithFallback } from '../utils' -// TODO: use import() -const _dirname = dirname(fileURLToPath(import.meta.url)) +let terserPath: string | undefined +const loadTerserPath = (root: string) => { + if (terserPath) return terserPath + try { + terserPath = requireResolveFromRootWithFallback(root, 'terser') + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND') { + throw new Error( + 'terser not found. Since Vite v3, terser has become an optional dependency. You need to install it.' + ) + } else { + const message = new Error(`terser failed to load:\n${e.message}`) + message.stack = e.stack + '\n' + message.stack + throw message + } + } + return terserPath +} export function terserPlugin(config: ResolvedConfig): Plugin { const makeWorker = () => new Worker( - async (basedir: string, code: string, options: Terser.MinifyOptions) => { - // when vite is linked, the worker thread won't share the same resolve - // root with vite itself, so we have to pass in the basedir and resolve - // terser first. - // eslint-disable-next-line node/no-restricted-require, no-restricted-globals - const terserPath = require.resolve('terser', { - paths: [basedir] - }) - // eslint-disable-next-line no-restricted-globals - return require(terserPath).minify(code, options) as Terser.MinifyOutput + async ( + terserPath: string, + code: string, + options: Terser.MinifyOptions + ) => { + // test fails when using `import`. maybe related: https://github.com/nodejs/node/issues/43205 + // eslint-disable-next-line no-restricted-globals -- this function runs inside cjs + const terser = require(terserPath) + return terser.minify(code, options) as Terser.MinifyOutput } ) @@ -50,7 +64,8 @@ export function terserPlugin(config: ResolvedConfig): Plugin { // Lazy load worker. worker ||= makeWorker() - const res = await worker.run(_dirname, code, { + const terserPath = loadTerserPath(config.root) + const res = await worker.run(terserPath, code, { safari10: true, ...config.build.terserOptions, sourceMap: !!outputOptions.sourcemap, diff --git a/packages/vite/src/node/plugins/wasm.ts b/packages/vite/src/node/plugins/wasm.ts index 56aa56402df8e2..19bb9a0e541892 100644 --- a/packages/vite/src/node/plugins/wasm.ts +++ b/packages/vite/src/node/plugins/wasm.ts @@ -7,11 +7,21 @@ const wasmHelperId = '/__vite-wasm-helper' const wasmHelper = async (opts = {}, url: string) => { let result if (url.startsWith('data:')) { - // @ts-ignore - const binaryString = atob(url.replace(/^data:.*?base64,/, '')) - const bytes = new Uint8Array(binaryString.length) - for (let i = 0; i < binaryString.length; i++) { - bytes[i] = binaryString.charCodeAt(i) + const urlContent = url.replace(/^data:.*?base64,/, '') + let bytes + if (typeof Buffer === 'function' && typeof Buffer.from === 'function') { + bytes = Buffer.from(urlContent, 'base64') + } else if (typeof atob === 'function') { + // @ts-ignore + const binaryString = atob(urlContent) + bytes = new Uint8Array(binaryString.length) + for (let i = 0; i < binaryString.length; i++) { + bytes[i] = binaryString.charCodeAt(i) + } + } else { + throw new Error( + 'Failed to decode base64-encoded data URL, Buffer and atob are not supported' + ) } // @ts-ignore result = await WebAssembly.instantiate(bytes, opts) diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts index 1e38a18f3dbdbe..848d118ba0eb64 100644 --- a/packages/vite/src/node/plugins/worker.ts +++ b/packages/vite/src/node/plugins/worker.ts @@ -13,8 +13,8 @@ import { parseRequest } from '../utils' import { onRollupWarning } from '../build' +import { getDepsOptimizer } from '../optimizer' import { fileToUrl } from './asset' -import { registerWorkersSource } from './optimizedDeps' interface WorkerCache { // save worker all emit chunk avoid rollup make the same asset unique. @@ -269,7 +269,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin { : 'module' const workerOptions = workerType === 'classic' ? '' : ',{type: "module"}' if (isBuild) { - registerWorkersSource(config, id) + getDepsOptimizer(config)?.registerWorkersSource(id) if (query.inline != null) { const chunk = await bundleWorkerEntry(config, id, query) // inline as blob data url @@ -281,7 +281,7 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin { export default function WorkerWrapper() { const objURL = blob && (window.URL || window.webkitURL).createObjectURL(blob); try { - return objURL ? new ${workerConstructor}(objURL${workerOptions}) : new ${workerConstructor}("data:application/javascript;base64," + encodedJs${workerOptions}); + return objURL ? new ${workerConstructor}(objURL) : new ${workerConstructor}("data:application/javascript;base64," + encodedJs${workerOptions}); } finally { objURL && (window.URL || window.webkitURL).revokeObjectURL(objURL); } diff --git a/packages/vite/src/node/plugins/workerImportMetaUrl.ts b/packages/vite/src/node/plugins/workerImportMetaUrl.ts index cfb10fdb2e8591..510ae644a1a11b 100644 --- a/packages/vite/src/node/plugins/workerImportMetaUrl.ts +++ b/packages/vite/src/node/plugins/workerImportMetaUrl.ts @@ -12,10 +12,10 @@ import { parseRequest, transformResult } from '../utils' +import { getDepsOptimizer } from '../optimizer' import type { WorkerType } from './worker' import { WORKER_FILE_ID, workerFileToUrl } from './worker' import { fileToUrl } from './asset' -import { registerWorkersSource } from './optimizedDeps' const ignoreFlagRE = /\/\*\s*@vite-ignore\s*\*\// @@ -123,7 +123,7 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin { let url: string if (isBuild) { - registerWorkersSource(config, id) + getDepsOptimizer(config)?.registerWorkersSource(id) url = await workerFileToUrl(config, file, query) } else { url = await fileToUrl(cleanUrl(file), config, this) diff --git a/packages/vite/src/node/publicUtils.ts b/packages/vite/src/node/publicUtils.ts index e24db763814dec..664b9375275403 100644 --- a/packages/vite/src/node/publicUtils.ts +++ b/packages/vite/src/node/publicUtils.ts @@ -3,11 +3,12 @@ * This file will be bundled to ESM and CJS and redirected by ../index.cjs * Please control the side-effects by checking the ./dist/node-cjs/publicUtils.cjs bundle */ +export { VERSION as version } from './constants' export { splitVendorChunkPlugin, splitVendorChunk } from './plugins/splitVendorChunk' -export { normalizePath, mergeConfig, mergeAlias } from './utils' +export { normalizePath, mergeConfig, mergeAlias, createFilter } from './utils' export { send } from './server/send' export { createLogger } from './logger' export { searchForWorkspaceRoot } from './server/searchRoot' diff --git a/packages/vite/src/node/server/index.ts b/packages/vite/src/node/server/index.ts index 68c9f261f207b0..ed14fd27f70010 100644 --- a/packages/vite/src/node/server/index.ts +++ b/packages/vite/src/node/server/index.ts @@ -297,7 +297,6 @@ export async function createServer( const container = await createPluginContainer(config, moduleGraph, watcher) const closeHttpServer = createServerCloseFn(httpServer) - // eslint-disable-next-line prefer-const let exitProcess: () => void const server: ViteDevServer = { @@ -340,10 +339,11 @@ export async function createServer( return startServer(server, port, isRestart) }, async close() { - process.off('SIGTERM', exitProcess) - - if (!middlewareMode && process.env.CI !== 'true') { - process.stdin.off('end', exitProcess) + if (!middlewareMode) { + process.off('SIGTERM', exitProcess) + if (process.env.CI !== 'true') { + process.stdin.off('end', exitProcess) + } } await Promise.all([ @@ -380,18 +380,18 @@ export async function createServer( server.transformIndexHtml = createDevHtmlTransformFn(server) - exitProcess = async () => { - try { - await server.close() - } finally { - process.exit() + if (!middlewareMode) { + exitProcess = async () => { + try { + await server.close() + } finally { + process.exit() + } + } + process.once('SIGTERM', exitProcess) + if (process.env.CI !== 'true') { + process.stdin.on('end', exitProcess) } - } - - process.once('SIGTERM', exitProcess) - - if (!middlewareMode && process.env.CI !== 'true') { - process.stdin.on('end', exitProcess) } const { packageCache } = config @@ -475,7 +475,9 @@ export async function createServer( // this applies before the transform middleware so that these files are served // as-is without transforms. if (config.publicDir) { - middlewares.use(servePublicMiddleware(config.publicDir)) + middlewares.use( + servePublicMiddleware(config.publicDir, config.server.headers) + ) } // main transform middleware diff --git a/packages/vite/src/node/server/middlewares/proxy.ts b/packages/vite/src/node/server/middlewares/proxy.ts index 5c447435911ecd..9cd529a0dbba7b 100644 --- a/packages/vite/src/node/server/middlewares/proxy.ts +++ b/packages/vite/src/node/server/middlewares/proxy.ts @@ -43,11 +43,16 @@ export function proxyMiddleware( } const proxy = httpProxy.createProxyServer(opts) as HttpProxy.Server - proxy.on('error', (err) => { + proxy.on('error', (err, req, res) => { config.logger.error(`${colors.red(`http proxy error:`)}\n${err.stack}`, { timestamp: true, error: err }) + res + .writeHead(500, { + 'Content-Type': 'text/plain' + }) + .end() }) if (opts.configure) { diff --git a/packages/vite/src/node/server/middlewares/static.ts b/packages/vite/src/node/server/middlewares/static.ts index 5d4a948885baa3..3d0f453971803e 100644 --- a/packages/vite/src/node/server/middlewares/static.ts +++ b/packages/vite/src/node/server/middlewares/static.ts @@ -1,5 +1,5 @@ import path from 'path' -import type { ServerResponse } from 'http' +import type { OutgoingHttpHeaders, ServerResponse } from 'http' import type { Options } from 'sirv' import sirv from 'sirv' import type { Connect } from 'types/connect' @@ -20,24 +20,34 @@ import { const { isMatch } = micromatch -const sirvOptions: Options = { - dev: true, - etag: true, - extensions: [], - setHeaders(res, pathname) { - // Matches js, jsx, ts, tsx. - // The reason this is done, is that the .ts file extension is reserved - // for the MIME type video/mp2t. In almost all cases, we can expect - // these files to be TypeScript files, and for Vite to serve them with - // this Content-Type. - if (/\.[tj]sx?$/.test(pathname)) { - res.setHeader('Content-Type', 'application/javascript') +const sirvOptions = (headers?: OutgoingHttpHeaders): Options => { + return { + dev: true, + etag: true, + extensions: [], + setHeaders(res, pathname) { + // Matches js, jsx, ts, tsx. + // The reason this is done, is that the .ts file extension is reserved + // for the MIME type video/mp2t. In almost all cases, we can expect + // these files to be TypeScript files, and for Vite to serve them with + // this Content-Type. + if (/\.[tj]sx?$/.test(pathname)) { + res.setHeader('Content-Type', 'application/javascript') + } + if (headers) { + for (const name in headers) { + res.setHeader(name, headers[name]!) + } + } } } } -export function servePublicMiddleware(dir: string): Connect.NextHandleFunction { - const serve = sirv(dir, sirvOptions) +export function servePublicMiddleware( + dir: string, + headers?: OutgoingHttpHeaders +): Connect.NextHandleFunction { + const serve = sirv(dir, sirvOptions(headers)) // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...` return function viteServePublicMiddleware(req, res, next) { @@ -53,7 +63,7 @@ export function serveStaticMiddleware( dir: string, server: ViteDevServer ): Connect.NextHandleFunction { - const serve = sirv(dir, sirvOptions) + const serve = sirv(dir, sirvOptions(server.config.server.headers)) // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...` return function viteServeStaticMiddleware(req, res, next) { @@ -109,7 +119,7 @@ export function serveStaticMiddleware( export function serveRawFsMiddleware( server: ViteDevServer ): Connect.NextHandleFunction { - const serveFromRoot = sirv('/', sirvOptions) + const serveFromRoot = sirv('/', sirvOptions(server.config.server.headers)) // Keep the named function. The name is visible in debug logs via `DEBUG=connect:dispatcher ...` return function viteServeRawFsMiddleware(req, res, next) { diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index f759a51e60ff58..fbf7bb7bbd22ad 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -306,7 +306,7 @@ test('should declare variable for imported super class', async () => { class A extends Foo {} class B extends Foo {} Object.defineProperty(__vite_ssr_exports__, \\"B\\", { enumerable: true, configurable: true, get(){ return B }}); - Object.defineProperty(__vite_ssr_exports__, \\"default\\", { enumerable: true, value: A });" + Object.defineProperty(__vite_ssr_exports__, \\"default\\", { enumerable: true, configurable: true, value: A });" `) }) @@ -338,7 +338,7 @@ test('should handle default export variants', async () => { ).toMatchInlineSnapshot(` "function foo() {} foo.prototype = Object.prototype; - Object.defineProperty(__vite_ssr_exports__, \\"default\\", { enumerable: true, value: foo });" + Object.defineProperty(__vite_ssr_exports__, \\"default\\", { enumerable: true, configurable: true, value: foo });" `) // default named classes expect( @@ -353,7 +353,7 @@ test('should handle default export variants', async () => { "class A {} class B extends A {} Object.defineProperty(__vite_ssr_exports__, \\"B\\", { enumerable: true, configurable: true, get(){ return B }}); - Object.defineProperty(__vite_ssr_exports__, \\"default\\", { enumerable: true, value: A });" + Object.defineProperty(__vite_ssr_exports__, \\"default\\", { enumerable: true, configurable: true, value: A });" `) }) diff --git a/packages/vite/src/node/ssr/index.ts b/packages/vite/src/node/ssr/index.ts new file mode 100644 index 00000000000000..84f050ff8e41d4 --- /dev/null +++ b/packages/vite/src/node/ssr/index.ts @@ -0,0 +1,39 @@ +export type SSRTarget = 'node' | 'webworker' +export type SSRFormat = 'esm' | 'cjs' + +export interface SSROptions { + external?: string[] + noExternal?: string | RegExp | (string | RegExp)[] | true + /** + * Define the target for the ssr build. The browser field in package.json + * is ignored for node but used if webworker is the target + * Default: 'node' + */ + target?: SSRTarget + /** + * Define the format for the ssr build. Since Vite v3 the SSR build generates ESM by default. + * `'cjs'` can be selected to generate a CJS build, but it isn't recommended. This option is + * left marked as experimental to give users more time to update to ESM. CJS builds requires + * complex externalization heuristics that aren't present in the ESM format. + * @experimental + */ + format?: SSRFormat +} + +export interface ResolvedSSROptions extends SSROptions { + target: SSRTarget + format: SSRFormat +} + +export function resolveSSROptions( + ssr: SSROptions | undefined +): ResolvedSSROptions | undefined { + if (ssr === undefined) { + return undefined + } + return { + format: 'esm', + target: 'node', + ...ssr + } +} diff --git a/packages/vite/src/node/ssr/ssrExternal.ts b/packages/vite/src/node/ssr/ssrExternal.ts index fbba0e735f7df1..de0dd5bab031e4 100644 --- a/packages/vite/src/node/ssr/ssrExternal.ts +++ b/packages/vite/src/node/ssr/ssrExternal.ts @@ -1,12 +1,12 @@ import fs from 'fs' import path from 'path' import { createRequire } from 'module' -import { createFilter } from '@rollup/pluginutils' import type { InternalResolveOptions } from '../plugins/resolve' import { tryNodeResolve } from '../plugins/resolve' import { bareImportRE, createDebugger, + createFilter, isBuiltin, isDefined, lookupFile, diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index d7dc610cb82f47..e6f0d8b3a4562c 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -8,6 +8,8 @@ import type { Node as _Node } from 'estree' import { extract_names as extractNames } from 'periscopic' +// `eslint-plugin-node` doesn't support package without main +// eslint-disable-next-line node/no-missing-import import { walk as eswalk } from 'estree-walker' import type { RawSourceMap } from '@ampproject/remapping' import type { TransformResult } from '../server/transformRequest' @@ -188,7 +190,7 @@ async function ssrTransformScript( s.remove(node.start, node.start + 15 /* 'export default '.length */) s.append( `\nObject.defineProperty(${ssrModuleExportsKey}, "default", ` + - `{ enumerable: true, value: ${name} });` + `{ enumerable: true, configurable: true, value: ${name} });` ) } else { // anonymous default exports diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index 121505f566f6e9..c3c58696921dc9 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -16,16 +16,32 @@ import type { Alias, AliasOptions } from 'types/alias' import type MagicString from 'magic-string' import type { TransformResult } from 'rollup' +import { createFilter as _createFilter } from '@rollup/pluginutils' import { CLIENT_ENTRY, CLIENT_PUBLIC_PATH, DEFAULT_EXTENSIONS, ENV_PUBLIC_PATH, FS_PREFIX, - VALID_ID_PREFIX + VALID_ID_PREFIX, + wildcardHosts } from './constants' import type { ResolvedConfig } from '.' +/** + * Inlined to keep `@rollup/pluginutils` in devDependencies + */ +export type FilterPattern = + | ReadonlyArray + | string + | RegExp + | null +export const createFilter = _createFilter as ( + include?: FilterPattern, + exclude?: FilterPattern, + options?: { resolve?: string | false | null } +) => (id: string | unknown) => boolean + export function slash(p: string): string { return p.replace(/\\/g, '/') } @@ -37,7 +53,10 @@ export function unwrapId(id: string): string { } export const flattenId = (id: string): string => - id.replace(/(\s*>\s*)/g, '__').replace(/[\/\.:]/g, '_') + id + .replace(/[\/:]/g, '_') + .replace(/[\.]/g, '__') + .replace(/(\s*>\s*)/g, '___') export const normalizeId = (id: string): string => id.replace(/(\s*>\s*)/g, ' > ') @@ -729,7 +748,7 @@ export function resolveHostname( let host: string | undefined if (optionsHost === undefined || optionsHost === false) { // Use a secure default - host = '127.0.0.1' + host = 'localhost' } else if (optionsHost === true) { // If passed --host in the CLI without arguments host = undefined // undefined typically means 0.0.0.0 or :: (listen on all IPs) @@ -737,14 +756,9 @@ export function resolveHostname( host = optionsHost } - // Set host name to localhost when possible, unless the user explicitly asked for '127.0.0.1' + // Set host name to localhost when possible const name = - (optionsHost !== '127.0.0.1' && host === '127.0.0.1') || - host === '0.0.0.0' || - host === '::' || - host === undefined - ? 'localhost' - : host + host === undefined || wildcardHosts.has(host) ? 'localhost' : host return { host, name } } @@ -791,6 +805,18 @@ export function getHash(text: Buffer | string): string { return createHash('sha256').update(text).digest('hex').substring(0, 8) } +export const requireResolveFromRootWithFallback = ( + root: string, + id: string +): string => { + // Search in the root directory first, and fallback to the default require paths. + const fallbackPaths = _require.resolve.paths?.(id) || [] + const path = _require.resolve(id, { + paths: [root, ...fallbackPaths] + }) + return path +} + // Based on node-graceful-fs // The ISC License @@ -988,3 +1014,12 @@ export function transformResult( map: needSourceMap ? s.generateMap({ hires: true, source: id }) : null } } + +// strip UTF-8 BOM +export function stripBomTag(content: string): string { + if (content.charCodeAt(0) === 0xfeff) { + return content.slice(1) + } + + return content +} diff --git a/playground/alias/package.json b/playground/alias/package.json index c9883422d785d4..ee345bf1f9ce13 100644 --- a/playground/alias/package.json +++ b/playground/alias/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "aliased-module": "file:./dir/module", - "vue": "^3.2.36" + "vue": "^3.2.37" }, "devDependencies": { "resolve-linked": "workspace:*" diff --git a/playground/assets/__tests__/assets.spec.ts b/playground/assets/__tests__/assets.spec.ts index 20040c173c7f87..fda5e4e4c83ef1 100644 --- a/playground/assets/__tests__/assets.spec.ts +++ b/playground/assets/__tests__/assets.spec.ts @@ -218,6 +218,12 @@ describe('svg fragments', () => { }) }) +test('Unknown extension assets import', async () => { + expect(await page.textContent('.unknown-ext')).toMatch( + isBuild ? 'data:application/octet-stream;' : '/nested/foo.unknown' + ) +}) + test('?raw import', async () => { expect(await page.textContent('.raw')).toMatch('SVG') }) diff --git a/playground/assets/__tests__/relative-base/relative-base-assets.spec.ts b/playground/assets/__tests__/relative-base/relative-base-assets.spec.ts index a09116c88a7ea6..828ece5ea27c5f 100644 --- a/playground/assets/__tests__/relative-base/relative-base-assets.spec.ts +++ b/playground/assets/__tests__/relative-base/relative-base-assets.spec.ts @@ -5,7 +5,8 @@ import { getBg, getColor, isBuild, - page + page, + viteConfig } from '~utils' const absoluteAssetMatch = isBuild @@ -137,7 +138,8 @@ describe('css url() references', () => { describe.runIf(isBuild)('index.css URLs', () => { let css: string beforeAll(() => { - css = findAssetFile(/index.*\.css$/, '', 'other-assets') + const base = viteConfig ? viteConfig?.testConfig?.baseRoute : '' + css = findAssetFile(/index.*\.css$/, base, 'other-assets') }) test('relative asset URL', () => { diff --git a/playground/assets/index.html b/playground/assets/index.html index 418cc06f05bcd1..a741379e82013e 100644 --- a/playground/assets/index.html +++ b/playground/assets/index.html @@ -166,6 +166,9 @@

SVG Fragments via JS Import

+

Unknown extension assets import

+ +

?raw import

@@ -318,6 +321,9 @@

style in svg

text('.svg-frag-import-path', svgFrag) document.querySelector('.svg-frag-import').src = svgFrag + '#icon-heart-view' + import unknownExtUrl from './nested/foo.unknown' + text('.unknown-ext', unknownExtUrl) + import rawSvg from './nested/fragment.svg?raw' text('.raw', rawSvg) diff --git a/playground/assets/nested/foo.unknown b/playground/assets/nested/foo.unknown new file mode 100644 index 00000000000000..e24f83b664c55c --- /dev/null +++ b/playground/assets/nested/foo.unknown @@ -0,0 +1 @@ +custom file diff --git a/playground/assets/vite.config-relative-base.js b/playground/assets/vite.config-relative-base.js index ba624964d3e0e3..ae09766c0768ac 100644 --- a/playground/assets/vite.config-relative-base.js +++ b/playground/assets/vite.config-relative-base.js @@ -8,7 +8,7 @@ module.exports = { base: './', // relative base to make dist portable build: { ...baseConfig.build, - outDir: 'dist', + outDir: 'dist/relative-base', watch: false, minify: false, assetsInlineLimit: 0, @@ -19,5 +19,8 @@ module.exports = { assetFileNames: 'other-assets/[name].[hash][extname]' } } + }, + testConfig: { + baseRoute: '/relative-base/' } } diff --git a/playground/assets/vite.config.js b/playground/assets/vite.config.js index e44ddda7995185..c9d821ae3d73ee 100644 --- a/playground/assets/vite.config.js +++ b/playground/assets/vite.config.js @@ -11,6 +11,7 @@ module.exports = { '@': path.resolve(__dirname, 'nested') } }, + assetsInclude: ['**/*.unknown'], build: { outDir: 'dist/foo', assetsInlineLimit: 8192, // 8kb diff --git a/playground/backend-integration/__tests__/backend-integration.spec.ts b/playground/backend-integration/__tests__/backend-integration.spec.ts index e8059c7d20f13c..314ccfb0582680 100644 --- a/playground/backend-integration/__tests__/backend-integration.spec.ts +++ b/playground/backend-integration/__tests__/backend-integration.spec.ts @@ -52,7 +52,7 @@ describe.runIf(isServe)('serve', () => { await untilUpdated(() => getColor('body'), 'red') // successful HMR // Verify that the base (/dev/) was added during the css-update - const link = await page.$('link[rel="stylesheet"]') + const link = await page.$('link[rel="stylesheet"]:last-of-type') expect(await link.getAttribute('href')).toContain('/dev/global.css?t=') }) diff --git a/playground/backend-integration/package.json b/playground/backend-integration/package.json index c1419548cb3bd3..a9c2b4f2bca63d 100644 --- a/playground/backend-integration/package.json +++ b/playground/backend-integration/package.json @@ -9,7 +9,7 @@ "preview": "vite preview" }, "dependencies": { - "tailwindcss": "^2.2.19" + "tailwindcss": "^3.1.2" }, "devDependencies": { "fast-glob": "^3.2.11" diff --git a/playground/backend-integration/tailwind.config.js b/playground/backend-integration/tailwind.config.js index 6e72a7e5d9d87b..0c3ae11de7565e 100644 --- a/playground/backend-integration/tailwind.config.js +++ b/playground/backend-integration/tailwind.config.js @@ -1,7 +1,5 @@ module.exports = { - mode: 'jit', - purge: [__dirname + '/frontend/**/*.{css,html,ts,js}'], - darkMode: false, // or 'media' or 'class' + content: [__dirname + '/frontend/**/*.{css,html,ts,js}'], theme: { extend: {} }, diff --git a/playground/cli-module/__tests__/serve.ts b/playground/cli-module/__tests__/serve.ts index 5d40149300f6a5..698cbd048851d1 100644 --- a/playground/cli-module/__tests__/serve.ts +++ b/playground/cli-module/__tests__/serve.ts @@ -1,7 +1,7 @@ // this is automatically detected by playground/vitestSetup.ts and will replace // the default e2e test serve behavior -import execa from 'execa' +import { execaCommand } from 'execa' import kill from 'kill-port' import { isBuild, @@ -45,7 +45,7 @@ export async function serve() { if (isBuild) { const buildCommand = `${viteBinPath} build` try { - const buildProcess = execa.command(buildCommand, { + const buildProcess = execaCommand(buildCommand, { cwd: rootDir, stdio: 'pipe' }) @@ -67,7 +67,7 @@ export async function serve() { viteServerArgs.unshift('preview') } const serverCommand = `${viteBinPath} ${viteServerArgs.join(' ')}` - const serverProcess = execa.command(serverCommand, { + const serverProcess = execaCommand(serverCommand, { cwd: rootDir, stdio: 'pipe' }) diff --git a/playground/cli/__tests__/serve.ts b/playground/cli/__tests__/serve.ts index 6dbc05708d9cec..66f00677169f2a 100644 --- a/playground/cli/__tests__/serve.ts +++ b/playground/cli/__tests__/serve.ts @@ -1,7 +1,7 @@ // this is automatically detected by playground/vitestSetup.ts and will replace // the default e2e test serve behavior -import execa from 'execa' +import { execaCommand } from 'execa' import kill from 'kill-port' import { isBuild, @@ -45,7 +45,7 @@ export async function serve() { if (isBuild) { const buildCommand = `${viteBinPath} build` try { - const buildProcess = execa.command(buildCommand, { + const buildProcess = execaCommand(buildCommand, { cwd: rootDir, stdio: 'pipe' }) @@ -67,7 +67,7 @@ export async function serve() { viteServerArgs.unshift('preview') } const serverCommand = `${viteBinPath} ${viteServerArgs.join(' ')}` - const serverProcess = execa.command(serverCommand, { + const serverProcess = execaCommand(serverCommand, { cwd: rootDir, stdio: 'pipe' }) diff --git a/playground/css-sourcemap/package.json b/playground/css-sourcemap/package.json index f235b613e17922..f7a7d480c8ec22 100644 --- a/playground/css-sourcemap/package.json +++ b/playground/css-sourcemap/package.json @@ -9,9 +9,9 @@ "preview": "vite preview" }, "devDependencies": { - "less": "^4.1.2", + "less": "^4.1.3", "magic-string": "^0.26.2", - "sass": "^1.52.1", - "stylus": "^0.58.0" + "sass": "^1.52.3", + "stylus": "^0.58.1" } } diff --git a/playground/css/__tests__/css.spec.ts b/playground/css/__tests__/css.spec.ts index e9d1fccac61d6e..564f0665bf0cea 100644 --- a/playground/css/__tests__/css.spec.ts +++ b/playground/css/__tests__/css.spec.ts @@ -317,9 +317,11 @@ test('treeshaken async chunk', async () => { test('PostCSS dir-dependency', async () => { const el1 = await page.$('.dir-dep') const el2 = await page.$('.dir-dep-2') + const el3 = await page.$('.dir-dep-3') expect(await getColor(el1)).toBe('grey') expect(await getColor(el2)).toBe('grey') + expect(await getColor(el3)).toBe('grey') if (!isBuild) { editFile('glob-dep/foo.css', (code) => @@ -334,6 +336,13 @@ test('PostCSS dir-dependency', async () => { await untilUpdated(() => getColor(el2), 'red') expect(await getColor(el1)).toBe('blue') + editFile('glob-dep/nested (dir)/baz.css', (code) => + code.replace('color: grey', 'color: green') + ) + await untilUpdated(() => getColor(el3), 'green') + expect(await getColor(el1)).toBe('blue') + expect(await getColor(el2)).toBe('red') + // test add/remove removeFile('glob-dep/bar.css') await untilUpdated(() => getColor(el2), 'black') diff --git a/playground/css/glob-dep/nested (dir)/baz.css b/playground/css/glob-dep/nested (dir)/baz.css new file mode 100644 index 00000000000000..9a8b0f0ba47dc5 --- /dev/null +++ b/playground/css/glob-dep/nested (dir)/baz.css @@ -0,0 +1,3 @@ +.dir-dep-3 { + color: grey; +} diff --git a/playground/css/index.html b/playground/css/index.html index 15e81192cec7f1..4310967b6ca65b 100644 --- a/playground/css/index.html +++ b/playground/css/index.html @@ -113,6 +113,9 @@

CSS

PostCSS dir-dependency (file 2): this should be grey too

+

+ PostCSS dir-dependency (file 3): this should be grey too +

URL separation preservation: should have valid background-image diff --git a/playground/css/package.json b/playground/css/package.json index b83dcf384ad7e6..d78baa07c8d752 100644 --- a/playground/css/package.json +++ b/playground/css/package.json @@ -11,9 +11,9 @@ "devDependencies": { "css-dep": "link:./css-dep", "fast-glob": "^3.2.11", - "less": "^4.1.2", + "less": "^4.1.3", "postcss-nested": "^5.0.6", - "sass": "^1.52.1", - "stylus": "^0.58.0" + "sass": "^1.52.3", + "stylus": "^0.58.1" } } diff --git a/playground/css/postcss-caching/css.spec.ts b/playground/css/postcss-caching/css.spec.ts index bbffdb618280e4..45e8aadaa5489c 100644 --- a/playground/css/postcss-caching/css.spec.ts +++ b/playground/css/postcss-caching/css.spec.ts @@ -36,7 +36,7 @@ test('postcss config', async () => { blueApp = null greenApp = await startServer(greenAppDir) - await page.goto(`http://localhost:${port}`) + await page.reload() // hmr reloads it automatically but reload here for consistency const greenA = await page.$('.postcss-a') expect(await getColor(greenA)).toBe('black') const greenB = await page.$('.postcss-b') diff --git a/playground/css/postcss.config.js b/playground/css/postcss.config.js index 33058023541515..b30209bff42097 100644 --- a/playground/css/postcss.config.js +++ b/playground/css/postcss.config.js @@ -16,7 +16,7 @@ function testDirDep() { AtRule(atRule, { result, Comment }) { if (atRule.name === 'test') { const pattern = normalizePath( - path.resolve(path.dirname(result.opts.from), './glob-dep/*.css') + path.resolve(path.dirname(result.opts.from), './glob-dep/**/*.css') ) const files = glob.sync(pattern) const text = files.map((f) => fs.readFileSync(f, 'utf-8')).join('\n') @@ -30,6 +30,14 @@ function testDirDep() { glob: '*.css', parent: result.opts.from }) + + result.messages.push({ + type: 'dir-dependency', + plugin: 'dir-dep', + dir: './glob-dep/nested (dir)', // includes special characters in glob + glob: '*.css', + parent: result.opts.from + }) } } } diff --git a/playground/define/__tests__/define.spec.ts b/playground/define/__tests__/define.spec.ts index 695d210a822ed6..76b1dfef5feb39 100644 --- a/playground/define/__tests__/define.spec.ts +++ b/playground/define/__tests__/define.spec.ts @@ -40,4 +40,7 @@ test('string', async () => { // html would't need to define replacement expect(await page.textContent('.exp-define')).toBe('__EXP__') expect(await page.textContent('.import-json')).toBe('__EXP__') + expect(await page.textContent('.define-in-dep')).toBe( + defines.__STRINGIFIED_OBJ__ + ) }) diff --git a/playground/define/commonjs-dep/index.js b/playground/define/commonjs-dep/index.js new file mode 100644 index 00000000000000..23e0bf1b32e32f --- /dev/null +++ b/playground/define/commonjs-dep/index.js @@ -0,0 +1 @@ +module.exports = { defined: __STRINGIFIED_OBJ__ } diff --git a/playground/define/commonjs-dep/package.json b/playground/define/commonjs-dep/package.json new file mode 100644 index 00000000000000..3047ae68c9f75a --- /dev/null +++ b/playground/define/commonjs-dep/package.json @@ -0,0 +1,6 @@ +{ + "name": "commonjs-dep", + "private": true, + "version": "1.0.0", + "type": "commonjs" +} diff --git a/playground/define/index.html b/playground/define/index.html index 1260b119149d28..c4f4c598aba563 100644 --- a/playground/define/index.html +++ b/playground/define/index.html @@ -16,6 +16,7 @@

Define

no identifier substring:

define variable in html: __EXP__

import json:

+

define in dep: