diff --git a/.eslintrc.cjs b/.eslintrc.cjs index bb48bf9c307fd6..f6db9c4b4cbc5c 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -89,6 +89,7 @@ module.exports = defineConfig({ { prefer: 'type-imports' } ], + 'import/no-duplicates': 'error', 'import/order': 'error', 'sort-imports': [ 'error', @@ -114,6 +115,12 @@ module.exports = defineConfig({ 'node/no-extraneous-import': 'off' } }, + { + files: ['packages/plugin-*/**/*'], + rules: { + 'no-restricted-globals': ['error', 'require', '__dirname', '__filename'] + } + }, { files: ['playground/**'], rules: { diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 4659ea5ab7ae4f..5023b3cdc328d9 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -3,17 +3,42 @@ import { defineConfig } from 'vitepress' export default defineConfig({ title: 'Vite', description: 'Next Generation Frontend Tooling', - head: [['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }]], + + head: [ + ['link', { rel: 'icon', type: 'image/svg+xml', href: '/logo.svg' }], + + // TODO: This is neeeded to get smooth dark mode appearance on initial + // load. And this will be gone when VitePress figures out how to handle + // this in core. + [ + 'script', + {}, + ` + ;(() => { + const saved = localStorage.getItem('vitepress-theme-appearance') + const prefereDark = window.matchMedia('(prefers-color-scheme: dark)').matches + + if (!saved || saved === 'auto' ? prefereDark : saved === 'dark') { + document.documentElement.classList.add('dark') + } + })() + ` + ] + ], + vue: { reactivityTransform: true }, + themeConfig: { - repo: 'vitejs/vite', logo: '/logo.svg', - docsDir: 'docs', - docsBranch: 'main', - editLinks: true, - editLinkText: 'Suggest changes to this page', + + editLink: { + repo: 'vitejs/vite', + branch: 'main', + dir: 'docs', + text: 'Suggest changes to this page' + }, algolia: { apiKey: 'b573aa848fd57fb47d693b531297403c', @@ -28,6 +53,14 @@ export default defineConfig({ placement: 'vitejsdev' }, + localeLinks: { + text: 'English', + items: [ + { text: '简体中文', link: 'https://cn.vitejs.dev' }, + { text: '日本語', link: 'https://ja.vitejs.dev' } + ] + }, + nav: [ { text: 'Guide', link: '/guide/' }, { text: 'Config', link: '/config/' }, @@ -69,34 +102,14 @@ export default defineConfig({ link: 'https://v2.vitejs.dev' } ] - }, - { - text: 'Languages', - items: [ - { - text: 'English', - link: 'https://vitejs.dev' - }, - { - text: '简体中文', - link: 'https://cn.vitejs.dev' - }, - { - text: '日本語', - link: 'https://ja.vitejs.dev' - } - ] } ], sidebar: { - '/config/': 'auto', - '/plugins': 'auto', - // catch-all fallback '/': [ { text: 'Guide', - children: [ + items: [ { text: 'Why Vite', link: '/guide/why' @@ -153,7 +166,7 @@ export default defineConfig({ }, { text: 'APIs', - children: [ + items: [ { text: 'Plugin API', link: '/guide/api-plugin' diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.ts similarity index 84% rename from docs/.vitepress/theme/index.js rename to docs/.vitepress/theme/index.ts index babdc165f30ed8..4c75157f96c18e 100644 --- a/docs/.vitepress/theme/index.js +++ b/docs/.vitepress/theme/index.ts @@ -1,7 +1,8 @@ -import Theme from 'vitepress/theme' import { h } from 'vue' +import Theme from 'vitepress/theme' import SponsorsSidebar from './SponsorsSidebar.vue' -import './custom.css' +import './styles/vars.css' +import './styles/custom.css' export default { ...Theme, diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/styles/custom.css similarity index 70% rename from docs/.vitepress/theme/custom.css rename to docs/.vitepress/theme/styles/custom.css index 098a29853b4a49..2678c12e6b4283 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/styles/custom.css @@ -16,17 +16,12 @@ display: none; } -:root { - --c-brand: #646cff; - --c-brand-light: #747bff; -} - .custom-block.tip { - border-color: var(--c-brand-light); + border-color: var(--vp-c-brand-light); } .DocSearch { - --docsearch-primary-color: var(--c-brand) !important; + --docsearch-primary-color: var(--vp-c-brand) !important; } #play-vite-audio { diff --git a/docs/.vitepress/theme/styles/vars.css b/docs/.vitepress/theme/styles/vars.css new file mode 100644 index 00000000000000..1d2dc2b93d8a96 --- /dev/null +++ b/docs/.vitepress/theme/styles/vars.css @@ -0,0 +1,5 @@ +:root { + --vp-c-brand: #646cff; + --vp-c-brand-light: #747bff; + --vp-c-brand-dark: #535bf2; +} diff --git a/docs/config/index.md b/docs/config/index.md index 1c61f2bef5b7ac..5eeee78a37ffef 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -712,7 +712,6 @@ createServer() ### server.fs.deny -- **Experimental** - **Type:** `string[]` Blocklist for sensitive files being restricted to be served by Vite dev server. @@ -741,11 +740,11 @@ export default defineConfig({ - **Default:** `'modules'` - **Related:** [Browser Compatibility](/guide/build#browser-compatibility) - Browser compatibility target for the final bundle. The default value is a Vite special value, `'modules'`, which targets [browsers with native ES module support](https://caniuse.com/es6-module). + Browser compatibility target for the final bundle. The default value is a Vite special value, `'modules'`, which targets browsers with [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import) support. Another special value is `'esnext'` - which assumes native dynamic imports support and will transpile as little as possible: - - If the [`build.minify`](#build-minify) option is `'terser'`, `'esnext'` will be forced down to `'es2019'`. + - If the [`build.minify`](#build-minify) option is `'terser'`, `'esnext'` will be forced down to `'es2021'`. - In other cases, it will perform no transpilation at all. The transform is performed with esbuild and the value should be a valid [esbuild target option](https://esbuild.github.io/api/#target). Custom targets can either be a ES version (e.g. `es2015`), a browser with version (e.g. `chrome58`), or an array of multiple target strings. diff --git a/docs/guide/api-javascript.md b/docs/guide/api-javascript.md index 0128be26bd92ba..33202e0d608238 100644 --- a/docs/guide/api-javascript.md +++ b/docs/guide/api-javascript.md @@ -30,6 +30,10 @@ const { createServer } = require('vite') })() ``` +::: tip NOTE +When using `createServer` and `build` in the same Node.js process, both functions rely on `process.env.``NODE_ENV` to work properly, which also depends on the `mode` config option. To prevent conflicting behavior, set `process.env.``NODE_ENV` or the `mode` of the two APIs to `development`. Otherwise, you can spawn a child process to run the APIs separately. +::: + ## `InlineConfig` The `InlineConfig` interface extends `UserConfig` with additional properties: @@ -148,8 +152,6 @@ const { build } = require('vite') ## `preview` -**Experimental** - **Type Signature:** ```ts diff --git a/docs/guide/assets.md b/docs/guide/assets.md index 9776dcdd032f35..34e86924362add 100644 --- a/docs/guide/assets.md +++ b/docs/guide/assets.md @@ -114,6 +114,6 @@ const imgUrl = new URL(imagePath, import.meta.url).href This pattern does not work if you are using Vite for Server-Side Rendering, because `import.meta.url` have different semantics in browsers vs. Node.js. The server bundle also cannot determine the client host URL ahead of time. ::: -::: warning Esbuild target config is necessary -This pattern needs esbuild target to be set to `es2020` or higher. `vite@2.x` use `es2019` as default target. Set [build-target](https://vitejs.dev/config/#build-target) and [optimizedeps.esbuildoptions.target](https://vitejs.dev/config/#optimizedeps-esbuildoptions) to `es2020` or higher if you intend to use this partten. +::: warning `target` needs to be `es2020` or higher +This pattern will not work if [build-target](https://vitejs.dev/config/#build-target) or [optimizedeps.esbuildoptions.target](https://vitejs.dev/config/#optimizedeps-esbuildoptions) is set to a value lower than `es2020`. ::: diff --git a/docs/guide/build.md b/docs/guide/build.md index 358745d02f2cf1..578b8f495c41fb 100644 --- a/docs/guide/build.md +++ b/docs/guide/build.md @@ -4,11 +4,12 @@ When it is time to deploy your app for production, simply run the `vite build` c ## Browser Compatibility -The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ESM script tag](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import). As a reference, Vite uses this [browserslist](https://github.com/browserslist/browserslist) query: +The production bundle assumes support for modern JavaScript. By default, Vite targets browsers which support the [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import) and [`import.meta`](https://caniuse.com/mdn-javascript_statements_import_meta): -``` -defaults and supports es6-module and supports es6-module-dynamic-import, not opera > 0, not samsung > 0, not and_qq > 0 -``` +- Chrome >=87 +- Firefox >=78 +- Safari >=13 +- Edge >=88 You can specify custom targets via the [`build.target` config option](/config/#build-target), where the lowest target is `es2015`. diff --git a/docs/guide/features.md b/docs/guide/features.md index bb8179e75073f5..ef0610111b9709 100644 --- a/docs/guide/features.md +++ b/docs/guide/features.md @@ -435,13 +435,13 @@ Note that variables only represent file names one level deep. If `file` is `'foo ## WebAssembly -Pre-compiled `.wasm` files can be directly imported - the default export will be an initialization function that returns a Promise of the exports object of the wasm instance: +Pre-compiled `.wasm` files can be imported with `?init` - the default export will be an initialization function that returns a Promise of the wasm instance: ```js -import init from './example.wasm' +import init from './example.wasm?init' -init().then((exports) => { - exports.test() +init().then((instance) => { + instance.exports.test() }) ``` @@ -461,6 +461,11 @@ init({ In the production build, `.wasm` files smaller than `assetInlineLimit` will be inlined as base64 strings. Otherwise, they will be copied to the dist directory as an asset and fetched on-demand. +::: warning +[ES Module Integration Proposal for WebAssembly](https://github.com/WebAssembly/esm-integration) is not currently supported. +Use [`vite-plugin-wasm`](https://github.com/Menci/vite-plugin-wasm) or other community plugins to handle this. +::: + ## Web Workers ### Import with Constructors diff --git a/docs/guide/index.md b/docs/guide/index.md index 338bd42a565aa3..ab45ceb7f85475 100644 --- a/docs/guide/index.md +++ b/docs/guide/index.md @@ -18,7 +18,7 @@ You can learn more about the rationale behind the project in the [Why Vite](./wh ## Browser Support -- The default build targets browsers that support both [native ESM via script tags](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import). Legacy browsers can be supported via the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) - see the [Building for Production](./build) section for more details. +- The default build targets browsers that support both [native ES Modules](https://caniuse.com/es6-module) and [native ESM dynamic import](https://caniuse.com/es6-module-dynamic-import). Legacy browsers can be supported via the official [@vitejs/plugin-legacy](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) - see the [Building for Production](./build) section for more details. ## Trying Vite Online @@ -145,4 +145,4 @@ Then go to your Vite based project and run `pnpm link --global vite` (or the pac ## Community -If you have questions or need help, reach out to the community at [Discord](https://discord.gg/4cmKdMfpU5) and [GitHub Discussions](https://github.com/vitejs/vite/discussions). +If you have questions or need help, reach out to the community at [Discord](https://chat.vitejs.dev) and [GitHub Discussions](https://github.com/vitejs/vite/discussions). diff --git a/docs/guide/ssr.md b/docs/guide/ssr.md index 319b461022433d..ee078e82eb60a1 100644 --- a/docs/guide/ssr.md +++ b/docs/guide/ssr.md @@ -169,7 +169,7 @@ Our scripts in `package.json` will look like this: Note the `--ssr` flag which indicates this is an SSR build. It should also specify the SSR entry. -Then, in `server.js` we need to add some production specific logic by checking `process.env.NODE_ENV`: +Then, in `server.js` we need to add some production specific logic by checking `process.env.``NODE_ENV`: - Instead of reading the root `index.html`, use the `dist/client/index.html` as the template instead, since it contains the correct asset links to the client build. diff --git a/docs/index.md b/docs/index.md index ce1678de00404e..f1e950b19e8582 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,6 +23,8 @@ features: footer: MIT Licensed | Copyright © 2019-present Evan You & Vite Contributors --- +> TODO: Home Page feature is not ready in VitePress Next just yet! So this page looks broken for now. + diff --git a/package.json b/package.json index dd19523dfdc497..9144ab4d6e9590 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "npm-run-all": "^4.1.5", "picocolors": "^1.0.0", "playwright-chromium": "^1.21.1", + "pnpm": "^7.1.2", "prettier": "2.6.2", "prompts": "^2.4.2", "rimraf": "^3.0.2", @@ -83,7 +84,7 @@ "typescript": "^4.6.4", "unbuild": "^0.7.4", "vite": "workspace:*", - "vitepress": "^0.22.4", + "vitepress": "1.0.0-draft.1", "vitest": "^0.12.4", "vue": "^3.2.33" }, diff --git a/packages/create-vite/template-lit-ts/tsconfig.json b/packages/create-vite/template-lit-ts/tsconfig.json index 91a731fd8619d4..b080b2b2cd41a7 100644 --- a/packages/create-vite/template-lit-ts/tsconfig.json +++ b/packages/create-vite/template-lit-ts/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { - "module": "esnext", - "lib": ["es2017", "dom", "dom.iterable"], + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], "declaration": true, "emitDeclarationOnly": true, "outDir": "./types", @@ -10,7 +10,7 @@ "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "moduleResolution": "node", + "moduleResolution": "Node", "isolatedModules": true, "allowSyntheticDefaultImports": true, "experimentalDecorators": true, diff --git a/packages/create-vite/template-lit-ts/tsconfig.node.json b/packages/create-vite/template-lit-ts/tsconfig.node.json index e993792cb12c9d..65dbdb96ae5dcf 100644 --- a/packages/create-vite/template-lit-ts/tsconfig.node.json +++ b/packages/create-vite/template-lit-ts/tsconfig.node.json @@ -1,8 +1,8 @@ { "compilerOptions": { "composite": true, - "module": "esnext", - "moduleResolution": "node" + "module": "ESNext", + "moduleResolution": "Node" }, "include": ["vite.config.ts"] } diff --git a/packages/create-vite/template-preact-ts/tsconfig.node.json b/packages/create-vite/template-preact-ts/tsconfig.node.json index e993792cb12c9d..65dbdb96ae5dcf 100644 --- a/packages/create-vite/template-preact-ts/tsconfig.node.json +++ b/packages/create-vite/template-preact-ts/tsconfig.node.json @@ -1,8 +1,8 @@ { "compilerOptions": { "composite": true, - "module": "esnext", - "moduleResolution": "node" + "module": "ESNext", + "moduleResolution": "Node" }, "include": ["vite.config.ts"] } diff --git a/packages/create-vite/template-react-ts/src/main.tsx b/packages/create-vite/template-react-ts/src/main.tsx index 4a1b15096e15b1..611e848f1a3e9c 100644 --- a/packages/create-vite/template-react-ts/src/main.tsx +++ b/packages/create-vite/template-react-ts/src/main.tsx @@ -3,7 +3,7 @@ import ReactDOM from 'react-dom/client' import App from './App' import './index.css' -ReactDOM.createRoot(document.getElementById('root')!).render( +ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( diff --git a/packages/create-vite/template-react-ts/tsconfig.node.json b/packages/create-vite/template-react-ts/tsconfig.node.json index e993792cb12c9d..65dbdb96ae5dcf 100644 --- a/packages/create-vite/template-react-ts/tsconfig.node.json +++ b/packages/create-vite/template-react-ts/tsconfig.node.json @@ -1,8 +1,8 @@ { "compilerOptions": { "composite": true, - "module": "esnext", - "moduleResolution": "node" + "module": "ESNext", + "moduleResolution": "Node" }, "include": ["vite.config.ts"] } diff --git a/packages/create-vite/template-svelte-ts/tsconfig.json b/packages/create-vite/template-svelte-ts/tsconfig.json index 96bfd81aaf1203..d38303196ae8dc 100644 --- a/packages/create-vite/template-svelte-ts/tsconfig.json +++ b/packages/create-vite/template-svelte-ts/tsconfig.json @@ -1,9 +1,9 @@ { "extends": "@tsconfig/svelte/tsconfig.json", "compilerOptions": { - "target": "esnext", + "target": "ESNext", "useDefineForClassFields": true, - "module": "esnext", + "module": "ESNext", "resolveJsonModule": true, "baseUrl": ".", /** diff --git a/packages/create-vite/template-svelte-ts/tsconfig.node.json b/packages/create-vite/template-svelte-ts/tsconfig.node.json index e993792cb12c9d..65dbdb96ae5dcf 100644 --- a/packages/create-vite/template-svelte-ts/tsconfig.node.json +++ b/packages/create-vite/template-svelte-ts/tsconfig.node.json @@ -1,8 +1,8 @@ { "compilerOptions": { "composite": true, - "module": "esnext", - "moduleResolution": "node" + "module": "ESNext", + "moduleResolution": "Node" }, "include": ["vite.config.ts"] } diff --git a/packages/create-vite/template-svelte/jsconfig.json b/packages/create-vite/template-svelte/jsconfig.json index 42585941e160b7..ee5e92f298e484 100644 --- a/packages/create-vite/template-svelte/jsconfig.json +++ b/packages/create-vite/template-svelte/jsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "moduleResolution": "node", - "target": "esnext", - "module": "esnext", + "moduleResolution": "Node", + "target": "ESNext", + "module": "ESNext", /** * svelte-preprocess cannot figure out whether you have * a value or a type, so tell TypeScript to enforce using diff --git a/packages/create-vite/template-vue-ts/tsconfig.json b/packages/create-vite/template-vue-ts/tsconfig.json index bcc4abda4c57f0..d4aefa2c929dc2 100644 --- a/packages/create-vite/template-vue-ts/tsconfig.json +++ b/packages/create-vite/template-vue-ts/tsconfig.json @@ -1,16 +1,16 @@ { "compilerOptions": { - "target": "esnext", + "target": "ESNext", "useDefineForClassFields": true, - "module": "esnext", - "moduleResolution": "node", + "module": "ESNext", + "moduleResolution": "Node", "strict": true, "jsx": "preserve", "sourceMap": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, - "lib": ["esnext", "dom"], + "lib": ["ESNext", "DOM"], "skipLibCheck": true }, "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], diff --git a/packages/create-vite/template-vue-ts/tsconfig.node.json b/packages/create-vite/template-vue-ts/tsconfig.node.json index e993792cb12c9d..65dbdb96ae5dcf 100644 --- a/packages/create-vite/template-vue-ts/tsconfig.node.json +++ b/packages/create-vite/template-vue-ts/tsconfig.node.json @@ -1,8 +1,8 @@ { "compilerOptions": { "composite": true, - "module": "esnext", - "moduleResolution": "node" + "module": "ESNext", + "moduleResolution": "Node" }, "include": ["vite.config.ts"] } diff --git a/packages/plugin-legacy/CHANGELOG.md b/packages/plugin-legacy/CHANGELOG.md index 19bb068cc9502b..3332625765af00 100644 --- a/packages/plugin-legacy/CHANGELOG.md +++ b/packages/plugin-legacy/CHANGELOG.md @@ -1,3 +1,13 @@ +## 2.0.0-alpha.1 (2022-05-19) + +* fix: rewrite CJS specific funcs/vars in plugins (#8227) ([9baa70b](https://github.com/vitejs/vite/commit/9baa70b)), closes [#8227](https://github.com/vitejs/vite/issues/8227) +* fix(plugin-legacy): fail to get the fileName (#5250) ([c7fc1d4](https://github.com/vitejs/vite/commit/c7fc1d4)), closes [#5250](https://github.com/vitejs/vite/issues/5250) +* build!: bump targets (#8045) ([66efd69](https://github.com/vitejs/vite/commit/66efd69)), closes [#8045](https://github.com/vitejs/vite/issues/8045) +* feat!: relative base (#7644) ([09648c2](https://github.com/vitejs/vite/commit/09648c2)), closes [#7644](https://github.com/vitejs/vite/issues/7644) +* docs: use latest core-js unpkg link (#8190) ([102b678](https://github.com/vitejs/vite/commit/102b678)), closes [#8190](https://github.com/vitejs/vite/issues/8190) + + + ## 2.0.0-alpha.0 (2022-05-13) * chore: bump minors and rebuild lock (#8074) ([aeb5b74](https://github.com/vitejs/vite/commit/aeb5b74)), closes [#8074](https://github.com/vitejs/vite/issues/8074) diff --git a/packages/plugin-legacy/README.md b/packages/plugin-legacy/README.md index fc4167f4f1010f..bd581052e88801 100644 --- a/packages/plugin-legacy/README.md +++ b/packages/plugin-legacy/README.md @@ -122,9 +122,9 @@ The legacy plugin offers a way to use native `import()` in the modern build whil Polyfill specifier strings for `polyfills` and `modernPolyfills` can be either of the following: -- Any [`core-js` 3 sub import paths](https://unpkg.com/browse/core-js@3.8.2/) - e.g. `es/map` will import `core-js/es/map` +- Any [`core-js` 3 sub import paths](https://unpkg.com/browse/core-js@latest/) - e.g. `es/map` will import `core-js/es/map` -- Any [individual `core-js` 3 modules](https://unpkg.com/browse/core-js@3.8.2/modules/) - e.g. `es.array.iterator` will import `core-js/modules/es.array.iterator.js` +- Any [individual `core-js` 3 modules](https://unpkg.com/browse/core-js@latest/modules/) - e.g. `es.array.iterator` will import `core-js/modules/es.array.iterator.js` **Example** diff --git a/packages/plugin-legacy/package.json b/packages/plugin-legacy/package.json index 139253a9d9a795..bea89ef7bc492d 100644 --- a/packages/plugin-legacy/package.json +++ b/packages/plugin-legacy/package.json @@ -1,6 +1,6 @@ { "name": "@vitejs/plugin-legacy", - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "license": "MIT", "author": "Evan You", "files": [ diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts index 5fedb716f04f86..8e0cbf54a34333 100644 --- a/packages/plugin-legacy/src/index.ts +++ b/packages/plugin-legacy/src/index.ts @@ -1,6 +1,8 @@ /* eslint-disable node/no-extraneous-import */ import path from 'path' import { createHash } from 'crypto' +import { createRequire } from 'module' +import { fileURLToPath } from 'url' import { build } from 'vite' import MagicString from 'magic-string' import type { @@ -37,9 +39,9 @@ const legacyPolyfillId = 'vite-legacy-polyfill' const legacyEntryId = 'vite-legacy-entry' const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))` -const detectDynamicImportVarName = '__vite_is_dynamic_import_support' -const detectDynamicImportCode = `try{import("_").catch(()=>1);}catch(e){}window.${detectDynamicImportVarName}=true;` -const dynamicFallbackInlineCode = `!function(){if(window.${detectDynamicImportVarName})return;console.warn("vite: loading legacy build because dynamic import is unsupported, syntax error above should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();` +const detectModernBrowserVarName = '__vite_is_modern_browser' +const detectModernBrowserCode = `try{import(new URL(import.meta.url).href).catch(()=>1);}catch(e){}window.${detectModernBrowserVarName}=true;` +const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();` const forceDynamicImportUsage = `export function __vite_legacy_guard(){import('data:text/javascript,')};` @@ -129,11 +131,12 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { modernPolyfills ) await buildPolyfillChunk( - 'polyfills-modern', modernPolyfills, bundle, facadeToModernPolyfillMap, config.build, + 'es', + opts, options.externalSystemJS ) return @@ -158,19 +161,21 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { ) await buildPolyfillChunk( - 'polyfills-legacy', legacyPolyfills, bundle, facadeToLegacyPolyfillMap, // force using terser for legacy polyfill minification, since esbuild // isn't legacy-safe config.build, + 'iife', + opts, options.externalSystemJS ) } } } + const _require = createRequire(import.meta.url) const legacyPostPlugin: Plugin = { name: 'vite:legacy-post-process', enforce: 'post', @@ -306,7 +311,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { const { code, map } = babel.transform(raw, { babelrc: false, configFile: false, - compact: true, + compact: !!config.build.minify, sourceMaps, inputSourceMap: sourceMaps ? chunk.map : undefined, presets: [ @@ -331,7 +336,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { useBuiltIns: needPolyfills ? 'usage' : false, corejs: needPolyfills ? { - version: require('core-js/package.json').version, + version: _require('core-js/package.json').version, proposals: false } : undefined, @@ -438,7 +443,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { tags.push({ tag: 'script', attrs: { type: 'module' }, - children: detectDynamicImportCode, + children: detectModernBrowserCode, injectTo: 'head' }) tags.push({ @@ -546,18 +551,19 @@ export async function detectPolyfills( } async function buildPolyfillChunk( - name: string, imports: Set, bundle: OutputBundle, facadeToChunkMap: Map, buildOptions: BuildOptions, + format: 'iife' | 'es', + rollupOutputOptions: NormalizedOutputOptions, externalSystemJS?: boolean ) { let { minify, assetsDir } = buildOptions minify = minify ? 'terser' : false const res = await build({ // so that everything is resolved from here - root: __dirname, + root: path.dirname(fileURLToPath(import.meta.url)), configFile: false, logLevel: 'error', plugins: [polyfillsPlugin(imports, externalSystemJS)], @@ -568,10 +574,11 @@ async function buildPolyfillChunk( assetsDir, rollupOptions: { input: { - [name]: polyfillId + polyfills: polyfillId }, output: { - format: name.includes('legacy') ? 'iife' : 'es', + format, + entryFileNames: rollupOutputOptions.entryFileNames, manualChunks: undefined } } @@ -591,7 +598,7 @@ async function buildPolyfillChunk( } // add the chunk to the bundle - bundle[polyfillChunk.name] = polyfillChunk + bundle[polyfillChunk.fileName] = polyfillChunk } const polyfillId = '\0vite/legacy-polyfills' @@ -686,7 +693,7 @@ function wrapIIFEBabelPlugin(): BabelPlugin { export const cspHashes = [ createHash('sha256').update(safari10NoModuleFix).digest('base64'), createHash('sha256').update(systemJSInlineCode).digest('base64'), - createHash('sha256').update(detectDynamicImportCode).digest('base64'), + createHash('sha256').update(detectModernBrowserCode).digest('base64'), createHash('sha256').update(dynamicFallbackInlineCode).digest('base64') ] diff --git a/packages/plugin-legacy/tsconfig.json b/packages/plugin-legacy/tsconfig.json index c20adf0da4b86f..ddb60f864b7e6d 100644 --- a/packages/plugin-legacy/tsconfig.json +++ b/packages/plugin-legacy/tsconfig.json @@ -3,8 +3,8 @@ "exclude": ["**/*.spec.ts"], "compilerOptions": { "outDir": "dist", - "target": "ES2018", - "module": "CommonJS", + "target": "ES2020", + "module": "ES2020", "moduleResolution": "Node", "strict": true, "declaration": true, diff --git a/packages/plugin-react/CHANGELOG.md b/packages/plugin-react/CHANGELOG.md index a2e396912dc02d..e386d1f48babc8 100644 --- a/packages/plugin-react/CHANGELOG.md +++ b/packages/plugin-react/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.0.0-alpha.1 (2022-05-19) + +* fix: rewrite CJS specific funcs/vars in plugins (#8227) ([9baa70b](https://github.com/vitejs/vite/commit/9baa70b)), closes [#8227](https://github.com/vitejs/vite/issues/8227) +* build!: bump targets (#8045) ([66efd69](https://github.com/vitejs/vite/commit/66efd69)), closes [#8045](https://github.com/vitejs/vite/issues/8045) +* chore: enable `import/no-duplicates` eslint rule (#8199) ([11243de](https://github.com/vitejs/vite/commit/11243de)), closes [#8199](https://github.com/vitejs/vite/issues/8199) + + + ## 2.0.0-alpha.0 (2022-05-13) * chore: restore-jsx.spec.ts lint (#8004) ([f1af941](https://github.com/vitejs/vite/commit/f1af941)), closes [#8004](https://github.com/vitejs/vite/issues/8004) diff --git a/packages/plugin-react/package.json b/packages/plugin-react/package.json index 98dab8b095de4f..68169a451ccb6e 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.0", + "version": "2.0.0-alpha.1", "license": "MIT", "author": "Evan You", "contributors": [ diff --git a/packages/plugin-react/src/fast-refresh.ts b/packages/plugin-react/src/fast-refresh.ts index 6bff7d94fa023b..708021f28a2665 100644 --- a/packages/plugin-react/src/fast-refresh.ts +++ b/packages/plugin-react/src/fast-refresh.ts @@ -1,11 +1,13 @@ import fs from 'fs' import path from 'path' +import { createRequire } from 'module' import type { types as t } from '@babel/core' export const runtimePublicPath = '/@react-refresh' +const _require = createRequire(import.meta.url) const reactRefreshDir = path.dirname( - require.resolve('react-refresh/package.json') + _require.resolve('react-refresh/package.json') ) const runtimeFilePath = path.join( reactRefreshDir, diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index df97899522605f..63c950ebf46d8c 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -41,7 +41,9 @@ export interface Options { /** * Babel configuration applied in both dev and prod. */ - babel?: BabelOptions + babel?: + | BabelOptions + | ((id: string, options: { ssr?: boolean }) => BabelOptions) } export type BabelOptions = Omit< @@ -67,13 +69,21 @@ export interface ReactBabelOptions extends BabelOptions { } } +type ReactBabelHook = ( + babelConfig: ReactBabelOptions, + context: ReactBabelHookContext, + config: ResolvedConfig +) => void + +type ReactBabelHookContext = { ssr: boolean; id: string } + declare module 'vite' { export interface Plugin { api?: { /** * Manipulate the Babel options of `@vitejs/plugin-react` */ - reactBabel?: (options: ReactBabelOptions, config: ResolvedConfig) => void + reactBabel?: ReactBabelHook } } } @@ -86,21 +96,14 @@ export default function viteReact(opts: Options = {}): PluginOption[] { let projectRoot = process.cwd() let skipFastRefresh = opts.fastRefresh === false let skipReactImport = false + let runPluginOverrides = ( + options: ReactBabelOptions, + context: ReactBabelHookContext + ) => false + let staticBabelOptions: ReactBabelOptions | undefined const useAutomaticRuntime = opts.jsxRuntime !== 'classic' - const babelOptions = { - babelrc: false, - configFile: false, - ...opts.babel - } as ReactBabelOptions - - babelOptions.plugins ||= [] - babelOptions.presets ||= [] - babelOptions.overrides ||= [] - babelOptions.parserOpts ||= {} as any - babelOptions.parserOpts.plugins ||= [] - // Support patterns like: // - import * as React from 'react'; // - import React from 'react'; @@ -141,11 +144,22 @@ export default function viteReact(opts: Options = {}): PluginOption[] { `[@vitejs/plugin-react] You should stop using "${plugin.name}" ` + `since this plugin conflicts with it.` ) + }) + + runPluginOverrides = (babelOptions, context) => { + const hooks = config.plugins + .map((plugin) => plugin.api?.reactBabel) + .filter(Boolean) as ReactBabelHook[] - if (plugin.api?.reactBabel) { - plugin.api.reactBabel(babelOptions, config) + if (hooks.length > 0) { + return (runPluginOverrides = (babelOptions) => { + hooks.forEach((hook) => hook(babelOptions, context, config)) + return true + })(babelOptions) } - }) + runPluginOverrides = () => false + return false + } }, async transform(code, id, options) { const ssr = typeof options === 'boolean' ? options : options?.ssr === true @@ -162,6 +176,18 @@ export default function viteReact(opts: Options = {}): PluginOption[] { const isProjectFile = !isNodeModules && (id[0] === '\0' || id.startsWith(projectRoot + '/')) + let babelOptions = staticBabelOptions + if (typeof opts.babel === 'function') { + const rawOptions = opts.babel(id, { ssr }) + babelOptions = createBabelOptions(rawOptions) + runPluginOverrides(babelOptions, { ssr, id: id }) + } else if (!babelOptions) { + babelOptions = createBabelOptions(opts.babel) + if (!runPluginOverrides(babelOptions, { ssr, id: id })) { + staticBabelOptions = babelOptions + } + } + const plugins = isProjectFile ? [...babelOptions.plugins] : [] let useFastRefresh = false @@ -368,3 +394,19 @@ viteReact.preambleCode = preambleCode function loadPlugin(path: string): Promise { return import(path).then((module) => module.default || module) } + +function createBabelOptions(rawOptions?: BabelOptions) { + const babelOptions = { + babelrc: false, + configFile: false, + ...rawOptions + } as ReactBabelOptions + + babelOptions.plugins ||= [] + babelOptions.presets ||= [] + babelOptions.overrides ||= [] + babelOptions.parserOpts ||= {} as any + babelOptions.parserOpts.plugins ||= [] + + return babelOptions +} diff --git a/packages/plugin-react/src/jsx-runtime/babel-import-to-require.ts b/packages/plugin-react/src/jsx-runtime/babel-import-to-require.ts index 01e4cc4c37d478..cd6608221512c9 100644 --- a/packages/plugin-react/src/jsx-runtime/babel-import-to-require.ts +++ b/packages/plugin-react/src/jsx-runtime/babel-import-to-require.ts @@ -1,5 +1,4 @@ import type * as babelCore from '@babel/core' -import type { Visitor, types as t } from '@babel/core' /** * Replace this: @@ -11,13 +10,13 @@ import type { Visitor, types as t } from '@babel/core' * var _jsx = require("react/jsx-runtime").jsx */ export function babelImportToRequire({ types: t }: typeof babelCore): { - visitor: Visitor + visitor: babelCore.Visitor } { return { visitor: { ImportDeclaration(path) { const decl = path.node - const spec = decl.specifiers[0] as t.ImportSpecifier + const spec = decl.specifiers[0] as babelCore.types.ImportSpecifier path.replaceWith( t.variableDeclaration('var', [ diff --git a/packages/plugin-react/src/jsx-runtime/restore-jsx.ts b/packages/plugin-react/src/jsx-runtime/restore-jsx.ts index 2c49f508c8b5be..28825918895dde 100644 --- a/packages/plugin-react/src/jsx-runtime/restore-jsx.ts +++ b/packages/plugin-react/src/jsx-runtime/restore-jsx.ts @@ -1,9 +1,11 @@ import type * as babelCore from '@babel/core' -import type { PluginItem, types as t } from '@babel/core' -type RestoredJSX = [result: t.File | null | undefined, isCommonJS: boolean] +type RestoredJSX = [ + result: babelCore.types.File | null | undefined, + isCommonJS: boolean +] -let babelRestoreJSX: Promise | undefined +let babelRestoreJSX: Promise | undefined const jsxNotFound: RestoredJSX = [null, false] diff --git a/packages/plugin-react/tsconfig.json b/packages/plugin-react/tsconfig.json index c20adf0da4b86f..ddb60f864b7e6d 100644 --- a/packages/plugin-react/tsconfig.json +++ b/packages/plugin-react/tsconfig.json @@ -3,8 +3,8 @@ "exclude": ["**/*.spec.ts"], "compilerOptions": { "outDir": "dist", - "target": "ES2018", - "module": "CommonJS", + "target": "ES2020", + "module": "ES2020", "moduleResolution": "Node", "strict": true, "declaration": true, diff --git a/packages/plugin-vue-jsx/CHANGELOG.md b/packages/plugin-vue-jsx/CHANGELOG.md index 70f70a243b326f..57d07e2a1f7802 100644 --- a/packages/plugin-vue-jsx/CHANGELOG.md +++ b/packages/plugin-vue-jsx/CHANGELOG.md @@ -1,3 +1,10 @@ +## 2.0.0-alpha.1 (2022-05-19) + +* fix: rewrite CJS specific funcs/vars in plugins (#8227) ([9baa70b](https://github.com/vitejs/vite/commit/9baa70b)), closes [#8227](https://github.com/vitejs/vite/issues/8227) +* build!: bump targets (#8045) ([66efd69](https://github.com/vitejs/vite/commit/66efd69)), closes [#8045](https://github.com/vitejs/vite/issues/8045) + + + ## 2.0.0-alpha.0 (2022-05-13) * chore: revert vitejs/vite#8152 (#8161) ([85b8b55](https://github.com/vitejs/vite/commit/85b8b55)), closes [vitejs/vite#8152](https://github.com/vitejs/vite/issues/8152) [#8161](https://github.com/vitejs/vite/issues/8161) diff --git a/packages/plugin-vue-jsx/package.json b/packages/plugin-vue-jsx/package.json index 309abf9e6745de..8764b168fb8069 100644 --- a/packages/plugin-vue-jsx/package.json +++ b/packages/plugin-vue-jsx/package.json @@ -1,6 +1,6 @@ { "name": "@vitejs/plugin-vue-jsx", - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "license": "MIT", "author": "Evan You", "files": [ diff --git a/packages/plugin-vue-jsx/src/index.ts b/packages/plugin-vue-jsx/src/index.ts index e23f0031b69bd1..c96fe2964e83b0 100644 --- a/packages/plugin-vue-jsx/src/index.ts +++ b/packages/plugin-vue-jsx/src/index.ts @@ -73,7 +73,7 @@ function vueJsxPlugin(options: Options = {}): Plugin { } }, - transform(code, id, opt) { + async transform(code, id, opt) { const ssr = typeof opt === 'boolean' ? opt : (opt && opt.ssr) === true const { include, @@ -91,7 +91,10 @@ function vueJsxPlugin(options: Options = {}): Plugin { const plugins = [importMeta, [jsx, babelPluginOptions], ...babelPlugins] if (id.endsWith('.tsx') || filepath.endsWith('.tsx')) { plugins.push([ - require('@babel/plugin-transform-typescript'), + // @ts-ignore missing type + await import('@babel/plugin-transform-typescript').then( + (r) => r.default + ), // @ts-ignore { isTSX: true, allowExtensions: true } ]) diff --git a/packages/plugin-vue-jsx/tsconfig.json b/packages/plugin-vue-jsx/tsconfig.json index c20adf0da4b86f..ddb60f864b7e6d 100644 --- a/packages/plugin-vue-jsx/tsconfig.json +++ b/packages/plugin-vue-jsx/tsconfig.json @@ -3,8 +3,8 @@ "exclude": ["**/*.spec.ts"], "compilerOptions": { "outDir": "dist", - "target": "ES2018", - "module": "CommonJS", + "target": "ES2020", + "module": "ES2020", "moduleResolution": "Node", "strict": true, "declaration": true, diff --git a/packages/plugin-vue/CHANGELOG.md b/packages/plugin-vue/CHANGELOG.md index e9ecc698fef094..8c17f381fc24ca 100644 --- a/packages/plugin-vue/CHANGELOG.md +++ b/packages/plugin-vue/CHANGELOG.md @@ -1,3 +1,14 @@ +## 3.0.0-alpha.1 (2022-05-19) + +* fix: rewrite CJS specific funcs/vars in plugins (#8227) ([9baa70b](https://github.com/vitejs/vite/commit/9baa70b)), closes [#8227](https://github.com/vitejs/vite/issues/8227) +* fix(plugin-vue): regenerate scoped css in build watch, fix #7980 (#7989) ([dc00225](https://github.com/vitejs/vite/commit/dc00225)), closes [#7980](https://github.com/vitejs/vite/issues/7980) [#7989](https://github.com/vitejs/vite/issues/7989) +* fix(plugin-vue): use server.origin when building base for transformAssetUrls (#8077) ([2f7a490](https://github.com/vitejs/vite/commit/2f7a490)), closes [#8077](https://github.com/vitejs/vite/issues/8077) +* build!: bump targets (#8045) ([66efd69](https://github.com/vitejs/vite/commit/66efd69)), closes [#8045](https://github.com/vitejs/vite/issues/8045) +* chore: enable `import/no-duplicates` eslint rule (#8199) ([11243de](https://github.com/vitejs/vite/commit/11243de)), closes [#8199](https://github.com/vitejs/vite/issues/8199) +* docs(plugin-vue): clarify asset url handling (#8184) ([32c75e2](https://github.com/vitejs/vite/commit/32c75e2)), closes [#8184](https://github.com/vitejs/vite/issues/8184) + + + ## 3.0.0-alpha.0 (2022-05-13) * chore: bump minors and rebuild lock (#8074) ([aeb5b74](https://github.com/vitejs/vite/commit/aeb5b74)), closes [#8074](https://github.com/vitejs/vite/issues/8074) diff --git a/packages/plugin-vue/README.md b/packages/plugin-vue/README.md index a232982e8aed59..ae848051cecd10 100644 --- a/packages/plugin-vue/README.md +++ b/packages/plugin-vue/README.md @@ -51,6 +51,40 @@ export interface Options { } ``` +## Asset URL handling + +When `@vitejs/plugin-vue` compiles the `