首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >零外部依赖的前端开发:用纯原生 JavaScript 打造高性能页面

零外部依赖的前端开发:用纯原生 JavaScript 打造高性能页面

作者头像
佛系豪豪吖
发布2026-06-22 20:57:35
发布2026-06-22 20:57:35
1080
举报

零外部依赖的前端开发:用纯原生 JavaScript 打造高性能页面

> 你真的需要 React、Vue、Bootstrap 吗?本文分享如何用纯 HTML + CSS + JavaScript 开发企业级管理后台,零 npm、零 CDN、零 node_modules。

为什么要零依赖?

2026 年了,前端框架已经卷到飞起。但回过头想想:

  • 一个后台管理面板,真的需要 200MB 的 node_modules?
  • React 18 打包出来 50KB gzip,Vue 3 也差不多 — 但你的业务代码可能才 5KB
  • CDN 挂了你的页面就挂了 — 不管用多好的 fallback 方案
  • 升级一个依赖,连锁升级十个,CI 跑半小时

我选择了一条"极端"路线:完全零外部依赖。所有代码自己写,一切责任自负。

原生模块化方案

ES Modules 已经全面支持,不需要 Webpack/Vite:

代码语言:javascript
复制
<p>import { createApp, ref, reactive } from './js/core.js';</p>
<p>import { Button, Table, Modal } from './js/components.js';</p>
<p>import { fetchApi, formatDate } from './js/utils.js';</p>

<p>// 开始写业务逻辑</p>

自己实现一个超轻量的响应式系统:

代码语言:javascript
复制
// js/core.js — 仅 50 行
let currentEffect = null;
const depsMap = new WeakMap();

export function ref(value) {
    const dep = new Set();
    return {
        get value() {
            if (currentEffect) { depsMap.set(currentEffect, dep); dep.add(currentEffect); }
            return value;
        },
        set value(newVal) {
            if (value !== newVal) { value = newVal; dep.forEach(fn => fn()); }
        }
    };
}

export function watchEffect(fn) {
    currentEffect = fn; fn(); currentEffect = null;
}

组件化:函数就是组件

不需要 JSX,不需要 template 编译器:

代码语言:javascript
复制
// js/components.js
export function DataTable({ columns, data, onRowClick }) {
    const el = document.createElement('table');
    el.className = 'data-table';

    // 表头
    const thead = document.createElement('thead');
    thead.innerHTML = ${columns.map(c => ${c.label}).join('')};
    el.appendChild(thead);

    // 表体
    const tbody = document.createElement('tbody');
    tbody.innerHTML = data.map(row =>
        ${columns.map(c => ${row[c.key] ?? ''}).join('')}
    ).join('');
    tbody.querySelectorAll('tr').forEach((tr, i) => {
        tr.addEventListener('click', () => onRowClick?.(data[i]));
    });
    el.appendChild(tbody);

    return el;
}

路由:URL Hash 就够了

单页应用路由不需要 react-router 那套重装备:

代码语言:javascript
复制
// js/router.js
const routes = new Map();

export function route(path, handler) {
    routes.set(path, handler);
}

export function navigate(path) {
    window.location.hash = path;
}

window.addEventListener('hashchange', () => {
    const path = window.location.hash.slice(1) || '/';
    const handler = routes.get(path);
    if (handler) {
        document.getElementById('app').innerHTML = '';
        document.getElementById('app').appendChild(handler());
    }
});

状态管理:简单的发布订阅

代码语言:javascript
复制
// js/store.js
export function createStore(initialState) {
    let state = { ...initialState };
    const listeners = new Set();

    return {
        getState: () => ({ ...state }),
        setState: (partial) => {
            state = { ...state, ...partial };
            listeners.forEach(fn => fn(state));
        },
        subscribe: (fn) => { listeners.add(fn); return () => listeners.delete(fn); }
    };
}

CSS 方案:CSS Variables + BEM

不需要 Tailwind 那些预处理:

代码语言:javascript
复制
:root {
    --color-primary: #0052d9;
    --color-bg: #f5f5f5;
    --color-text: #333;
    --radius: 8px;
    --shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.card {
    background: #fff;
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 20px;
}

.card__title {
    font-size: 18px;
    font-weight: 600;
    color: var(--color-text);
}

.btn--primary {
    background: var(--color-primary);
    color: #fff;
    border: none;
    padding: 8px 16px;
    border-radius: 6px;
    cursor: pointer;
}

HTTP 请求:fetch 足矣

代码语言:javascript
复制
// js/api.js
const BASE_URL = 'https://api.rmzdb.cloud';

export async function apiGet(path, params = {}) {
    const qs = new URLSearchParams(params).toString();
    const res = await fetch(${BASE_URL}${path}?${qs}, {
        headers: { 'Authorization': 'Bearer ' + getToken() }
    });
    if (!res.ok) throw new Error(API Error: ${res.status});
    return res.json();
}

export async function apiPost(path, body) {
    const res = await fetch(${BASE_URL}${path}, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + getToken()
        },
        body: JSON.stringify(body)
    });
    if (!res.ok) throw new Error(API Error: ${res.status});
    return res.json();
}

真实案例:管理后台

以下是我用这套方案搭建的实际项目结构:

代码语言:javascript
复制
admin-frontend/
├── index.html          # 入口
├── css/
│   └── style.css       # 全局样式 + CSS变量
├── js/
│   ├── core.js         # 响应式引擎 (50行)
│   ├── router.js       # 路由 (30行)
│   ├── store.js        # 状态管理 (25行)
│   ├── api.js          # HTTP封装 (40行)
│   ├── components.js   # 组件库 (300行)
│   └── utils.js        # 工具函数
├── pages/
│   ├── dashboard.js    # 仪表盘
│   ├── users.js        # 用户管理
│   └── settings.js     # 系统设置
└── favicon.svg

总代码量不到 1000 行,gzip 后不到 5KB。

效果对比

| 指标 | React + Ant Design | 纯原生方案 |

|------|:---:|:---:|

| node_modules | 200MB+ | 0 |

| 首屏加载 | 1.2s | 0.2s |

| gzip 后大小 | ~80KB | ~5KB |

| 构建时间 | 30s | 0 |

| 外部依赖 | 500+ | 0 |

什么时候不该这样做

零依赖不是银弹。以下场景还是老老实实用框架:

  • 大型团队协作项目
  • 需要 SSR/SEO 的内容站
  • 复杂表单和表格交互(可用 TDesign/Element Plus)
  • 需要大量第三方生态的项目

总结

零依赖的核心思想不是"反对框架",而是对每一行引入的代码负责

当你自己写了路由、状态管理、组件系统,你会比用任何框架都更理解你的代码。而且——你的页面永远不会因为 CDN 挂了而白屏,永远不会因为依赖升级而改业务代码

这就是数据主权的意义。

---

你的项目里有多少个 node_modules?欢迎评论区晒一下。

本文为作者原创,未经授权禁止转载、洗稿、搬运。如需引用请保留原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 零外部依赖的前端开发:用纯原生 JavaScript 打造高性能页面
    • 为什么要零依赖?
    • 原生模块化方案
    • 组件化:函数就是组件
    • 路由:URL Hash 就够了
    • 状态管理:简单的发布订阅
    • CSS 方案:CSS Variables + BEM
    • HTTP 请求:fetch 足矣
    • 真实案例:管理后台
    • 效果对比
    • 什么时候不该这样做
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档