Open-source project
vuejs/vue avatar
vuejs/vue

Vue 2 reached End of Life, and the repository still serves a 2.7.16 runtime

GitHub describes it as This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core. The repository metadata lists TypeScript as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

212,839 stars33,720 forksTypeScriptMIT

At a glance

What is it?
This is the Vue 2 repository, and the README on its default branch opens by telling you it is inactive and that new work happens in vuejs/core. The package still installs and its build scripts still work, so the interesting question for anyone still on it is what the manifest and the folder layout do to your build.
Who is it for?
Keep Vue 2 only where a rewrite is genuinely blocked, and treat this repository as a read-only reference rather than a dependency you track. The npm package remains installable and the build still works, so nothing forces your hand today, but the last push was on 2024-10-10 and the last release was v2.7.16 on 2023-12-24, which means every defect you find from here is one you own.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Probably not. The repository last received commits 23 months ago, on October 10, 2024.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The exports map hands Node a different file than your bundler

The main entry point resolves three ways, and the third one surprises people.

json
"exports": {
  ".": {
    "types": "./types/index.d.ts",
    "import": {
      "node": "./dist/vue.runtime.mjs",
      "default": "./dist/vue.runtime.esm.js"
    },
    "require": "./dist/vue.runtime.common.js"
  }
}

Under the `node` condition an ESM import gets the `.mjs` runtime, while every other resolver falls through to the `.esm.js` build and a CommonJS `require` gets the `.common.js` build. Older tooling that ignores `exports` altogether falls back to `main`, which is `dist/vue.runtime.common.js`, and the `module` field points at the ESM build for bundlers that read that instead.

So the same `import Vue from 'vue'` can resolve to three different files depending on the resolver, and nothing in the package warns you which one you got. That matters for server-side rendering, where the Node condition is the one you want and a misconfigured resolver quietly hands the browser-oriented build to your server.

sideEffects: false lets your bundler delete the import that registered your plugin

One line in package.json carries more risk than the rest of the manifest combined.

json
"sideEffects": false

That tells a tree-shaking bundler that no file in this package has an effect when imported, so an import whose bindings you never reference is a candidate for deletion. In Vue 2 that is exactly the shape of the code people write to make a plugin, filter or global component available: you import it for its side effect, then reference it nowhere.

If the bundler takes the declaration at face value, the registration code disappears. The build succeeds, the application boots, and the first render fails at runtime on a component or filter that was registered by a module nobody kept. There is no warning at build time, and the stack trace points at your render function rather than at the import that was dropped.

The other side of the same field is that the package is unusually well shaken. Both facts come from the same declaration, and only one of them is what the author intended you to rely on.

Five watch targets, and none of them is the file npm serves

Development builds are a rollup watch with a TARGET value injected on the command line, and there are five of them.

json
"dev": "rollup -w -c scripts/config.js --environment TARGET:full-dev",
"dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:runtime-cjs-dev",
"dev:esm": "rollup -w -c scripts/config.js --environment TARGET:runtime-esm",
"dev:ssr": "rollup -w -c scripts/config.js --environment TARGET:server-renderer",
"dev:compiler": "rollup -w -c scripts/config.js --environment TARGET:compiler "

Read the target names against the `files` array, which ships `dist/*.js`, `dist/*.mjs`, `types/*.d.ts`, `compiler-sfc`, `packages/compiler-sfc` and `src`. The plain `dev` script builds `full-dev`, a development build with the template compiler included, which is not one of the files the registry serves. The three runtime targets and the server-renderer target are, and `dist/` is committed at the top of the repository rather than ignored.

Two consequences. A contributor who runs only `pnpm dev` is building an artifact that no consumer of the package will ever load, and a server-side rendering change needs `dev:ssr` specifically, because nothing in the default watch covers the server-renderer entry. The full build is a separate script, `node scripts/build.js`.

v2.7.16 was named Swan Song, and the last push was 2024-10-10

The repository is not marked archived, so it stays clonable and the branch stays browsable. What the README's first heading says is that this is the inactive repository for Vue 2, and that current work on Vue happens in vuejs/core.

The dates back that up. End of Life was December 31st, 2023, and the project says it no longer receives new features, updates or fixes. The final release was v2.7.16 on 2023-12-24, titled Swan Song, after two betas earlier that month. The last push to this branch was on 2024-10-10, and that is the most recent commit of any kind in the repository.

Nothing after 2.7.16 was published, so a commit dated 2024 does not imply a supported release. That release is what every package manager gives you on the 2.x line today, and the ten months between it and the last push is work that never shipped.

The issue list is exclusively for bugs, and anything off-guideline gets closed

The project states that the issue list of this repository is exclusively for bug reports and feature requests, and points questions to the official forum or community chat. There is a separate rule about what counts: read the Issue Reporting Checklist before opening an issue, and issues that do not conform to the guidelines may be closed immediately.

The policy itself is unremarkable. On a project whose last release was 2023-12-24 it has a different effect. A well-formed bug report against 2.7.16 is a well-formed request for a fix that will not come, and the guidance you get back is the forum, where the answer will be the migration guide.

There is also no upgrade path hidden in the release notes to check first. The changelog link at the top of the README points at the release notes for this repository, and the migration path it recommends is a different repository entirely, vuejs/core, with its own guide at v3-migration.vuejs.org.

Single file components arrive through a webpack loader and a subpath export

The `.vue` file is the reason most people reached for Vue, and the wiring for it is two separate pieces that the README keeps apart in the ecosystem table.

One is vue-loader, described as the single file component loader for webpack. The webpack qualifier is the whole point: the loader is bound to a specific bundler, and nothing in this repository provides an equivalent for Rollup, Vite, Parcel or esbuild. If you are assembling a toolchain around a different bundler, you are outside what this package can offer you.

The other piece is the compiler, and it is exposed as its own subpath rather than through the main entry.

json
"./compiler-sfc": {
  "types": "./compiler-sfc/index.d.ts",
  "import": "./compiler-sfc/index.mjs",
  "require": "./compiler-sfc/index.js"
}

That subpath is why `files` includes both `compiler-sfc` and `packages/compiler-sfc`, and why the `compiler-sfc` watch target exists at all. Importing the compiler directly is the supported route for tools that need to parse single file components without going through webpack.

Types are rolled up by api-extractor, so you cannot rebuild them with tsc alone

Type declarations are generated, then rolled up, then shipped. The whole sequence is one script.

json
"build:types": "rimraf temp && tsc --declaration --emitDeclarationOnly --outDir temp && api-extractor run && api-extractor run -c packages/compiler-sfc/api-extractor.json"

Read that left to right. A temp directory is destroyed, tsc emits declarations into it, and api-extractor runs twice, once for the main package and once against a second config for the single file component compiler. Two api-extractor config files sit at the repository root, `api-extractor.json` and `api-extractor.tsconfig.json`, which is what makes the two runs possible.

The shipped `typings` entry is `types/index.d.ts`, not the raw tsc output, so what you consume is a rolled-up bundle rather than a directory of per-file declarations. That is good for consumers and bad for contributors: you cannot reproduce the published types with tsc alone, and a contributor changing a public signature needs both api-extractor configs and the rollup step to see whether the change is compatible.

packageManager pins pnpm 8.9.2 while the build scripts still call npm

The manifest declares `"packageManager": "[email protected]"`, and the repository ships both `pnpm-lock.yaml` and `pnpm-workspace.yaml`. Then several scripts invoke npm.

The clearest one is the server-side renderer build, `"build:ssr": "npm run build -- runtime-cjs,server-renderer"`, which runs the build script through npm and passes two target names after the separator. The test script is composed the same way, chaining `npm run ts-check` into further sub-scripts.

This is a real trap for a contributor, because npm will happily run a script that assumes a pnpm-installed tree, and the resulting failure points at a missing module rather than at the package manager. A workspace with pnpm-lock.yaml, a pinned pnpm version and npm invocations inside its own scripts has no single source of truth for how it is meant to be installed. The pin tells you what the maintainer intends; the scripts do not enforce it.

Editorial conclusion

Keep Vue 2 only where a rewrite is genuinely blocked, and treat this repository as a read-only reference rather than a dependency you track. The npm package remains installable and the build still works, so nothing forces your hand today, but the last push was on 2024-10-10 and the last release was v2.7.16 on 2023-12-24, which means every defect you find from here is one you own. If a compliance or security review blocks unmaintained software, that review is the decision point, and the README points at Vue 2 NES as the option the project itself names. Before starting new work, check the exports map in package.json against your bundler's condition support, because that is where a Vue 2 install fails quietly rather than loudly.

Frequently asked questions

What does VueJS do?

Vue is a progressive framework for building user interfaces, designed from the ground up to be incrementally adoptable, and it can scale between a library and a framework depending on the use case. The core library focuses on the view layer only, with supporting libraries in the ecosystem for larger single-page applications, including vue-router for routing and vuex for large-scale state management.

Is Vue a framework or library?

Both, depending on how you use it. The project describes Vue as a progressive framework that can easily scale between a library and a framework, made up of an approachable core library focused on the view layer only plus an ecosystem that handles complexity in large single-page applications.

What does Vue stand for?

The README gives the pronunciation, `/vjuː/`, like the word view, and does not expand the name into anything further. It is described as a progressive framework for building user interfaces, and it is MIT-licensed with copyright held by Yux.

Is VueJS better than React?

The Vue 2 repository makes no comparison with React, and nothing in it supports a better-or-worse claim either way. What it does state is that Vue is incrementally adoptable, that the core library covers the view layer only, and that separate packages handle routing, state, scaffolding and single file components.

Should I use vuejs/vue or vuejs/core?

The `vue` package built by this repository is Vue 2, which reached End of Life on December 31st, 2023 and no longer receives features, updates or fixes. The repository points new projects at vuejs/core for the latest version of Vue, and strongly recommends that existing Vue 2 users upgrade using the guide at v3-migration.vuejs.org.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vuejs-vue.svg)](https://hysenlabs.com/projects/vuejs-vue)
Community notes

Community notes