Skip to content

Commit

Permalink
chore: merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Sep 30, 2022
2 parents 5366624 + 931d69b commit a2d5715
Show file tree
Hide file tree
Showing 35 changed files with 238 additions and 114 deletions.
14 changes: 13 additions & 1 deletion docs/guide/api-hmr.md
Expand Up @@ -125,7 +125,18 @@ Calling `import.meta.hot.decline()` indicates this module is not hot-updatable,
## `hot.invalidate()`
For now, calling `import.meta.hot.invalidate()` simply reloads the page.
A self-accepting module may realize during runtime that it can't handle a HMR update, and so the update needs to be forcefully propagated to importers. By calling `import.meta.hot.invalidate()`, the HMR server will invalidate the importers of the caller, as if the caller wasn't self-accepting.
Note that you should always call `import.meta.hot.accept` even if you plan to call `invalidate` immediately afterwards, or else the HMR client won't listen for future changes to the self-accepting module. To communicate your intent clearly, we recommend calling `invalidate` within the `accept` callback like so:
```ts
import.meta.hot.accept(module => {
// You may use the new module instance to decide whether to invalidate.
if (cannotHandleUpdate(module)) {
import.meta.hot.invalidate()
}
})
```
## `hot.on(event, cb)`
Expand All @@ -136,6 +147,7 @@ The following HMR events are dispatched by Vite automatically:
- `'vite:beforeUpdate'` when an update is about to be applied (e.g. a module will be replaced)
- `'vite:beforeFullReload'` when a full reload is about to occur
- `'vite:beforePrune'` when modules that are no longer needed are about to be pruned
- `'vite:invalidate'` when a module is invalidated with `import.meta.hot.invalidate()`
- `'vite:error'` when an error occurs (e.g. syntax error)
Custom HMR events can also be sent from plugins. See [handleHotUpdate](./api-plugin#handlehotupdate) for more details.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -62,7 +62,7 @@
"@typescript-eslint/parser": "^5.38.0",
"conventional-changelog-cli": "^2.2.2",
"esbuild": "^0.14.47",
"eslint": "^8.23.1",
"eslint": "^8.24.0",
"eslint-define-config": "^1.7.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.1.0",
Expand All @@ -88,7 +88,7 @@
"typescript": "^4.6.4",
"unbuild": "^0.8.11",
"vite": "workspace:*",
"vitepress": "^1.0.0-alpha.15",
"vitepress": "^1.0.0-alpha.16",
"vitest": "^0.23.4",
"vue": "^3.2.39"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-legacy/package.json
Expand Up @@ -36,7 +36,7 @@
"homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme",
"dependencies": {
"@babel/standalone": "^7.19.2",
"core-js": "^3.25.2",
"core-js": "^3.25.3",
"magic-string": "^0.26.4",
"regenerator-runtime": "^0.13.9",
"systemjs": "^6.12.6"
Expand Down
1 change: 0 additions & 1 deletion packages/plugin-vue-jsx/package.json
Expand Up @@ -36,7 +36,6 @@
"homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-vue-jsx#readme",
"dependencies": {
"@babel/core": "^7.19.1",
"@babel/plugin-syntax-import-meta": "^7.10.4",
"@babel/plugin-transform-typescript": "^7.19.1",
"@vue/babel-plugin-jsx": "^1.1.1"
},
Expand Down
4 changes: 1 addition & 3 deletions packages/plugin-vue-jsx/src/index.ts
Expand Up @@ -3,8 +3,6 @@ import path from 'node:path'
import type { types } from '@babel/core'
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 'vite'
import type { ComponentOptions } from 'vue'
import type { Plugin } from 'vite'
Expand Down Expand Up @@ -83,7 +81,7 @@ function vueJsxPlugin(options: Options = {}): Plugin {
// use id for script blocks in Vue SFCs (e.g. `App.vue?vue&type=script&lang.jsx`)
// use filepath for plain jsx files (e.g. App.jsx)
if (filter(id) || filter(filepath)) {
const plugins = [importMeta, [jsx, babelPluginOptions], ...babelPlugins]
const plugins = [[jsx, babelPluginOptions], ...babelPlugins]
if (id.endsWith('.tsx') || filepath.endsWith('.tsx')) {
plugins.push([
// @ts-ignore missing type
Expand Down
6 changes: 3 additions & 3 deletions packages/vite/src/client/client.ts
Expand Up @@ -546,10 +546,10 @@ export function createHotContext(ownerPath: string): ViteHotContext {
// eslint-disable-next-line @typescript-eslint/no-empty-function
decline() {},

// tell the server to re-perform hmr propagation from this module as root
invalidate() {
// TODO should tell the server to re-perform hmr propagation
// from this module as root
location.reload()
notifyListeners('vite:invalidate', { path: ownerPath })
this.send('vite:invalidate', { path: ownerPath })
},

// custom events
Expand Down
42 changes: 23 additions & 19 deletions packages/vite/src/client/overlay.ts
Expand Up @@ -9,6 +9,17 @@ const template = /*html*/ `
left: 0;
width: 100%;
height: 100%;
--monospace: 'SFMono-Regular', Consolas,
'Liberation Mono', Menlo, Courier, monospace;
--red: #ff5555;
--yellow: #e2aa53;
--purple: #cfa4ff;
--cyan: #2dd9da;
--dim: #c9c9c9;
--window-background: #181818;
--window-color: #d8d8d8;
}
.backdrop {
Expand All @@ -21,24 +32,17 @@ const template = /*html*/ `
overflow-y: scroll;
margin: 0;
background: rgba(0, 0, 0, 0.66);
--monospace: 'SFMono-Regular', Consolas,
'Liberation Mono', Menlo, Courier, monospace;
--red: #ff5555;
--yellow: #e2aa53;
--purple: #cfa4ff;
--cyan: #2dd9da;
--dim: #c9c9c9;
}
.window {
font-family: var(--monospace);
line-height: 1.5;
width: 800px;
color: #d8d8d8;
color: var(--window-color);
margin: 30px auto;
padding: 25px 40px;
position: relative;
background: #181818;
background: var(--window-background);
border-radius: 6px 6px 8px 8px;
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22);
overflow: hidden;
Expand Down Expand Up @@ -108,13 +112,13 @@ code {
cursor: pointer;
}
</style>
<div class="backdrop">
<div class="window">
<pre class="message"><span class="plugin"></span><span class="message-body"></span></pre>
<pre class="file"></pre>
<pre class="frame"></pre>
<pre class="stack"></pre>
<div class="tip">
<div class="backdrop" part="backdrop">
<div class="window" part="window">
<pre class="message" part="message"><span class="plugin"></span><span class="message-body"></span></pre>
<pre class="file" part="file"></pre>
<pre class="frame" part="frame"></pre>
<pre class="stack" part="stack"></pre>
<div class="tip" part="tip">
Click outside or fix the code to dismiss.<br>
You can also disable this overlay by setting
<code>server.hmr.overlay</code> to <code>false</code> in <code>vite.config.js.</code>
Expand All @@ -132,7 +136,7 @@ const { HTMLElement = class {} as typeof globalThis.HTMLElement } = globalThis
export class ErrorOverlay extends HTMLElement {
root: ShadowRoot

constructor(err: ErrorPayload['err']) {
constructor(err: ErrorPayload['err'], links = true) {
super()
this.root = this.attachShadow({ mode: 'open' })
this.root.innerHTML = template
Expand All @@ -149,15 +153,15 @@ export class ErrorOverlay extends HTMLElement {

const [file] = (err.loc?.file || err.id || 'unknown file').split(`?`)
if (err.loc) {
this.text('.file', `${file}:${err.loc.line}:${err.loc.column}`, true)
this.text('.file', `${file}:${err.loc.line}:${err.loc.column}`, links)
} else if (err.id) {
this.text('.file', file)
}

if (hasFrame) {
this.text('.frame', err.frame!.trim())
}
this.text('.stack', err.stack, true)
this.text('.stack', err.stack, links)

this.root.querySelector('.window')!.addEventListener('click', (e) => {
e.stopPropagation()
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/config.ts
Expand Up @@ -126,7 +126,7 @@ export interface UserConfig {
/**
* Directory to serve as plain static assets. Files in this directory are
* served and copied to build dist dir as-is without transform. The value
* can be either an absolute file system path or a path relative to <root>.
* can be either an absolute file system path or a path relative to project root.
*
* Set to `false` or an empty string to disable copied static assets to build dist dir.
* @default 'public'
Expand All @@ -137,7 +137,7 @@ export interface UserConfig {
* deps or some other cache files that generated by vite, which can improve
* the performance. You can use `--force` flag or manually delete the directory
* to regenerate the cache files. The value can be either an absolute file
* system path or a path relative to <root>.
* system path or a path relative to project root.
* Default to `.vite` when no `package.json` is detected.
* @default 'node_modules/.vite'
*/
Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/index.ts
Expand Up @@ -102,7 +102,12 @@ export type {
PrunePayload,
ErrorPayload
} from 'types/hmrPayload'
export type { CustomEventMap, InferCustomEventPayload } from 'types/customEvent'
export type {
CustomEventMap,
InferCustomEventPayload,
InvalidatePayload
} from 'types/customEvent'
// [deprecated: use vite/client/types instead]
export type {
ImportGlobFunction,
ImportGlobEagerFunction,
Expand Down
7 changes: 6 additions & 1 deletion packages/vite/src/node/optimizer/index.ts
Expand Up @@ -1042,7 +1042,12 @@ function isSingleDefaultExport(exports: readonly string[]) {
return exports.length === 1 && exports[0] === 'default'
}

const lockfileFormats = ['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml']
const lockfileFormats = [
'package-lock.json',
'yarn.lock',
'pnpm-lock.yaml',
'bun.lockb'
]

export function getDepHash(config: ResolvedConfig, ssr: boolean): string {
let content = lookupFile(config.root, lockfileFormats) || ''
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugin.ts
Expand Up @@ -108,7 +108,7 @@ export interface Plugin extends RollupPlugin {
* - bundle?: rollup.OutputBundle (only present during build)
*
* It can either return a transformed string, or a list of html tag
* descriptors that will be injected into the <head> or <body>.
* descriptors that will be injected into the `<head>` or `<body>`.
*
* By default the transform is applied **after** vite's internal html
* transform. If you need to apply the transform before vite, use an object:
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/css.ts
Expand Up @@ -563,7 +563,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
// the legacy build should avoid inserting entry CSS modules here, they
// will be collected into `chunk.viteMetadata.importedCss` and injected
// later by the `'vite:build-html'` plugin into the `index.html`
if (chunk.isEntry) {
if (chunk.isEntry && !config.build.lib) {
return null
}
chunkCSS = await finalizeCss(chunkCSS, true, config)
Expand Down
6 changes: 3 additions & 3 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -147,7 +147,7 @@ function extractImportedBindings(
* ```
*
* - CSS imports are appended with `.js` since both the js module and the actual
* css (referenced via <link>) may go through the transform pipeline:
* css (referenced via `<link>`) may go through the transform pipeline:
*
* ```js
* import './style.css'
Expand Down Expand Up @@ -187,8 +187,8 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {

const start = performance.now()
await init
let imports: readonly ImportSpecifier[] = []
let exports: readonly ExportSpecifier[] = []
let imports!: readonly ImportSpecifier[]
let exports!: readonly ExportSpecifier[]
source = stripBomTag(source)
try {
;[imports, exports] = parseImports(source)
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/importAnalysisBuild.ts
Expand Up @@ -439,7 +439,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
// dynamic import to constant json may get inlined.
if (chunk.type === 'chunk' && chunk.code.indexOf(preloadMarker) > -1) {
const code = chunk.code
let imports: ImportSpecifier[] = []
let imports!: ImportSpecifier[]
try {
imports = parseImports(code)[0].filter((i) => i.d > -1)
} catch (e: any) {
Expand Down
8 changes: 6 additions & 2 deletions packages/vite/src/node/plugins/resolve.ts
Expand Up @@ -44,6 +44,7 @@ import type { DepsOptimizer } from '../optimizer'
import type { SSROptions } from '..'
import type { PackageCache, PackageData } from '../packages'
import { loadPackageData, resolvePackageData } from '../packages'
import { isWorkerRequest } from './worker'

const normalizedClientEntry = normalizePath(CLIENT_ENTRY)
const normalizedEnvEntry = normalizePath(ENV_ENTRY)
Expand Down Expand Up @@ -144,13 +145,16 @@ export function resolvePlugin(resolveOptions: InternalResolveOptions): Plugin {
}

if (importer) {
const _importer = isWorkerRequest(importer)
? splitFileAndPostfix(importer).file
: importer
if (
isTsRequest(importer) ||
isTsRequest(_importer) ||
resolveOpts.custom?.depScan?.loader?.startsWith('ts')
) {
options.isFromTsImporter = true
} else {
const moduleLang = this.getModuleInfo(importer)?.meta?.vite?.lang
const moduleLang = this.getModuleInfo(_importer)?.meta?.vite?.lang
options.isFromTsImporter = moduleLang && isTsRequest(`.${moduleLang}`)
}
}
Expand Down
8 changes: 8 additions & 0 deletions packages/vite/src/node/plugins/worker.ts
Expand Up @@ -32,6 +32,14 @@ export type WorkerType = 'classic' | 'module' | 'ignore'
export const WORKER_FILE_ID = 'worker_file'
const workerCache = new WeakMap<ResolvedConfig, WorkerCache>()

export function isWorkerRequest(id: string): boolean {
const query = parseRequest(id)
if (query && query[WORKER_FILE_ID] != null) {
return true
}
return false
}

function saveEmitWorkerAsset(
config: ResolvedConfig,
asset: EmittedAsset
Expand Down
16 changes: 15 additions & 1 deletion packages/vite/src/node/server/index.ts
Expand Up @@ -13,6 +13,7 @@ import launchEditorMiddleware from 'launch-editor-middleware'
import type { SourceMap } from 'rollup'
import picomatch from 'picomatch'
import type { Matcher } from 'picomatch'
import type { InvalidatePayload } from 'types/customEvent'
import type { CommonServerOptions } from '../http'
import {
httpServerStart,
Expand Down Expand Up @@ -67,7 +68,12 @@ import { timeMiddleware } from './middlewares/time'
import { ModuleGraph } from './moduleGraph'
import { errorMiddleware, prepareError } from './middlewares/error'
import type { HmrOptions } from './hmr'
import { handleFileAddUnlink, handleHMRUpdate } from './hmr'
import {
getShortName,
handleFileAddUnlink,
handleHMRUpdate,
updateModules
} from './hmr'
import { openBrowser } from './openBrowser'
import type { TransformOptions, TransformResult } from './transformRequest'
import { transformRequest } from './transformRequest'
Expand Down Expand Up @@ -489,6 +495,14 @@ export async function createServer(
handleFileAddUnlink(normalizePath(file), server)
})

ws.on('vite:invalidate', async ({ path }: InvalidatePayload) => {
const mod = moduleGraph.urlToModuleMap.get(path)
if (mod && mod.isSelfAccepting && mod.lastHMRTimestamp > 0) {
const file = getShortName(mod.file!, config.root)
updateModules(file, [...mod.importers], mod.lastHMRTimestamp, server)
}
})

if (!middlewareMode && httpServer) {
httpServer.once('listening', () => {
// update actual port since this may be different from initial value
Expand Down
5 changes: 5 additions & 0 deletions packages/vite/types/customEvent.d.ts
Expand Up @@ -10,6 +10,11 @@ export interface CustomEventMap {
'vite:beforePrune': PrunePayload
'vite:beforeFullReload': FullReloadPayload
'vite:error': ErrorPayload
'vite:invalidate': InvalidatePayload
}

export interface InvalidatePayload {
path: string
}

export type InferCustomEventPayload<T extends string> =
Expand Down

0 comments on commit a2d5715

Please sign in to comment.