能救,但必须先切断全局变量污染链、移除window挂载点、禁用隐式全局声明,再通过CSS Modules构建时重命名实现样式隔离,配合template复用HTML片段,彻底告别innerHTML拼接与BEM人工约束。

旧HTML项目里满屏div和全局变量,还能救吗?
能,但必须放弃“修修补补”心态。真正可维护的重构不是把div class="header">换成<header>就完事——而是先切断全局变量污染链,再按职责拆出独立作用域。否则语义化标签只是给混乱套了层马甲。
先干掉window上的挂载点,再谈模块化
几乎所有老项目都有一段类似window.initNav = function() {...}或var config = {...}的代码。这些是模块化的死敌,因为它们让任何脚本都能随意读写、覆盖、依赖未声明的变量。
- 用
const和let替换所有var,禁用隐式全局声明 - 把散落在
<script>里的逻辑全部移入独立JS文件,并统一加type="module" - 检查是否有直接调用
initNav()的地方,改成import { initNav } from './nav.js'显式依赖 - 运行时用
console.log(Object.keys(window))比对前后差异,确认无新挂载
HTML片段复用别靠innerHTML拼接
常见错误是写fetch('header.html').then(r => r.text()).then(html => document.getElementById('header').innerHTML = html)——这会清空原有事件监听器、销毁已初始化的第三方组件(比如Cesium Viewer),且无法做SSR或静态预渲染。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 改用
<template id="header-template">包裹结构,用document.importNode(template.content, true)克隆而非cloneNode(true) - 模板内避免硬编码内容,用
data-*属性或占位符(如{{title}}),由JS注入 - 如果必须动态加载,确保在
DOMContentLoaded后执行,并在插入前手动重建关键实例(如重新new Cesium.Viewer(...)) - 注意
file://协议下fetch会被CORS拦截,开发务必起本地服务(npx serve或python3 -m http.server)
CSS作用域不靠BEM命名,靠构建工具重命名
手写.header__logo--dark解决不了问题——它只是把冲突从class名转移到开发者脑力上。真正隔离靠的是CSS Modules自动重命名机制,但很多人配错loader顺序或漏关node_modules排除,导致第三方样式炸开。
立即学习“前端免费学习笔记(深入)”;
- Webpack中
css-loader必须开启modules: true,且exclude: /node_modules/要明确写出 -
localIdentName建议设为[name]_[local]_[hash:5],调试时一眼看出来源文件 - HTML里不能直接写
class="logo",必须通过JS导入:import styles from './Header.module.css'; element.className = styles.logo; - 若项目暂无构建流程,宁可用
<style scoped>(Vue单文件组件)或Shadow DOM,也别硬套BEM
最常被跳过的一步:没清理旧的document.write、eval字符串模板、jQuery全局插件绑定。这些代码不会报错,但会让模块加载顺序失控,且无法被Tree Shaking剔除。重构不是加新东西,是先清出一块干净地。


















