为什么我放弃了 Vue,重写了整个项目用原生 Web Components

301 阅读2分钟

我是一个 Vue 使用者,甚至不夸张地说,“Vue 是我入行前端的第一个框架”。

但三个月前,我开始一个内部系统重构项目时,发现:

  • 项目组件越来越多,但状态共享越来越难处理;
  • Vuex 太重,Pinia 不够通用,跨模块通信成灾;
  • 想在不打包的前提下部署一部分组件,结果 Vue 完全不行;
  • SSR?不需要,甚至SSR 是个负担
  • 最关键的是:页面启动 700ms 才能点按钮

我突然意识到:是不是我在强行用 Vue 去做不该它做的事?


为什么是 Web Components?不是 React?不是 Svelte?

我想过用 React 重写,但我不想引入构建工具;Svelte 太新,团队没人懂。

Web Components 却提供了我想要的一切:

  • 封装: Shadow DOM 完全隔离样式,不再担心 Bootstrap 冲 Tailwind;
  • 复用: 一个组件就一个 .js 文件,扔到哪都能用;
  • 部署: 不需要 Webpack,不需要 Vite,浏览器能识别就能跑;
  • 兼容性: 所有主流浏览器都支持。

它就是一个“浏览器内置框架”。


我是怎么做的?

举一个真实组件:项目里的 <user-card>

class UserCard extends HTMLElement {
  connectedCallback() {
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.innerHTML = `
      <style>
        .card { border: 1px solid #ccc; padding: 1em; }
      </style>
      <div class="card">
        <slot name="name"></slot>
        <slot name="email"></slot>
      </div>
    `;
  }
}
customElements.define('user-card', UserCard);

使用方式:

<user-card>
  <span slot="name">张三</span>
  <span slot="email">zhangsan@example.com</span>
</user-card>

无需框架,无需虚拟 DOM,直接写,直接跑


遇到的坑也不少

  • 双向绑定? 没有!需要手写事件监听;
  • 跨组件通信? 没有 Pinia,要用事件或自定义属性;
  • 样式隔离? 太隔离了!想覆盖都难;
  • 生命周期不如 Vue 细致,但基本够用;
  • SEO? 别想,必须搭 SSR 或 Prerender;

我的选择是否正确?

答案可能不是肯定的。但我得到了一些宝贵的东西:

  • 组件真的独立了:没有 build,就能跑;
  • 发布非常简单:就是上传 JS 文件;
  • 性能提升了:不再等 bundle 初始化;
  • 学习更深入了:你必须掌握事件、DOM、模板,框架不再帮你挡枪

结语:你真的需要 Vue 吗?

并不是 Vue 不好,而是当你不再需要它时,你才知道它帮你做了多少,也拖慢了多少。

Web Components 并非万能,但在某些场景下,它比任何框架都适合 —— 尤其是:

  • 内嵌系统;
  • 多系统复用组件;
  • 零构建部署;
  • 页面重量极敏感。

放弃 Vue,不是背叛,而是归根。