Skip to content

Commit d0cf234

Browse files
committed
Merge branch 'vapor' into minor
2 parents cf20ee6 + 3a3bd84 commit d0cf234

File tree

303 files changed

+35157
-2100
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

303 files changed

+35157
-2100
lines changed

.github/contributing.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,17 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
3838
### Pull Request Checklist
3939

4040
- Vue core has two primary work branches: `main` and `minor`.
41-
4241
- If your pull request is a feature that adds new API surface, it should be submitted against the `minor` branch.
4342

4443
- Otherwise, it should be submitted against the `main` branch.
4544

4645
- [Make sure to tick the "Allow edits from maintainers" box](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork). This allows us to directly make minor edits / refactors and saves a lot of time.
4746

4847
- If adding a new feature:
49-
5048
- Add accompanying test case.
5149
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it.
5250

5351
- If fixing a bug:
54-
5552
- If you are resolving a special issue, add `(fix #xxxx[,#xxxx])` (#xxxx is the issue id) in your PR title for a better release log, e.g. `update entities encoding/decoding (fix #3899)`.
5653
- Provide a detailed description of the bug in the PR. Live demo preferred.
5754
- Add appropriate test coverage if applicable. You can check the coverage of your code addition by running `nr test-coverage`.
@@ -69,9 +66,7 @@ Hi! I'm really excited that you are interested in contributing to Vue.js. Before
6966
- The PR should fix the intended bug **only** and not introduce unrelated changes. This includes unnecessary refactors - a PR should focus on the fix and not code style, this makes it easier to trace changes in the future.
7067

7168
- Consider the performance / size impact of the changes, and whether the bug being fixes justifies the cost. If the bug being fixed is a very niche edge case, we should try to minimize the size / perf cost to make it worthwhile.
72-
7369
- Is the code perf-sensitive (e.g. in "hot paths" like component updates or the vdom patch function?)
74-
7570
- If the branch is dev-only, performance is less of a concern.
7671

7772
- Check how much extra bundle size the change introduces.
@@ -265,7 +260,6 @@ This repository employs a [monorepo](https://en.wikipedia.org/wiki/Monorepo) set
265260
- `vue`: The public facing "full build" which includes both the runtime AND the compiler.
266261

267262
- Private utility packages:
268-
269263
- `dts-test`: Contains type-only tests against generated dts files.
270264

271265
- `sfc-playground`: The playground continuously deployed at https://play.vuejs.org. To run the playground locally, use [`nr dev-sfc`](#nr-dev-sfc).
@@ -290,27 +284,39 @@ This is made possible via several configurations:
290284

291285
```mermaid
292286
flowchart LR
287+
vue["vue"]
293288
compiler-sfc["@vue/compiler-sfc"]
294289
compiler-dom["@vue/compiler-dom"]
290+
compiler-vapor["@vue/compiler-vapor"]
295291
compiler-core["@vue/compiler-core"]
296-
vue["vue"]
297292
runtime-dom["@vue/runtime-dom"]
293+
runtime-vapor["@vue/runtime-vapor"]
298294
runtime-core["@vue/runtime-core"]
299295
reactivity["@vue/reactivity"]
300296
301297
subgraph "Runtime Packages"
302298
runtime-dom --> runtime-core
299+
runtime-vapor --> runtime-core
303300
runtime-core --> reactivity
304301
end
305302
306303
subgraph "Compiler Packages"
307304
compiler-sfc --> compiler-core
308305
compiler-sfc --> compiler-dom
306+
compiler-sfc --> compiler-vapor
309307
compiler-dom --> compiler-core
308+
compiler-vapor --> compiler-core
310309
end
311310
311+
vue --> compiler-sfc
312312
vue ---> compiler-dom
313313
vue --> runtime-dom
314+
vue --> compiler-vapor
315+
vue --> runtime-vapor
316+
317+
%% Highlight class
318+
classDef highlight stroke:#35eb9a,stroke-width:3px;
319+
class compiler-vapor,runtime-vapor highlight;
314320
```
315321

316322
There are some rules to follow when importing across package boundaries:

.github/maintenance.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,13 @@ Depending on the type of the PR, different considerations need to be taken into
4848
- Performance: if a refactor PR claims to improve performance, there should be benchmarks showcasing said performance unless the improvement is self-explanatory.
4949

5050
- Code quality / stylistic PRs: we should be conservative on merging this type PRs because (1) they can be subjective in many cases, and (2) they often come with large git diffs, causing merge conflicts with other pending PRs, and leading to unwanted noise when tracing changes through git history. Use your best judgement on this type of PRs on whether they are worth it.
51-
5251
- For PRs in this category that are approved, do not merge immediately. Group them before releasing a new minor, after all feature-oriented PRs are merged.
5352

5453
### Reviewing a Feature
5554

5655
- Feature PRs should always have clear context and explanation on why the feature should be added, ideally in the form of an RFC. If the PR doesn't explain what real-world problem it is solving, ask the contributor to clarify.
5756

5857
- Decide if the feature should require an RFC process. The line isn't always clear, but a rough criteria is whether it is augmenting an existing API vs. adding a new API. Some examples:
59-
6058
- Adding a new built-in component or directive is "significant" and definitely requires an RFC.
6159
- Template syntax additions like adding a new `v-on` modifier or a new `v-bind` syntax sugar are "substantial". It would be nice to have an RFC for it, but a detailed explanation on the use case and reasoning behind the design directly in the PR itself can be acceptable.
6260
- Small, low-impact additions like exposing a new utility type or adding a new app config option can be self-explanatory, but should still provide enough context in the PR.
@@ -70,7 +68,6 @@ Depending on the type of the PR, different considerations need to be taken into
7068
- Implementation: code style should be consistent with the rest of the codebase, follow common best practices. Prefer code that is boring but easy to understand over "clever" code.
7169

7270
- Size: bundle size matters. We have a GitHub action that compares the size change for every PR. We should always aim to realize the desired changes with the smallest amount of code size increase.
73-
7471
- Sometimes we need to compare the size increase vs. perceived benefits to decide whether a change is justifiable. Also take extra care to make sure added code can be tree-shaken if not needed.
7572

7673
- Make sure to put dev-only code in `__DEV__` branches so they are tree-shakable.
@@ -80,7 +77,6 @@ Depending on the type of the PR, different considerations need to be taken into
8077
- Make sure it doesn't accidentally cause dev-only or compiler-only code branches to be included in the runtime build. Notable case is that some functions in @vue/shared are compiler-only and should not be used in runtime code, e.g. `isHTMLTag` and `isSVGTag`.
8178

8279
- Performance
83-
8480
- Be careful about code changes in "hot paths", in particular the Virtual DOM renderer (`runtime-core/src/renderer.ts`) and component instantiation code.
8581

8682
- Potential Breakage

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ on:
99
branches:
1010
- main
1111
- minor
12+
- vapor
1213

1314
jobs:
1415
test:
1516
if: ${{ ! startsWith(github.event.head_commit.message, 'release:') && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository) }}
1617
uses: ./.github/workflows/test.yml
1718

1819
continuous-release:
19-
if: github.repository == 'vuejs/core'
20+
if: github.repository == 'vuejs/core' && github.ref_name != 'vapor'
2021
runs-on: ubuntu-latest
2122
steps:
2223
- name: Checkout

.github/workflows/test.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,32 @@ jobs:
8080
- name: verify treeshaking
8181
run: node scripts/verify-treeshaking.js
8282

83+
e2e-vapor:
84+
runs-on: ubuntu-latest
85+
steps:
86+
- uses: actions/checkout@v4
87+
88+
- name: Setup cache for Chromium binary
89+
uses: actions/cache@v4
90+
with:
91+
path: ~/.cache/puppeteer
92+
key: chromium-${{ hashFiles('pnpm-lock.yaml') }}
93+
94+
- name: Install pnpm
95+
uses: pnpm/action-setup@v4.0.0
96+
97+
- name: Install Node.js
98+
uses: actions/setup-node@v4
99+
with:
100+
node-version-file: '.node-version'
101+
cache: 'pnpm'
102+
103+
- run: pnpm install
104+
- run: node node_modules/puppeteer/install.mjs
105+
106+
- name: Run e2e tests
107+
run: pnpm run test-e2e-vapor
108+
83109
lint-and-test-dts:
84110
runs-on: ubuntu-latest
85111
env:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ TODOs.md
1111
dts-build/packages
1212
*.tsbuildinfo
1313
*.tgz
14+
packages-private/benchmark/reference

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@
1414
"[json]": {
1515
"editor.defaultFormatter": "esbenp.prettier-vscode"
1616
},
17-
"editor.formatOnSave": true
17+
"editor.formatOnSave": true,
18+
"vitest.disableWorkspaceWarning": true
1819
}

eslint.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export default tseslint.config(
106106

107107
// Packages targeting DOM
108108
{
109-
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
109+
files: ['packages/{vue,vue-compat,runtime-dom,runtime-vapor}/**'],
110110
rules: {
111111
'no-restricted-globals': ['error', ...NodeGlobals],
112112
},
@@ -126,6 +126,7 @@ export default tseslint.config(
126126
files: [
127127
'packages-private/template-explorer/**',
128128
'packages-private/sfc-playground/**',
129+
'packages-private/local-playground/**',
129130
],
130131
rules: {
131132
'no-restricted-globals': ['error', ...NodeGlobals],
@@ -152,6 +153,8 @@ export default tseslint.config(
152153
'./*.{js,ts}',
153154
'packages/*/*.js',
154155
'packages/vue/*/*.js',
156+
'packages-private/benchmark/*',
157+
'packages-private/e2e-utils/*',
155158
],
156159
rules: {
157160
'no-restricted-globals': 'off',

package.json

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
"build-dts": "tsc -p tsconfig.build.json --noCheck && rollup -c rollup.dts.config.js",
1010
"clean": "rimraf --glob packages/*/dist temp .eslintcache",
1111
"size": "run-s \"size-*\" && node scripts/usage-size.js",
12-
"size-global": "node scripts/build.js vue runtime-dom -f global -p --size",
12+
"size-global": "node scripts/build.js vue runtime-dom compiler-dom -f global -p --size",
1313
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
14-
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
14+
"size-esm": "node scripts/build.js runtime-shared runtime-dom runtime-core reactivity shared runtime-vapor -f esm-bundler",
1515
"check": "tsc --incremental --noEmit",
1616
"lint": "eslint --cache .",
1717
"format": "prettier --write --cache .",
1818
"format-check": "prettier --check --cache .",
1919
"test": "vitest",
20-
"test-unit": "vitest --project unit",
20+
"test-unit": "vitest --project unit --project unit-jsdom",
2121
"test-e2e": "node scripts/build.js vue -f global -d && vitest --project e2e",
22+
"test-e2e-vapor": "pnpm run prepare-e2e-vapor && vitest --project e2e-vapor",
23+
"prepare-e2e-vapor": "node scripts/build.js -f cjs+esm-bundler+esm-bundler-runtime && pnpm run -C packages-private/vapor-e2e-test build",
2224
"test-dts": "run-s build-dts test-dts-only",
2325
"test-dts-only": "tsc -p packages-private/dts-built-test/tsconfig.json && tsc -p ./packages-private/dts-test/tsconfig.test.json",
2426
"test-coverage": "vitest run --project unit --coverage",
@@ -29,19 +31,17 @@
2931
"release": "node scripts/release.js",
3032
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
3133
"dev-esm": "node scripts/dev.js -if esm-bundler-runtime",
32-
"dev-compiler": "run-p \"dev template-explorer\" serve",
33-
"dev-sfc": "run-s dev-sfc-prepare dev-sfc-run",
34-
"dev-sfc-prepare": "node scripts/pre-dev-sfc.js || npm run build-all-cjs",
35-
"dev-sfc-serve": "vite packages-private/sfc-playground --host",
36-
"dev-sfc-run": "run-p \"dev compiler-sfc -f esm-browser\" \"dev vue -if esm-bundler-runtime\" \"dev vue -ipf esm-browser-runtime\" \"dev server-renderer -if esm-bundler\" dev-sfc-serve",
34+
"dev-prepare-cjs": "node scripts/prepare-cjs.js || node scripts/build.js -f cjs",
35+
"dev-compiler": "run-p \"dev template-explorer\" serve open",
36+
"dev-sfc": "run-s dev-prepare-cjs dev-sfc-run",
37+
"dev-sfc-serve": "vite packages-private/sfc-playground",
38+
"dev-sfc-run": "run-p \"dev compiler-sfc -f esm-browser\" \"dev vue -if esm-browser-vapor\" \"dev vue -ipf esm-browser-vapor\" \"dev server-renderer -if esm-bundler\" dev-sfc-serve",
39+
"dev-vapor": "pnpm -C packages-private/local-playground run dev",
3740
"serve": "serve",
3841
"open": "open http://localhost:3000/packages-private/template-explorer/local.html",
39-
"build-sfc-playground": "run-s build-all-cjs build-runtime-esm build-browser-esm build-ssr-esm build-sfc-playground-self",
40-
"build-all-cjs": "node scripts/build.js vue runtime compiler reactivity shared -af cjs",
41-
"build-runtime-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler-runtime && node scripts/build.js vue -f esm-browser-runtime",
42-
"build-browser-esm": "node scripts/build.js runtime reactivity shared -af esm-bundler && node scripts/build.js vue -f esm-bundler && node scripts/build.js vue -f esm-browser",
43-
"build-ssr-esm": "node scripts/build.js compiler-sfc server-renderer -f esm-browser",
44-
"build-sfc-playground-self": "cd packages-private/sfc-playground && npm run build",
42+
"build-sfc-playground": "run-s build-sfc-deps build-sfc-playground-self",
43+
"build-sfc-deps": "node scripts/build.js -f ~global+global-runtime",
44+
"build-sfc-playground-self": "pnpm run -C packages-private/sfc-playground build",
4545
"preinstall": "npx only-allow pnpm",
4646
"postinstall": "simple-git-hooks"
4747
},
@@ -74,6 +74,7 @@
7474
"@types/node": "^22.16.0",
7575
"@types/semver": "^7.7.0",
7676
"@types/serve-handler": "^6.1.4",
77+
"@vitest/ui": "^3.0.2",
7778
"@vitest/coverage-v8": "^3.1.4",
7879
"@vitest/eslint-plugin": "^1.2.1",
7980
"@vue/consolidate": "1.0.0",

packages-private/benchmark/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
results/*
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<script setup>
2+
import { shallowRef, triggerRef } from 'vue'
3+
import { buildData } from './data'
4+
import { defer, wrap } from './profiling'
5+
6+
const selected = shallowRef()
7+
const rows = shallowRef([])
8+
9+
// Bench Add: https://jsbench.me/45lzxprzmu/1
10+
const add = wrap('add', () => {
11+
rows.value.push(...buildData(1000))
12+
triggerRef(rows)
13+
})
14+
15+
const remove = wrap('remove', id => {
16+
rows.value.splice(
17+
rows.value.findIndex(d => d.id === id),
18+
1,
19+
)
20+
triggerRef(rows)
21+
})
22+
23+
const select = wrap('select', id => {
24+
selected.value = id
25+
})
26+
27+
const run = wrap('run', () => {
28+
rows.value = buildData()
29+
selected.value = undefined
30+
})
31+
32+
const update = wrap('update', () => {
33+
const _rows = rows.value
34+
for (let i = 0, len = _rows.length; i < len; i += 10) {
35+
_rows[i].label.value += ' !!!'
36+
}
37+
})
38+
39+
const runLots = wrap('runLots', () => {
40+
rows.value = buildData(10000)
41+
selected.value = undefined
42+
})
43+
44+
const clear = wrap('clear', () => {
45+
rows.value = []
46+
selected.value = undefined
47+
})
48+
49+
const swapRows = wrap('swap', () => {
50+
const _rows = rows.value
51+
if (_rows.length > 998) {
52+
const d1 = _rows[1]
53+
const d998 = _rows[998]
54+
_rows[1] = d998
55+
_rows[998] = d1
56+
triggerRef(rows)
57+
}
58+
})
59+
60+
async function bench() {
61+
for (let i = 0; i < 30; i++) {
62+
rows.value = []
63+
await runLots()
64+
await defer()
65+
}
66+
}
67+
68+
const globalThis = window
69+
</script>
70+
71+
<template>
72+
<h1>Vue.js (VDOM) Benchmark</h1>
73+
74+
<div style="display: flex; gap: 4px; margin-bottom: 4px">
75+
<label>
76+
<input
77+
type="checkbox"
78+
:value="globalThis.doProfile"
79+
@change="globalThis.doProfile = $event.target.checked"
80+
/>
81+
Profiling
82+
</label>
83+
<label>
84+
<input
85+
type="checkbox"
86+
:value="globalThis.reactivity"
87+
@change="globalThis.reactivity = $event.target.checked"
88+
/>
89+
Reactivity Cost
90+
</label>
91+
</div>
92+
93+
<div
94+
id="control"
95+
style="display: flex; flex-direction: column; width: fit-content; gap: 6px"
96+
>
97+
<button @click="bench">Benchmark mounting</button>
98+
<button id="run" @click="run">Create 1,000 rows</button>
99+
<button id="runlots" @click="runLots">Create 10,000 rows</button>
100+
<button id="add" @click="add">Append 1,000 rows</button>
101+
<button id="update" @click="update">Update every 10th row</button>
102+
<button id="clear" @click="clear">Clear</button>
103+
<button id="swaprows" @click="swapRows">Swap Rows</button>
104+
</div>
105+
<div id="time"></div>
106+
<table class="table table-hover table-striped test-data">
107+
<tbody>
108+
<tr
109+
v-for="row of rows"
110+
:key="row.id"
111+
:class="selected === row.id ? 'danger' : ''"
112+
>
113+
<td class="col-md-1">{{ row.id }}</td>
114+
<td class="col-md-4">
115+
<a @click="select(row.id)">{{ row.label.value }}</a>
116+
</td>
117+
<td class="col-md-1">
118+
<a @click="remove(row.id)">
119+
<span class="glyphicon glyphicon-remove" aria-hidden="true">x</span>
120+
</a>
121+
</td>
122+
<td class="col-md-6"></td>
123+
</tr>
124+
</tbody>
125+
</table>
126+
<span
127+
class="preloadicon glyphicon glyphicon-remove"
128+
aria-hidden="true"
129+
></span>
130+
</template>
131+
132+
<style>
133+
.danger {
134+
background-color: red;
135+
}
136+
</style>

0 commit comments

Comments
 (0)