技术文章

阳光_思想家
2025-12-23 18:26
阅读 2268

我在成都小县城远程办公的第18个月

去年这个时候,我还在为下一份简历发愁。虽然每天在青白江的小出租屋里写代码、调接口、修 Bug,看起来岁月静好,但内心其实慌得一批——毕竟“小镇做题家”这个标签不是白叫的:高考刷题上来的,大学靠 LeetCode 找工作,进了大厂又靠面试题挑战续命。如今远程办公久了,技术栈没怎么更新,连 GitHub 提交记录都快长草了。

直到上周五晚上,被产品经理@了一条消息:“能不能让这个页面首屏加载再快点?用户反馈卡成PPT了。” 我盯着屏幕,心里默默翻了个白眼——这已经是本月第三次提性能优化需求了,而我们的 JavaScript 包体积已经逼近 3MB。那一刻我意识到:不能再靠 Ctrl+C/V 混日子了,是时候深入搞点技术探索与实践了。


面试题挑战逼我重学模块拆分

说来惭愧,前阵子准备跳槽面了几家,被问到“你们项目怎么做的按需加载?”我支支吾吾说了句“用了 dynamic import”,结果面试官反问:“那你们的 chunk 切分策略是什么?有没有考虑过路由级和组件级的粒度平衡?” 我当场大脑宕机。

回来后痛定思痛,决定拿手头这个电商后台项目开刀。我们用的是 Vue 3 + Vite,早期为了赶双11上线,所有页面一股脑全塞进主 bundle,导致首屏加载时间高达 4.2s(本地开发环境测的,线上可能更惨)。

于是,我开始动手重构。核心思路就一条:把 JavaScript 拆得越细越好,但也不能太碎。这里有个微妙的平衡点——chunk 太少,加载慢;chunk 太多,HTTP 请求爆炸,反而更慢(尤其对移动端和弱网用户)。

我参考了 Webpack 的 splitChunks 策略,结合 Vite 的 rollupOptions 做了如下配置:

// vite.config.js
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          // 把第三方库单独打包
          if (id.includes('node_modules')) {
            if (id.includes('element-plus')) return 'element-plus';
            if (id.includes('echarts')) return 'echarts';
            if (id.includes('lodash')) return 'lodash';
            return 'vendor'; // 其他第三方归到 vendor
          }
          // 按页面路由拆分
          if (id.includes('/src/views/')) {
            const match = id.match(/src\/views\/([^/]+)/);
            if (match) return `page-${match[1]}`;
          }
          // 公共组件单独打包
          if (id.includes('/src/components/shared/')) {
            return 'shared-components';
          }
        }
      }
    }
  }
});

改完之后,主 bundle 从 2.8MB 降到了 600KB,首屏加载时间压到 1.3s(本地)。线上灰度发布后,Lighthouse 性能分从 48 提升到 76,PM 终于没再半夜@我了。


简历不能只写“熟悉 Vue”,得有工具链沉淀

很多像我一样的小镇做题家,简历上清一色写着“熟练掌握 JavaScript、Vue、React”,但真要问细节,比如“你们怎么监控前端错误?”、“怎么保证代码质量?”,就答不上来了。

其实,技术深度不体现在你会多少框架,而体现在你构建了多少自动化工具

我们团队人少(远程+兼职一共5个人),没法像大厂那样配专门的 DevOps 工程师,所以我就自己撸了个轻量级工具链,主要解决三个问题:

  1. 代码规范:用 ESLint + Prettier + Husky,在 commit 前自动格式化并检查
  2. 错误监控:接入 Sentry,自定义上报逻辑,过滤掉测试环境噪音
  3. 性能基线:用 Lighthouse CI 在每次 PR 合并前跑性能测试,低于阈值就阻断合并

下面是我们 .husky/pre-commit 脚本的一部分:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint-staged
npm run type-check

lighthouserc.json 配置则确保性能不退步:

{
  "ci": {
    "collect": {
      "url": ["http://localhost:3000/dashboard"],
      "startServerCommand": "npm run preview"
    },
    "assert": {
      "assertions": {
        "categories:performance": ["error", { "minScore": 0.7 }],
        "first-contentful-paint": ["warn", { "maxNumericValue": 1500 }]
      }
    }
  }
}

这些看似“小打小闹”的工具,其实极大提升了交付质量。更重要的是——它们都能写进简历!我现在简历里不再是“参与XX项目开发”,而是“主导前端工程化体系建设,实现自动化性能守门机制,降低线上 JS 错误率 62%”。HR 看不懂没关系,技术面试官一眼就知道你干过实事。


技术探索不是闭门造车,得去“蹭会”

别看我在县城,但我可没闲着。成都本地的技术沙龙我基本场场不落(虽然要坐1小时地铁进城)。上个月在天府软件园听了一场关于“微前端与模块联邦”的分享,主讲人提到他们用 Module Federation 动态加载不同团队的组件,我当时就心动了。

回来立马在测试环境试水。我们后台有商品、订单、用户三个大模块,原本是单体应用,现在想逐步解耦。用 Module Federation 的好处是:不用重构整个架构,就能实现跨应用组件共享

宿主应用(Host)配置:

// vite.config.js (Host)
plugins: [
  federation({
    name: 'host_app',
    remotes: {
      productModule: 'productApp@http://localhost:3001/assets/remoteEntry.js'
    },
    shared: ['vue', 'pinia']
  })
]

远程模块(Remote):

// product-app/vite.config.js
plugins: [
  federation({
    name: 'productApp',
    filename: 'remoteEntry.js',
    exposes: {
      './ProductList': './src/components/ProductList.vue'
    },
    shared: ['vue', 'pinia']
  })
]

然后在 Host 里直接动态引入:

<script setup>
import ProductList from 'productModule/ProductList';
</script>

效果立竿见影:商品模块独立部署,更新时不影响主站。而且因为共享了 Vue 和 Pinia 实例,内存占用也没翻倍。

当然,踩坑也不少。比如一开始没配好 shared 版本,导致两个 Vue 实例打架,页面直接白屏。还有跨域问题、缓存失效……但这些问题恰恰是最好的学习素材。后来我把整个过程整理成一篇内部 Wiki,还录了个 15 分钟的分享视频,团队群里反响不错。


最佳实践总结:别为了技术而技术

经过这几个月折腾,我最大的感悟是:技术探索必须服务于业务痛点,否则就是自嗨

  • 如果你的用户都在强网环境,拼命压 JS 体积可能收益不大;
  • 如果团队只有 3 个人,搞一套复杂的微前端反而增加维护成本;
  • 如果产品迭代快如闪电,花两周搭 Lighthouse CI 可能不如先搞定需求。

但在合适的时机做合适的事,技术就能变成护城河。比如我们现在新招人,面试必问:“你怎么看待前端工程化?” 然后让人现场看我们的工具链设计——这比背八股文有用多了。

最后附上一个小对比表,看看重构前后的关键指标变化:

指标 重构前 重构后 提升幅度
主 JS Bundle 2.8 MB 600 KB ↓78%
首屏加载时间 4.2s 1.3s ↓69%
JS 错误率(日均) 1,200+ 450 ↓62%
PR 合并阻断次数(性能) 0 平均每周 2 次 ✅建立守门机制

写这篇文章的时候,窗外正下着成都典型的毛毛雨。远程办公虽然自由,但也容易陷入舒适区。还好有这些技术挑战推着我往前走——不管是为了面试题不再卡壳,还是为了让简历有点干货,又或者单纯不想被时代甩下。

如果你也和我一样,在小城市远程搬砖,别躺平。参加个线上 Meetup,读篇 RFC,甚至只是把一个重复的手动操作写成脚本,都是进步。

毕竟,小镇做题家的终极武器,从来不是天赋,而是持续折腾的劲头

共勉。

评论 0

最热最新
暂无评论
阳光_思想家Lv.1
0
影响力
0
文章
0
粉丝