2026/4/6 9:37:41
网站建设
项目流程
大型门户网站建设工作总结,短链接生成,网页设计作业压缩包,网站集约化建设 技术前端老铁别懵圈#xff1a;shim 和 polyfill 到底有啥不一样#xff1f;#xff08;附避坑指南#xff09;前端老铁别懵圈#xff1a;shim 和 polyfill 到底有啥不一样#xff1f;#xff08;附避坑指南#xff09;先整一句人话#xff1a;这俩都是“背锅侠”#xf…前端老铁别懵圈shim 和 polyfill 到底有啥不一样附避坑指南前端老铁别懵圈shim 和 polyfill 到底有啥不一样附避坑指南先整一句人话这俩都是“背锅侠”但背法不一样从“想喝可乐”到“自己造汽水”——概念先掰扯清楚1. shim接口翻译官老鸨子接新客2. polyfill功能克隆兵缺啥造啥实战场景到底什么时候上哪道菜场景 1产品经理非要你在 H5 里裁剪图片而且——“兼容到安卓 4.4”场景 2后台小哥扔给你一段 swagger 生成的 TS 代码满屏 async/awaitIE11 当场去世场景 3Safari 报“cant find variable: IntersectionObserver”懒加载模块全崩打包体积爆炸教你三招“瘦身术”1. 别一上来就 import core-js; 全量2. 打包两层策略现代浏览器走“干净 bundle”老旧走“带 polyfill”3. 动态 polyfill 服务polyfill.io 真香踩坑合集那些年一起熬过的夜坑 1重复引用 Promise polyfill导致 instanceof Promise false坑 2shim 把原生方法覆盖了性能雪崩坑 3WeakMap polyfill 内存泄漏坑 4babel-runtime 和 babel/plugin-transform-runtime 混用手写一个“最小但能用”的 fetch shim拿去忽悠面试官一句话总结别再把它们当“同义词”前端老铁别懵圈shim 和 polyfill 到底有啥不一样附避坑指南先整一句人话这俩都是“背锅侠”但背法不一样早几年我在一家做政务系统的公司混甲方爸爸一句“必须兼容 IE9”我当场原地裂开。那时候天天跟这俩哥们打交道咖啡当水喝console 当聊天框。shim 和 polyfill 就像夜班同事一个帮你“翻译”甲方需求一个直接“造假”给你把功能硬怼出来。今天咱就把当年踩过的坑、熬过的夜、骂过的娘统统打包成一篇口水文能救一个是一个。从“想喝可乐”到“自己造汽水”——概念先掰扯清楚1. shim接口翻译官老鸨子接新客shim 的核心思想是“接口不变底层偷换”。浏览器不认新 API行我给它整一层“塑料普通话”让它听懂。举个最小白的例子IE 没有Array.prototype.forEach我们给它糊一层// 这就是纯血 shim代码里继续 forEach老浏览器也能跑if(!Array.prototype.forEach){Array.prototype.forEachfunction(callback,thisArg){// 老 IE 不认箭头函数咱就写 ES3 语法for(vari0;ithis.length;i){// 经典防坑跳过稀疏数组的 undefinedif(iinthis){callback.call(thisArg,this[i],i,this);}}};}看见没语法糖照常用背后全是“老鸨子”在接客客户新 API爽了浏览器旧环境也以为自己在玩老招式。2. polyfill功能克隆兵缺啥造啥polyfill 的哲学简单粗暴——“你没有我给你 3D 打印一个”。继续拿 IE 开涮IE 全家没有Promise那就从零搓一个// 超缩略版 Promise polyfill能跑但不严谨仅演示思路(function(global){functionMyPromise(executor){varselfthis;self.statepending;self.valueundefined;self.callbacks[];functionresolve(result){if(self.state!pending)return;self.statefulfilled;self.valueresult;// 异步模拟微任务真项目别这么写setTimeout(function(){self.callbacks.forEach(function(cb){cb.onFulfilled(result);});},0);}functionreject(reason){if(self.state!pending)return;self.staterejected;self.valuereason;setTimeout(function(){self.callbacks.forEach(function(cb){cb.onRejected(reason);});},0);}executor(resolve,reject);}MyPromise.prototype.thenfunction(onFulfilled,onRejected){varselfthis;returnnewMyPromise(function(resolve,reject){self.callbacks.push({onFulfilled:function(val){try{varxonFulfilled?onFulfilled(val):val;resolve(x);}catch(e){reject(e);}},onRejected:function(reason){try{varxonRejected?onRejected(reason):reason;reject(x);}catch(e){reject(e);}}});});};// 最后一步挂到全局假装自己是原生global.PromiseMyPromise;})(window);看到区别没polyfill 直接把缺失的“功能器官”移植进去 shim 只是“语言翻译”。一个动刀子一个动嘴皮子。实战场景到底什么时候上哪道菜场景 1产品经理非要你在 H5 里裁剪图片而且——“兼容到安卓 4.4”安卓 4.4 的 WebView 连canvas.toBlob都不给咋整思路先找 shim不行再上 polyfill。// 1. 先 shim把 toBlob 转成 toDataURL 再转 Blobif(!HTMLCanvasElement.prototype.toBlob){Object.defineProperty(HTMLCanvasElement.prototype,toBlob,{value:function(callback,type,quality){vardataURLthis.toDataURL(type,quality);varbinatob(dataURL.split(,)[1]);vararr[];for(vari0;ibin.length;i){arr.push(bin.charCodeAt(i));}varblobnewBlob([newUint8Array(arr)],{type:type||image/png});callback(blob);}});}一行业务代码不用改直接canvas.toBlob(blob {...})老 WebView 也能跑。这就是 shim 的爽点不动业务只动底层。场景 2后台小哥扔给你一段 swagger 生成的 TS 代码满屏async/awaitIE11 当场去世async/await语法糖背后是 generator Promise。IE11 连 Promise 都没有generator 更别聊。这种时候就别想 shim 了必须整 polyfill 全家桶先装依赖npmi core-js regenerator-runtime --save在入口顶部一次性喂饱// 把 core-js 的 stable 特性全打包进来体积爆炸但省心importcore-js/stable;// regenerator-runtime 负责 generator / asyncimportregenerator-runtime/runtime;如果只想按需强烈建议改写成importcore-js/es/promise;importcore-js/es/object/assign;importregenerator-runtime/runtime;然后 webpack 配置babel-loader加babel/preset-envuseBuiltIns: usage让 Babel 自动嗅探你代码里用到的 API帮你import对应的 polyfill。注意core-js 3 和 2 的目录结构不一样别整混了不然 IE 直接给你白屏现场尬舞。场景 3Safari 报“can’t find variable: IntersectionObserver”懒加载模块全崩IntersectionObserver 这玩意好用得飞起但 Safari 14 之前部分版本缺席。社区有现成的 polyfill体积 6KBgzip比自己手搓省头发npmi intersection-observer --save入口判断一下按需加载避免无谓流量// 动态加载 polyfill只有不支持才请求节省 6KBif(!(IntersectionObserverinwindow)){import(intersection-observer).then((){// 真正初始化懒加载initLazyLoad();});}else{initLazyLoad();}上面这段“懒加载 polyfill”的写法同样适用于ResizeObserver、fetch、URL等现代 API套路一模一样 CV 工程师狂喜。打包体积爆炸教你三招“瘦身术”1. 别一上来就import core-js;全量core-js 全量 90KBgzipIE 都退休了你还给全球用户塞红包用babel/preset-env的useBuiltIns: usagecorejs: 3Babel 会自动帮你按需引入立减 70KB 不是梦。2. 打包两层策略现代浏览器走“干净 bundle”老旧走“带 polyfill”webpack 多入口 HtmlWebpackPlugin的excludeChunks// webpack.config.jsmodule.exports{entry:{modern:./src/modern.js,legacy:./src/polyfilled.js},plugins:[newHtmlWebpackPlugin({filename:index.html,excludeChunks:[legacy]}),newHtmlWebpackPlugin({filename:legacy.html,excludeChunks:[modern]})]};服务器根据User-Agent把 IE 重定向到legacy.html其他现代浏览器走index.html。这一招对政务、银行项目尤其好用领导看你首屏 100 分绩效直接 20%。3. 动态 polyfill 服务polyfill.io 真香polyfill.io通过浏览器 UA 动态返回所需 polyfill链接丢一行即可!-- 只给缺失的浏览器返回代码体积≈0 --scriptcrossoriginanonymoussrchttps://polyfill.io/v3/polyfill.min.js?featuresdefault,es2015,IntersectionObserver/script自建也行源码在 GitHub内网部署不依赖外网妈妈再也不用担心我白屏。踩坑合集那些年一起熬过的夜坑 1重复引用 Promise polyfill导致instanceof Promise false有些库某聊天 SDK 不点名自己偷偷塞了个 Promise结果你业务代码里new Promise走的是另一份两边原型链不一致instanceof直接翻车。解决统一版本把core-js的 Promise 锁死或者在构建里alias强制指向同一文件。坑 2shim 把原生方法覆盖了性能雪崩某日期库为了兼容把Date.now重写成new Date().getTime()还全局覆盖。结果你代码里高频Date.now()做节流瞬间从 O(1) 变 O(N)。教训写 shim 一定先判断原生存不存在不存在再补千万别“强行覆盖”。坑 3WeakMap polyfill 内存泄漏IE 没有原生 WeakMap社区 polyfill 用数组 随机 key 模拟删不掉引用单页应用跑一晚上内存飙到 2G领导手机直接烫成暖手宝。解决IE 时代该退就退真要强上记得 Destroy 阶段手动清空或者限制缓存数量别再让 polyfill 背锅。坑 4babel-runtime 和 babel/plugin-transform-runtime 混用transform-runtime会把全局污染转成局部引用可你同时import core-js/stable又把 polyfill 挂到全局左右互搏包体积 double。正确姿势选边站。想全局污染 简单用preset-envuseBuiltIns想零污染 造库用transform-runtimecore-js-pure手写一个“最小但能用”的 fetch shim拿去忽悠面试官fetch 本质是 Promise XMLHttpRequestIE 没有 Promise我们假装 Promise 已存在前面已 polyfill下面只包 shim(function(global){// 参数序列化辅助超简化版functionobj2query(obj){varstr;for(varkinobj){if(obj.hasOwnProperty(k)){str(str?:)kencodeURIComponent(obj[k]);}}returnstr;}functionmyFetch(url,opts){optsopts||{};returnnewPromise(function(resolve,reject){varxhrnewXMLHttpRequest();varmethod(opts.method||GET).toUpperCase();vardataopts.body||null;// 处理 query 拼接if(methodGETopts.params){url(url.indexOf(?)-1?:?)obj2query(opts.params);}xhr.open(method,url,true);// 简单设置请求头if(opts.headers){for(varhinopts.headers){if(opts.headers.hasOwnProperty(h)){xhr.setRequestHeader(h,opts.headers[h]);}}}// 超时vartimeoutopts.timeout||0;if(timeout){xhr.timeouttimeout;xhr.ontimeoutfunction(){reject(newError(Request timeout));};}xhr.onloadfunction(){// 构造一个看起来像 Response 的对象varresponse{ok:xhr.status200xhr.status300,status:xhr.status,statusText:xhr.statusText,url:xhr.responseURL,text:function(){returnPromise.resolve(xhr.responseText);},json:function(){try{returnPromise.resolve(JSON.parse(xhr.responseText));}catch(e){returnPromise.reject(e);}}};resolve(response);};xhr.onerrorfunction(){reject(newError(Network error));};xhr.send(data);});}// 挂全局假装自己是原生 fetchglobal.fetchmyFetch;})(window);interviewer“小伙纸说说 fetch 原理”你“我自己写过xhr Promise 套壳IE 也能跑github 链接在这里……”注意生产别用缺太多细节仅忽悠用一句话总结别再把它们当“同义词”shim 接口翻译不造功能只转发。polyfill 功能克隆缺啥造啥自带器官。记住这句骚话“shim 是口红polyfill 是整容。”口红卸了还能看整容失败……那就只能回炉重造了。下次再有同事把俩词混着叫你就把这篇文章甩他脸上让他好好背三遍背不会webpack alias 配一夜包教包会保熟。欢迎来到我的博客很高兴能够在这里和您见面希望您在这里可以感受到一份轻松愉快的氛围不仅可以获得有趣的内容和知识也可以畅所欲言、分享您的想法和见解。推荐DTcode7的博客首页。一个做过前端开发的产品经理经历过睿智产品的折磨导致脱发之后励志要翻身农奴把歌唱一边打入敌人内部一边持续提升自己为我们广大开发同胞谋福祉坚决抵制睿智产品折磨我们码农兄弟专栏系列点击解锁学习路线(点击解锁知识定位《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架记录请求、封装、tabbar、UI组件的学习记录和使用技巧等《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容入坑前端或者辅助学习的必看知识《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客共同构建用户界面。通过操作DOM元素、响应事件、发起网络请求等JS使页面能够响应用户行为实现数据动态展示和页面流畅跳转是现代Web开发的核心《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法同时收集精美的CSS效果代码用来丰富你的web网页《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素通过JavaScript及其提供的绘图API开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力使得前端绘图技术更加丰富和多样化《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅《python相关博客》持续更新中~Python简洁易学的编程语言强大到足以应对各种应用场景是编程新手的理想选择也是专业人士的得力工具《sql数据库相关博客》持续更新中~SQL数据库高效管理数据的利器学会SQL轻松驾驭结构化数据解锁数据分析与挖掘的无限可能《算法系列相关博客》持续更新中~算法与数据结构学习总结通过JS来编写处理复杂有趣的算法问题提升你的技术思维《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术涉及软件开发、网络建设、系统维护等领域的知识《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理只要是从事信息化相关行业的人员都应该掌握这些信息化的基础知识可以不精通但是一定要了解避免日常工作中贻笑大方《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧提升自我能力与面试通过率扩展知识面《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等《photoshop相关博客》持续更新中~基础的PS学习记录含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结日常开发办公生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具丰富阅历给大家提供处理事情的更多角度学习了解更多的便利工具如Fiddler抓包、办公快捷键、虚拟机VMware等工具吾辈才疏学浅摹写之作恐有瑕疵。望诸君海涵赐教。望轻喷嘤嘤嘤非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益纵其简陋未及渊博亦足以略尽绵薄之力。倘若尚存阙漏敬请不吝斧正俾便精进