Skip to content

Commit

Permalink
chore: merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
patak-dev committed Jul 1, 2022
2 parents aed31c7 + cad27ee commit 452bee2
Show file tree
Hide file tree
Showing 19 changed files with 103 additions and 49 deletions.
42 changes: 7 additions & 35 deletions docs/guide/comparisons.md
@@ -1,38 +1,4 @@
# Comparisons with Other No-Bundler Solutions

## Snowpack

[Snowpack](https://www.snowpack.dev/) is also a no-bundle native ESM dev server that is very similar in scope to Vite. Aside from different implementation details, the two projects share a lot in terms of technical advantages over traditional tooling. Vite's dependency pre-bundling is also inspired by Snowpack v1 (now [`esinstall`](https://github.com/snowpackjs/snowpack/tree/main/esinstall)). Some of the main differences between the two projects are:

**Production Build**

Snowpack's default build output is unbundled: it transforms each file into separate built modules, which can then be fed into different "optimizers" that perform the actual bundling. The benefit of this is that you can choose between different end-bundlers to fit specific needs (e.g. webpack, Rollup, or even esbuild), the downside is that it's a bit of a fragmented experience - for example, the esbuild optimizer is still unstable, the Rollup optimizer is not officially maintained, and different optimizers have different output and configurations.

Vite opts to have a deeper integration with one single bundler (Rollup) in order to provide a more streamlined experience. It also allows Vite to support a [Universal Plugin API](./api-plugin) that works for both dev and build.

Due to a more integrated build process, Vite supports a wide range of features that are currently not available in Snowpack build optimizers:

- [Multi-Page Support](./build#multi-page-app)
- [Library Mode](./build#library-mode)
- [Automatic CSS code-splitting](./features#css-code-splitting)
- [Optimized async chunk loading](./features#async-chunk-loading-optimization)
- Official [legacy mode plugin](https://github.com/vitejs/vite/tree/main/packages/plugin-legacy) that generates dual modern/legacy bundles and auto delivers the right bundle based on browser support.

**Faster Dependency Pre-Bundling**

Vite uses [esbuild](https://esbuild.github.io/) instead of Rollup for dependency pre-bundling. This results in significant performance improvements in terms of cold server start and re-bundling on dependency invalidations.

**Monorepo Support**

Vite is designed to handle monorepo setups and we have users successfully using it with Yarn, Yarn 2, and PNPM based monorepos.

**CSS Pre-Processor Support**

Vite provides more refined support for Sass and Less, including improved `@import` resolution (aliases and npm dependencies) and [automatic `url()` rebasing for inlined files](./features#import-inlining-and-rebasing).

**First Class Vue Support**

Vite was initially created to serve as the future foundation of [Vue.js](https://vuejs.org/) tooling. Although as of 2.0 Vite is now fully framework-agnostic, the official Vue plugin still provides first-class support for Vue's Single File Component format, covering all advanced features such as template asset reference resolving, `<script setup>`, `<style module>`, custom blocks and more. In addition, Vite provides fine-grained HMR for Vue SFCs. For example, updating the `<template>` or `<style>` of an SFC will perform hot updates without resetting its state.
# Comparisons

## WMR

Expand All @@ -47,3 +13,9 @@ WMR is mainly designed for [Preact](https://preactjs.com/) projects, and offers
`@web/dev-server` is a bit lower-level in terms of scope. It does not provide official framework integrations, and requires manually setting up a Rollup configuration for the production build.

Overall, Vite is a more opinionated / higher-level tool that aims to provide a more out-of-the-box workflow. That said, the `@web` umbrella project contains many other excellent tools that may benefit Vite users as well.

## Snowpack

[Snowpack](https://www.snowpack.dev/) was also a no-bundle native ESM dev server, very similar in scope to Vite. The project is no longer being maintained. The Snowpack team is now working on [Astro](https://astro.build/), a static site builder powered by Vite. The Astro team is now an active player in the ecosystem, and they are helping to improve Vite.

Aside from different implementation details, the two projects shared a lot in terms of technical advantages over traditional tooling. Vite's dependency pre-bundling is also inspired by Snowpack v1 (now [`esinstall`](https://github.com/snowpackjs/snowpack/tree/main/esinstall)). Some of the main differences between the two projects are listed in [the v2 Comparisons Guide](https://v2.vitejs.dev/guide/comparisons).
4 changes: 2 additions & 2 deletions packages/plugin-react/src/index.ts
Expand Up @@ -165,10 +165,10 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
.filter(Boolean) as ReactBabelHook[]

if (hooks.length > 0) {
return (runPluginOverrides = (babelOptions) => {
return (runPluginOverrides = (babelOptions, context) => {
hooks.forEach((hook) => hook(babelOptions, context, config))
return true
})(babelOptions)
})(babelOptions, context)
}
runPluginOverrides = () => false
return false
Expand Down
6 changes: 4 additions & 2 deletions packages/vite/src/node/config.ts
Expand Up @@ -639,14 +639,16 @@ export async function resolveConfig(
if (middlewareMode === 'ssr') {
logger.warn(
colors.yellow(
`server.middlewareMode 'ssr' is now deprecated, use server.middlewareMode true and appType 'custom'`
`Setting server.middlewareMode to 'ssr' is deprecated, set server.middlewareMode to \`true\`${
config.appType === 'custom' ? '' : ` and appType to 'custom'`
} instead`
)
)
}
if (middlewareMode === 'html') {
logger.warn(
colors.yellow(
`server.middlewareMode 'html' is now deprecated, use server.middlewareMode true`
`Setting server.middlewareMode to 'html' is deprecated, set server.middlewareMode to \`true\` instead`
)
)
}
Expand Down
3 changes: 2 additions & 1 deletion packages/vite/src/node/server/index.ts
Expand Up @@ -291,8 +291,9 @@ export async function createServer(
const { ignored = [], ...watchOptions } = serverConfig.watch || {}
const watcher = chokidar.watch(path.resolve(root), {
ignored: [
'**/node_modules/**',
'**/.git/**',
'**/node_modules/**',
'**/test-results/**', // Playwright
...(Array.isArray(ignored) ? ignored : [ignored])
],
ignoreInitial: true,
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/utils.ts
Expand Up @@ -480,7 +480,7 @@ export function generateCodeFrame(
const lineLength = lines[j].length
if (j === i) {
// push underline
const pad = start - (count - lineLength) + 1
const pad = Math.max(start - (count - lineLength) + 1, 0)
const length = Math.max(
1,
end > count ? lineLength - pad : end - start
Expand Down
11 changes: 11 additions & 0 deletions playground/css/__tests__/css.spec.ts
Expand Up @@ -349,6 +349,11 @@ test('PostCSS dir-dependency', async () => {
}
})

test('import dependency includes css import', async () => {
expect(await getColor('.css-js-dep')).toBe('green')
expect(await getColor('.css-js-dep-module')).toBe('green')
})

test('URL separation', async () => {
const urlSeparated = await page.$('.url-separated')
const baseUrl = 'url(images/dog.webp)'
Expand Down Expand Up @@ -426,3 +431,9 @@ test('PostCSS source.input.from includes query', async () => {
// should resolve assets
expect(code).toContain('/postcss-source-input.css?query=foo')
})

test('aliased css has content', async () => {
expect(await getColor('.aliased')).toBe('blue')
expect(await page.textContent('.aliased-content')).toMatch('.aliased')
expect(await getColor('.aliased-module')).toBe('blue')
})
3 changes: 3 additions & 0 deletions playground/css/aliased/bar.module.css
@@ -0,0 +1,3 @@
.aliasedModule {
color: blue;
}
3 changes: 3 additions & 0 deletions playground/css/aliased/foo.css
@@ -0,0 +1,3 @@
.aliased {
color: blue;
}
3 changes: 3 additions & 0 deletions playground/css/css-js-dep/bar.module.css
@@ -0,0 +1,3 @@
.cssJsDepModule {
color: green;
}
3 changes: 3 additions & 0 deletions playground/css/css-js-dep/foo.css
@@ -0,0 +1,3 @@
.css-js-dep {
color: green;
}
4 changes: 4 additions & 0 deletions playground/css/css-js-dep/index.js
@@ -0,0 +1,4 @@
import './foo.css'
import barModuleClasses from './bar.module.css'

export { barModuleClasses }
7 changes: 7 additions & 0 deletions playground/css/css-js-dep/package.json
@@ -0,0 +1,7 @@
{
"name": "css-js-dep",
"private": true,
"type": "module",
"version": "1.0.0",
"main": "index.js"
}
12 changes: 12 additions & 0 deletions playground/css/index.html
Expand Up @@ -117,6 +117,13 @@ <h1>CSS</h1>
PostCSS dir-dependency (file 3): this should be grey too
</p>

<p class="css-js-dep">
import dependency includes 'import "./foo.css"': this should be green
</p>
<p class="css-js-dep-module">
import dependency includes 'import "./bar.module.css"': this should be green
</p>

<p class="url-separated">
URL separation preservation: should have valid background-image
</p>
Expand All @@ -141,6 +148,11 @@ <h1>CSS</h1>

<p>PostCSS source.input.from. Should include query</p>
<pre class="postcss-source-input"></pre>

<p>Aliased</p>
<p class="aliased">import '#alias': this should be blue</p>
<pre class="aliased-content"></pre>
<p class="aliased-module">import '#alias-module': this should be blue</p>
</div>

<script type="module" src="./main.js"></script>
12 changes: 12 additions & 0 deletions playground/css/main.js
Expand Up @@ -47,6 +47,11 @@ text('.charset-css', charset)
import './dep.css'
import './glob-dep.css'

import { barModuleClasses } from 'css-js-dep'
document
.querySelector('.css-js-dep-module')
.classList.add(barModuleClasses.cssJsDepModule)

function text(el, text) {
document.querySelector(el).textContent = text
}
Expand Down Expand Up @@ -92,3 +97,10 @@ text('.imported-css-globEager', JSON.stringify(globEager, null, 2))

import postcssSourceInput from './postcss-source-input.css?query=foo'
text('.postcss-source-input', postcssSourceInput)

import aliasContent from '#alias'
text('.aliased-content', aliasContent)
import aliasModule from '#alias-module'
document
.querySelector('.aliased-module')
.classList.add(aliasModule.aliasedModule)
1 change: 1 addition & 0 deletions playground/css/package.json
Expand Up @@ -13,6 +13,7 @@
},
"devDependencies": {
"css-dep": "link:./css-dep",
"css-js-dep": "file:./css-js-dep",
"fast-glob": "^3.2.11",
"less": "^4.1.3",
"postcss-nested": "^5.0.6",
Expand Down
4 changes: 3 additions & 1 deletion playground/css/vite.config.js
Expand Up @@ -10,7 +10,9 @@ module.exports = {
resolve: {
alias: {
'@': __dirname,
spacefolder: __dirname + '/folder with space'
spacefolder: __dirname + '/folder with space',
'#alias': __dirname + '/aliased/foo.css',
'#alias-module': __dirname + '/aliased/bar.module.css'
}
},
css: {
Expand Down
12 changes: 8 additions & 4 deletions playground/glob-import/__tests__/glob-import.spec.ts
Expand Up @@ -81,11 +81,15 @@ const relativeRawResult = {
}

test('should work', async () => {
expect(await page.textContent('.result')).toBe(
JSON.stringify(allResult, null, 2)
await untilUpdated(
() => page.textContent('.result'),
JSON.stringify(allResult, null, 2),
true
)
expect(await page.textContent('.result-node_modules')).toBe(
JSON.stringify(nodeModulesResult, null, 2)
await untilUpdated(
() => page.textContent('.result-node_modules'),
JSON.stringify(nodeModulesResult, null, 2),
true
)
})

Expand Down
4 changes: 2 additions & 2 deletions playground/ssr-vue/vite.config.noexternal.js
@@ -1,8 +1,8 @@
const config = require('./vite.config.js')
import config from './vite.config.js'
/**
* @type {import('vite').UserConfig}
*/
module.exports = Object.assign(config, {
export default Object.assign(config, {
ssr: {
noExternal: /./
},
Expand Down
16 changes: 15 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 452bee2

Please sign in to comment.