哪个传奇私服好玩又不花钱的网络游戏!要倚天版本的L2K域8R

&&&&2K&7&发酵工程原理与技术应用&余龙江&&化学工业出版...
邀请好友参加吧
版 次:1页 数:100字 数:100印刷时间:日开 本:16开纸 张:胶版纸包 装:平装-胶订是否套装:否国际标准书号ISBN:7所属分类:&&&
下载免费当当读书APP
品味海量优质电子书,尊享优雅的阅读体验,只差手机下载一个当当读书APP
本商品暂无详情。
当当价:为商品的销售价,具体的成交价可能因会员使用优惠券、积分等发生变化,最终以订单结算页价格为准。
划线价:划线价格可能是图书封底定价、商品吊牌价、品牌专柜价或由品牌供应商提供的正品零售价(如厂商指导价、建议零售价等)或该商品曾经展示过的销售价等,由于地区、时间的差异化和市场行情波动,商品吊牌价、品牌专柜价等可能会与您购物时展示的不一致,该价格仅供您参考。
折扣:折扣指在划线价(图书定价、商品吊牌价、品牌专柜价、厂商指导价等)某一价格基础上计算出的优惠比例或优惠金额。如有疑问,您可在购买前联系客服咨询。
异常问题:如您发现活动商品销售价或促销信息有异常,请立即联系我们补正,以便您能顺利购物。
当当购物客户端手机端1元秒
当当读书客户端万本电子书免费读&p&入职前一天,我正收拾行李,准备离家去另一座城市报道。看我一件一件地把衣服塞进箱子,妈妈站在不远处絮叨着,要和同事处好关系,要尊敬领导,你年龄最小要主动干活,不要太计较……看着她认真的表情,我不忍心打断,只好耐心地“嗯”着等她说完。&/p&&p&&br&&/p&&p&“妈,我走了!”我站起来,向她告别。&/p&&p&&br&&/p&&p&“你能找到这么好的工作,妈妈就放心了!”她由衷地感慨道,自豪之情溢于言表。&/p&&p&&br&&/p&&p&我拎着箱子出了单元楼,回头看到玻璃窗上映出她的影子,于是向她挥了挥手,大步流星地向前走去。&/p&&p&&br&&/p&&p&一年前的这一幕,至今仍记忆犹新。&/p&&p&&br&&/p&&p&&b&“你有一份‘好工作’”——除了我自己,身边所有人都这么认为。&/b&&/p&&p&&br&&/p&&p&与一起入职的应届生相比,我应该算是很幸运的。一毕业就进入体制内管理岗,大家都客客气气和和睦睦,领导与同事作为长辈对我关怀备至,除了有时加班,除了没有什么同龄人可以交朋友的遗憾,似乎没有什么可以挑剔的。&/p&&p&&br&&/p&&p&我大抵可以一直这样生活下去。无需努力,拿着一份不高不低的薪水,不必为生计忧虑,工间休息时和老师傅们一起聊聊家庭琐事,刷手机打发时间,每一天都岁月静好。&/p&&p&&br&&/p&&p&新鲜感过去后,我陷入了一种僵尸般的生活状态。每天起床,上班,下班,睡觉,日复一日地做着重复机械劳动。说不出哪里不好,但是分明觉得生机与活力一天天地从我身体里溜走,取而代之的是懒散与懈怠。&/p&&p&&br&&/p&&p&眼看一天更比一天颓废,我忍不住问自己:这真的是你想要的生活吗?40岁的时候,你还会觉得这样的生活好吗?眼看同龄人一个个事业有成,昔日同窗早已在不觉间远远将你甩在身后,真的会甘心吗?&/p&&p&&br&&/p&&p&每天早上起来照镜子的时候,我都对自己说,不能再这样下去了!&/p&&p&&br&&/p&&p&然后又浑浑噩噩地过了一天。&/p&&p&&br&&/p&&p&&b&躺在出租屋的床上,莫名想哭。一种深深的无力感包裹着我。&/b&&/p&&p&&br&&/p&&p&回顾之前23年的人生,我出生在一个三线小城市并不富裕的家庭。98年母亲从国企下岗,家里只剩父亲微薄的工资,一度困窘到勉强度日。但他们都是极认真、极上进的人,凭着自己勤勤恳恳的工作态度与孜孜不倦的学习精神,后来终于成了我们当地行业内小有名气的专家。&/p&&p&&br&&/p&&p&受到父母榜样的激励,我成绩一直很好。我并不聪慧,但是凭着踏实的学习态度与高效的学习策略,除了高考略微有些不尽人意,总体来说学业一直顺风顺水。&/p&&p&&br&&/p&&p&小学时遭遇过校园冷暴力,我性格敏感,不擅长与人打交道。我喜欢安静,比起与人相处,更喜欢一个人捧着书度过一整天,与死去了几百年的人交谈。也因为读了很多书的缘故,我对世界的认知有着不切实际的古典主义情结。&/p&&p&&br&&/p&&p&如果生活一直这样下去,我大抵会继续扮演“好学生”的角色,做父母的乖乖女,按部就班地照着他们给我规划的路径前行。&/p&&p&&br&&/p&&p&大学时我遇到了人生的最低谷。我对母校的感情很复杂,又爱又恨。爱的是,我在这里学到了一生受用的知识,来自小城市的我在这里见到了以前没有见过的大世界,认识到“人外有人”,也接触到了专业以外其他领域。恨的是,在这里经历的一些事情让我在长达三年的时间里饱受抑郁症的折磨。除了室友和个别好友,我几乎和任何人没有交集,人际关系糟糕的一塌糊涂。&/p&&p&&br&&/p&&p&负面情绪太多,不想重述。这期间我吃过一种叫“草酸艾司西酞普兰”的药,盒子上有一枚笑脸。它比普通抗抑郁的药物价格高,但效果对我一点也不友好。我是敏感体质,我吃过的药物,但凡副作用中标注了“偶见”的,我九成概率会是那个“偶见”。&b&吃艾司西酞普兰的时候感觉像是在服毒。&/b&&/p&&p&&br&&/p&&figure&&img src=&/v2-68b14e241cfe2e37bfa5_b.jpg& data-rawwidth=&2048& data-rawheight=&1536& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&/v2-68b14e241cfe2e37bfa5_r.jpg&&&/figure&&p&&br&&/p&&p&&b&于是我知道谁也帮不了我,只有我才能给自己救赎。&/b&&/p&&p&&br&&/p&&p&在自闭的、与世隔绝的日子里,我将大把光阴挥霍在了我不擅长也不喜欢的那些专业课上。毕业的时候拿到了漂亮的成绩单——虽然不算出类拔萃,但是那些分数绝对对得起我付出的时间。以我的自我认知,若不是苦心钻研,我入学时的的理工科学习能力是绝不可能取得这样的成绩的。&/p&&p&&br&&/p&&p&&b&于是我明白了,什么都可能辜负你,但学习不会。&/b&&/p&&p&&br&&/p&&p&大二参加各种比赛、申专利、做项目,一年之间攒够了可以拿去写简历的全部内容。后来考研被数学拖了后腿而被迫参加春招,虽然过程历尽艰辛,但这份简历最终在我签到工作的过程中帮了大忙。&/p&&p&&br&&/p&&p&&b&于是我明白了,什么都可能欺骗你,但工作不会。&/b&&/p&&p&&br&&/p&&p&患病后的那一段时间里,我思考了许多。&b&我开始明白“不必活在别人的评价中”,也学会了控制自己的负面情绪。&/b&我读了许多心理学领域的书来帮助认知自己、调节自己的情绪。我曾经是一个非常情绪化的人,如今还是依然会有负面情绪,但很少会失控,而是面对愤怒时很快平息下来,在生气的时候不做出让自己冲动的后悔之举,可以置身事外般地看待发生在自己身上的一些事情。因为学会了情绪管理,在新的环境中,我的人际关系也开始向好的方向发展。&/p&&p&&br&&/p&&p&这一段经历让我的&b&自我意识开始觉醒&/b&,我开始摒弃自幼性格中迁就了所有人而唯独忽略自己的“懂事”,开始主动说“我想要”,开始不再畏首畏尾。&/p&&p&&br&&/p&&p&我曾为自己出身于小城市而自卑,曾经纠结于不甘心“一眼就看到老”的生活又无力改变。如今我已知道,&b&平台与地理空间从来都不是束缚能力的枷锁,真正限制发展的是人的心境。&/b&&/p&&p&&br&&/p&&p&终于在24岁那天下定决心与过去诀别。&/p&&p&&br&&/p&&p&工间休息的时候,我不再漫无目的刷手机打发时间,取而代之的是学习——考能考的证,看能看的书。我工位的文件筐里有一摞厚厚的A4纸,上面密密麻麻的都是我学习执业资格证考试中演算的过程、读书画的思维导图。学编程,优化工作方案,让计算机代替人工劳动。因为充实取代了空虚,我不再每天懒散地上班,换了一副精力充沛的模样。&/p&&p&&br&&/p&&p&我每天至少要读4小时的书,雷打不动。也因为此,这半年来,我思想的深度和广度都向着更深远的方向拓展,这些知识碎片铸成了我自己的知识体系。&/p&&p&&br&&/p&&p&学会了理财,从月光族到每月攒下大半,并且给自己与家人配置了保险;学投资,让钱为自己工作。定投指数基金,用一小部分去股市试水,以价值投资的理性决策代替投机主义。&/p&&figure&&img src=&/v2-f23ecc32bc66e2d6646d_b.png& data-rawwidth=&1257& data-rawheight=&850& class=&origin_image zh-lightbox-thumb& width=&1257& data-original=&/v2-f23ecc32bc66e2d6646d_r.png&&&/figure&&p&(这是数据回溯的过程)&/p&&figure&&img src=&/v2-fa3b7fcd87b0c6e3bacb354_b.jpg& data-rawwidth=&1117& data-rawheight=&846& class=&origin_image zh-lightbox-thumb& width=&1117& data-original=&/v2-fa3b7fcd87b0c6e3bacb354_r.jpg&&&/figure&&p&坚持健身。我自幼体弱多病,颇得双亲挂念;不为别的,只是想少去医院,给父母省省心。&br&&/p&&p&&br&&/p&&figure&&img src=&/v2-a0e6f3c4e2fef7f3cd195f2a8e0b9393_b.png& data-rawwidth=&1080& data-rawheight=&1920& class=&origin_image zh-lightbox-thumb& width=&1080& data-original=&/v2-a0e6f3c4e2fef7f3cd195f2a8e0b9393_r.png&&&/figure&&p&坚持练琴。即使一个人生活,也要有滋有味。&br&&/p&&figure&&img src=&/v2-1e7e6f6ffdda15f03003d_b.jpg& data-rawwidth=&1536& data-rawheight=&2048& class=&origin_image zh-lightbox-thumb& width=&1536& data-original=&/v2-1e7e6f6ffdda15f03003d_r.jpg&&&/figure&&figure&&img src=&/v2-c852afd837b9f3db930e_b.jpg& data-rawwidth=&2048& data-rawheight=&1536& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&/v2-c852afd837b9f3db930e_r.jpg&&&/figure&&p&坚持写作。把自己从书中汲取的精华,打碎了、重新整合再输出;和别人分享我的生活态度。写一些温暖的文章,写一些对别人有帮助的文章。&br&&/p&&p&&br&&/p&&p&结识了很多厉害的朋友。有的2011年就在人人网上写了阅读量10w+的文;有的上高中时候靠写小说就超过了自己父母的收入;有的只身走遍全国,会画画、会烧一手好菜,有趣的灵魂万里挑一;有的才华横溢,语不惊人死不休;有的是大学讲师,同时也是设计师、皮具师,还出版过三本小说;有的是互联网、自媒体行业的大牛,和他们交谈会发现更广阔的天地;有的朋友30多岁,但是比20多岁的我还要拼,看的书更多、写的文章更好,坚持健身,一天的日程清单比我两天做的事都要多……&/p&&p&&br&&/p&&p&这些朋友有一个共同的特质——他们都“&b&比我优秀且比我更努力&/b&”。每当我想要偷懒的时候,总是有人语重心长地对我说:倩倩,你要加油了啊——于是我只能继续前行,不敢有丝毫懈怠。我怕一不小心就再也追不上他们的步伐。&/p&&p&&br&&/p&&p&以前生活在自己的小圈子中,我恐怕连和他们搭讪的机会都没有,更不曾想也不敢想会与这些厉害的人成为朋友。在大家的帮助下,我以超越自己想象的速度成长。&/p&&p&&br&&/p&&p&从一个被世界抛弃的人,到成为一个给别人带来温暖的人。&/p&&p&&br&&/p&&p&从消极怠工、浑浑噩噩,到如今找到方向、砥砺前行。&/p&&p&&br&&/p&&p&因为努力学习,我得以因高考而离开出生的小城,见到更大的世界;因为努力想要走出黑夜,我得以挣脱抑郁的牢笼;因为努力想做自己,我得以发现并发展自己热爱的事业。因为努力,我认识了一群同样努力的人,他们愿意帮助我,愿意看到我成长。&/p&&p&&br&&/p&&p&我很喜欢《白夜行》中的一段话,“一天当中,有太阳升起的时候,也有下沉的时候。人生也一样,有白天和黑夜。人害怕的,就是本来一直存在的太阳落下不再升起,也就是非常害怕原本照在身上的光芒消失。”&/p&&p&&br&&/p&&p&&b&人究竟为什么要努力?&/b&&/p&&p&&br&&/p&&p&为了身处黑夜时不绝望、不放弃,依然相信自己能等到太阳升起的那一天。&/p&&p&&br&&/p&&p&为了在迷茫时不畏惧、不退缩,相信终归会有好的结局。&/p&&p&&br&&/p&&p&为了有一天能过上自己想要的生活,能长成自己希望的样子。&/p&&p&&br&&/p&&p&&b&你是什么样的人,就会结交什么样的人。&/b&&/p&&p&&br&&/p&&p&&b&你想成为什么样的人,最终就会成为什么样的人。&/b&&/p&
入职前一天,我正收拾行李,准备离家去另一座城市报道。看我一件一件地把衣服塞进箱子,妈妈站在不远处絮叨着,要和同事处好关系,要尊敬领导,你年龄最小要主动干活,不要太计较……看着她认真的表情,我不忍心打断,只好耐心地“嗯”着等她说完。 “妈,…
&figure&&img src=&/50/v2-5a361f0f3d8520a92cede_b.png& data-rawwidth=&2078& data-rawheight=&1016& class=&origin_image zh-lightbox-thumb& width=&2078& data-original=&/50/v2-5a361f0f3d8520a92cede_r.png&&&/figure&&h2&&b&前言&/b&&/h2&&p&在前端应用的优化中,对加载资源的大小控制极其的重要,大多数时候我们能做的是在打包编译的过程对资源进行大小控制、拆分与复用。&/p&&p&本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。&/p&&p&同时对打包资源的分析可以使用 (&a href=&/?target=https%3A///webpack-contrib/webpack-bundle-analyzer& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&webpack-contrib/webpack-bundle-analyzer&i class=&icon-external&&&/i&&/a&) 插件,当然可选的分析插件还是很多的,在本文中主要以该插件来举例分析。&/p&&p&&i&&b&TIP: webpack 版本 @3.6.0&/b&&/i&&/p&&hr&&h2&&b&一、打包环境与代码压缩&/b&&/h2&&p&首先我们有一个最基本的 webpack 配置:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&kr&&const&/span& &span class=&nx&&path&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'path'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&BundleAnalyzerPlugin&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'webpack-bundle-analyzer'&/span&&span class=&p&&).&/span&&span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&;&/span&
&span class=&kr&&const&/span& &span class=&nx&&PROJECT_ROOT&/span& &span class=&o&&=&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'./'&/span&&span class=&p&&);&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&entry&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&index&/span&&span class=&o&&:&/span& &span class=&s1&&'./src/index.js'&/span&
&span class=&p&&},&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&path&/span&&span class=&o&&:&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'dist'&/span&&span class=&p&&),&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s1&&'[name].[chunkhash:4].js'&/span&
&span class=&p&&},&/span&
&span class=&nx&&module&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&rules&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&p&&{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.js[x]?$/&/span&&span class=&p&&,&/span&
&span class=&nx&&use&/span&&span class=&o&&:&/span& &span class=&s1&&'babel-loader'&/span&&span class=&p&&,&/span&
&span class=&nx&&include&/span&&span class=&o&&:&/span& &span class=&nx&&PROJECT_ROOT&/span&&span class=&p&&,&/span&
&span class=&nx&&exclude&/span&&span class=&o&&:&/span& &span class=&sr&&/node_modules/&/span&
&span class=&p&&}&/span&
&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&()&/span&
&span class=&p&&],&/span&
&span class=&nx&&resolve&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&extensions&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'.js'&/span&&span class=&p&&,&/span& &span class=&s1&&'.jsx'&/span&&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&执行打包可以看到一个项目的 js 有 1M 以上:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: e51afc0b&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 2769ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&index.caa7.js
index&/span&
&/code&&/pre&&/div&&p&这时候只需要增加插件 `DefinePlugin` 与 `UglifyJSPlugin` 即可减少不少的体积,在 plugins 中添加:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&p&&...&/span&
&span class=&p&&{&/span&
&span class=&p&&...&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&(),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env.NODE_ENV'&/span&&span class=&o&&:&/span& &span class=&nx&&JSON&/span&&span class=&p&&.&/span&&span class=&nx&&stringify&/span&&span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&||&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&UglifyJSPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&uglifyOptions&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&ie8&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&comments&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&beautify&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&mangle&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&keep_fnames&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&drop_console&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&p&&}&/span&
&span class=&p&&})&/span&
&span class=&p&&]&/span&
&span class=&p&&...&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&可以看到这时候的打包输出:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: a6d3c5c25&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 9940ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&index.89c2.js
index&/span&
&/code&&/pre&&/div&&p&代码的大小从 1.3M 降到了 346K。&/p&&p&&b&(1)DefinePlugin&/b&&/p&&blockquote&DefinePlugin 允许创建一个在编译时可以配置的全局常量。这可能会对开发模式和发布模式的构建允许不同的行为非常有用。如果在开发构建中,而不在发布构建中执行日志记录,则可以使用全局常量来决定是否记录日志。这就是 DefinePlugin 的用处,设置它,就可以忘记开发和发布构建的规则。&/blockquote&&p&在我们的业务代码和第三方包的代码中很多时候需要判断 `process.env.NODE_ENV` 来做不同处理,而在生产环境中我们显然不需要非 `production` 的处理部分。&/p&&p&在这里我们设置 `process.env.NODE_ENV` 为 `JSON.stringify('production')`,也就是表示讲打包环境设置为生产环境。之后配合 `UglifyJSPlugin` 插件就可以在给生产环境打包的时候去除部分的冗余代码。&/p&&p&&b&(2)UglifyJSPlugin&/b&&/p&&p&UglifyJSPlugin 主要是用于解析、压缩 js 代码,它基于 `uglify-es` 来对 js 代码进行处理,它有多种配置选项:&a href=&/?target=https%3A///webpack-contrib/uglifyjs-webpack-plugin%25E3%& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&/webpack-contrib/uglifyjs-webpack-plugin。&i class=&icon-external&&&/i&&/a&&/p&&p&通过对代码的压缩处理以及去除冗余,大大减小了打包资源的体积大小。&/p&&hr&&h2&&b&二、代码拆分/按需加载&/b&&/h2&&p&在如 React 或者 vue 构建的单页面应用中,对页面路由与视图的控制是由前端来实现的,其对应的业务逻辑都在 js 代码中。&/p&&p&当一个应用设计的页面和逻辑很多的时候,最终生成的 js 文件资源也会相当大。&/p&&p&然而当我们打开一个 url 对应的页面时,实际上需要的并非全部的 js 代码,所需要的仅是一个主的运行时代码与该视图对应的业务逻辑的代码,在加载下一个视图的时候再去加载那部分的代码。&/p&&p&因此,对这方面可做的优化就是对 js 代码进行按需加载。&/p&&blockquote&懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。&/blockquote&&p&在 webpack 中提供了动态导入的技术来实现代码拆分,首先在 webpack 的配置中需要去配置拆分出来的每个子模块的配置:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&kr&&const&/span& &span class=&nx&&path&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'path'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&webpack&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'webpack'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&UglifyJSPlugin&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'uglifyjs-webpack-plugin'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&BundleAnalyzerPlugin&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'webpack-bundle-analyzer'&/span&&span class=&p&&).&/span&&span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&;&/span&
&span class=&kr&&const&/span& &span class=&nx&&PROJECT_ROOT&/span& &span class=&o&&=&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'./'&/span&&span class=&p&&);&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&entry&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&index&/span&&span class=&o&&:&/span& &span class=&s1&&'./src/index.js'&/span&
&span class=&p&&},&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&path&/span&&span class=&o&&:&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'dist'&/span&&span class=&p&&),&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s1&&'[name].[chunkhash:4].js'&/span&&span class=&p&&,&/span&
&span class=&nx&&chunkFilename&/span&&span class=&o&&:&/span& &span class=&s1&&'[name].[chunkhash:4].child.js'&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&module&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&rules&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&p&&{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.js[x]?$/&/span&&span class=&p&&,&/span&
&span class=&nx&&use&/span&&span class=&o&&:&/span& &span class=&s1&&'babel-loader'&/span&&span class=&p&&,&/span&
&span class=&nx&&include&/span&&span class=&o&&:&/span& &span class=&nx&&PROJECT_ROOT&/span&&span class=&p&&,&/span&
&span class=&nx&&exclude&/span&&span class=&o&&:&/span& &span class=&sr&&/node_modules/&/span&
&span class=&p&&}&/span&
&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&(),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env.NODE_ENV'&/span&&span class=&o&&:&/span& &span class=&nx&&JSON&/span&&span class=&p&&.&/span&&span class=&nx&&stringify&/span&&span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&||&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&UglifyJSPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&uglifyOptions&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&ie8&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&comments&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&beautify&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&mangle&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&keep_fnames&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&drop_console&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&p&&],&/span&
&span class=&nx&&resolve&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&extensions&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'.js'&/span&&span class=&p&&,&/span& &span class=&s1&&'.jsx'&/span&&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&其中主要需要定义的则是 `output` 中的 `chunkFilename`,它是导出的拆分代码的文件名,这里给它设置为 `[name].[chunkhash:4].child.js`,其中的 `name` 对应模块名称或者 id,`chunkhash` 是模块内容的 hash。&/p&&p&之后在业务代码中 webpack 提供了两种方式来动态导入:&/p&&ul&&li&`import('path/to/module') -& Promise`,&/li&&li&`require.ensure(dependencies: String[], callback: function(require), errorCallback: function(error), chunkName: String)`&/li&&/ul&&p&对于最新版本的 webpack 主要推荐使用 `import()` 的方式(&b&&i&注意:import 使用到了 Promise,因此需要确保代码中支持了 Promise 的 polyfill&/i&&/b&)。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// src/index.js&/span&
&span class=&kd&&function&/span& &span class=&nx&&getComponent&/span&&span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&kr&&import&/span&&span class=&p&&(&/span&
&span class=&cm&&/* webpackChunkName: &lodash& */&/span&
&span class=&s1&&'lodash'&/span&
&span class=&p&&).&/span&&span class=&nx&&then&/span&&span class=&p&&(&/span&&span class=&nx&&_&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&kd&&var&/span& &span class=&nx&&element&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&createElement&/span&&span class=&p&&(&/span&&span class=&s1&&'div'&/span&&span class=&p&&);&/span&
&span class=&nx&&element&/span&&span class=&p&&.&/span&&span class=&nx&&innerHTML&/span& &span class=&o&&=&/span& &span class=&nx&&_&/span&&span class=&p&&.&/span&&span class=&nx&&join&/span&&span class=&p&&([&/span&&span class=&s1&&'Hello'&/span&&span class=&p&&,&/span& &span class=&s1&&'webpack'&/span&&span class=&p&&],&/span& &span class=&s1&&' '&/span&&span class=&p&&);&/span&
&span class=&k&&return&/span& &span class=&nx&&element&/span&&span class=&p&&;&/span&
&span class=&p&&}).&/span&&span class=&k&&catch&/span&&span class=&p&&(&/span&&span class=&nx&&error&/span& &span class=&o&&=&&/span& &span class=&s1&&'An error occurred while loading the component'&/span&&span class=&p&&);&/span&
&span class=&p&&}&/span&
&span class=&nx&&getComponent&/span&&span class=&p&&().&/span&&span class=&nx&&then&/span&&span class=&p&&(&/span&&span class=&nx&&component&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&body&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&component&/span&&span class=&p&&);&/span&
&span class=&p&&})&/span&
&/code&&/pre&&/div&&p&可以看到打包的信息:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: d6ba79fe5995bcf9fa4d&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 7022ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&lodash.89f0.child.js
lodash&/span&
&span class=&go&&
index.316e.js
index&/span&
&span class=&go&&
[0] ./src/index.js 441 bytes {1} [built]&/span&
&span class=&go&&
[2] (webpack)/buildin/global.js 509 bytes {0} [built]&/span&
&span class=&go&&
[3] (webpack)/buildin/module.js 517 bytes {0} [built]&/span&
&span class=&go&&
+ 1 hidden module&/span&
&/code&&/pre&&/div&&p&可以看到打包出来的代码生成了 `index.316e.js` 和 `lodash.89f0.child.js` 两个文件,后者则是通过 `import` 来实现拆分的。&/p&&p&`import` 它接收一个 `path` 参数,指的是该子模块对于的路径,同时还注意到其中可以添加一行注释 `/* webpackChunkName: &lodash& */`,该注释并非是无用的,它定义了该子模块的 name,其对应与 `output.chunkFilename` 中的 `[name]`。&/p&&p&`import` 函数返回一个 Promise,当异步加载到子模块代码是会执行后续操作,比如更新视图等。&/p&&p&&b&(1)React 中的按需加载&/b&&/p&&p&在 React 配合 React-Router 开发中,往往就需要代码根据路由按需加载的能力,下面是一个基于 webpack 代码动态导入技术实现的 React 动态载入的组件:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&nx&&React&/span&&span class=&p&&,&/span& &span class=&p&&{&/span& &span class=&nx&&Component&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'react'&/span&&span class=&p&&;&/span&
&span class=&kr&&export&/span& &span class=&k&&default&/span& &span class=&kd&&function&/span& &span class=&nx&&lazyLoader&/span& &span class=&p&&(&/span&&span class=&nx&&importComponent&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&kr&&class&/span& &span class=&nx&&AsyncComponent&/span& &span class=&kr&&extends&/span& &span class=&nx&&Component&/span& &span class=&p&&{&/span&
&span class=&nx&&state&/span& &span class=&o&&=&/span& &span class=&p&&{&/span& &span class=&nx&&Component&/span&&span class=&o&&:&/span& &span class=&kc&&null&/span& &span class=&p&&}&/span&
&span class=&nx&&async&/span& &span class=&nx&&componentDidMount&/span& &span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&kr&&const&/span& &span class=&p&&{&/span& &span class=&k&&default&/span&&span class=&o&&:&/span& &span class=&nx&&Component&/span& &span class=&p&&}&/span& &span class=&o&&=&/span& &span class=&nx&&await&/span& &span class=&nx&&importComponent&/span&&span class=&p&&();&/span&
&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&setState&/span&&span class=&p&&({&/span&
&span class=&nx&&Component&/span&&span class=&o&&:&/span& &span class=&nx&&Component&/span&
&span class=&p&&});&/span&
&span class=&p&&}&/span&
&span class=&nx&&render&/span& &span class=&p&&()&/span& &span class=&p&&{&/span&
&span class=&kr&&const&/span& &span class=&nx&&Component&/span& &span class=&o&&=&/span& &span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&state&/span&&span class=&p&&.&/span&&span class=&nx&&Component&/span&&span class=&p&&;&/span&
&span class=&k&&return&/span& &span class=&nx&&Component&/span&
&span class=&o&&?&/span& &span class=&o&&&&/span&&span class=&nx&&Component&/span& &span class=&p&&{...&/span&&span class=&k&&this&/span&&span class=&p&&.&/span&&span class=&nx&&props&/span&&span class=&p&&}&/span& &span class=&o&&/&&/span&
&span class=&o&&:&/span& &span class=&kc&&null&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&p&&}&/span&
&span class=&k&&return&/span& &span class=&nx&&AsyncComponent&/span&&span class=&p&&;&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&在 `Route` 中:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&o&&&&/span&&span class=&nx&&Switch&/span&&span class=&o&&&&/span&
&span class=&o&&&&/span&&span class=&nx&&Route&/span& &span class=&nx&&exact&/span& &span class=&nx&&path&/span&&span class=&o&&=&/span&&span class=&s2&&&/&&/span&
&span class=&nx&&component&/span&&span class=&o&&=&/span&&span class=&p&&{&/span&&span class=&nx&&lazyLoader&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&kr&&import&/span&&span class=&p&&(&/span&&span class=&s1&&'./Home'&/span&&span class=&p&&))}&/span&
&span class=&o&&/&&/span&
&span class=&o&&&&/span&&span class=&nx&&Route&/span& &span class=&nx&&path&/span&&span class=&o&&=&/span&&span class=&s2&&&/about&&/span&
&span class=&nx&&component&/span&&span class=&o&&=&/span&&span class=&p&&{&/span&&span class=&nx&&lazyLoader&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&kr&&import&/span&&span class=&p&&(&/span&&span class=&s1&&'./About'&/span&&span class=&p&&))}&/span&
&span class=&o&&/&&/span&
&span class=&o&&&&/span&&span class=&nx&&Route&/span&
&span class=&nx&&component&/span&&span class=&o&&=&/span&&span class=&p&&{&/span&&span class=&nx&&lazyLoader&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&kr&&import&/span&&span class=&p&&(&/span&&span class=&s1&&'./NotFound'&/span&&span class=&p&&))}&/span&
&span class=&o&&/&&/span&
&span class=&o&&&&/span&&span class=&err&&/Switch&&/span&
&/code&&/pre&&/div&&p&在 `Route` 中渲染的是 `lazyLoader` 函数返回的组件,该组件在 mount 之后会去执行 `importComponent` 函数(既:`() =& import('./About')`)动态加载其对于的组件模块(被拆分出来的代码),待加载成功之后渲染该组件。&/p&&p&使用该方式打包出来的代码:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: 02a053d135a&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 9399ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&0.db22.child.js
[emitted]&/span&
&span class=&go&&1.fcf5.child.js
[emitted]&/span&
&span class=&go&&2.442d.child.js
[emitted]&/span&
&span class=&go&&
index.1bbc.js
index&/span&
&/code&&/pre&&/div&&hr&&h2&&b&三、抽离 Common 资源&/b&&/h2&&p&&b&(1)第三方库的长缓存&/b&&/p&&p&首先对于一些比较大的第三方库,比如在 React 中用到的 react、react-dom、react-router 等等,我们不希望它们被重复打包,并且在每次版本更新的时候也不希望去改变这部分的资源导致在用户端重新加载。&/p&&p&在这里可以使用 webpack 的 CommonsChunkPlugin 来抽离这些公共资源;&/p&&blockquote&CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存起来到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。&/blockquote&&p&首先需要在 entry 中新增一个入口用来打包需要抽离出来的库,这里将 `'react', 'react-dom', 'react-router-dom', 'immutable'` 都给单独打包进 `vendor` 中;&/p&&p&之后在 plugins 中定义一个 `CommonsChunkPlugin` 插件,同时将其 `name` 设置为 `vendor` 是它们相关联,再将 `minChunks` 设置为 `Infinity` 防止其他代码被打包进来。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&kr&&const&/span& &span class=&nx&&path&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'path'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&webpack&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'webpack'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&UglifyJSPlugin&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'uglifyjs-webpack-plugin'&/span&&span class=&p&&);&/span&
&span class=&kr&&const&/span& &span class=&nx&&BundleAnalyzerPlugin&/span& &span class=&o&&=&/span& &span class=&nx&&require&/span&&span class=&p&&(&/span&&span class=&s1&&'webpack-bundle-analyzer'&/span&&span class=&p&&).&/span&&span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&;&/span&
&span class=&kr&&const&/span& &span class=&nx&&PROJECT_ROOT&/span& &span class=&o&&=&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'./'&/span&&span class=&p&&);&/span&
&span class=&nx&&module&/span&&span class=&p&&.&/span&&span class=&nx&&exports&/span& &span class=&o&&=&/span& &span class=&p&&{&/span&
&span class=&nx&&entry&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&index&/span&&span class=&o&&:&/span& &span class=&s1&&'./src0/index.js'&/span&&span class=&p&&,&/span&
&span class=&nx&&vendor&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'react'&/span&&span class=&p&&,&/span& &span class=&s1&&'react-dom'&/span&&span class=&p&&,&/span& &span class=&s1&&'react-router-dom'&/span&&span class=&p&&,&/span& &span class=&s1&&'immutable'&/span&&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&path&/span&&span class=&o&&:&/span& &span class=&nx&&path&/span&&span class=&p&&.&/span&&span class=&nx&&resolve&/span&&span class=&p&&(&/span&&span class=&nx&&__dirname&/span&&span class=&p&&,&/span& &span class=&s1&&'dist'&/span&&span class=&p&&),&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s1&&'[name].[chunkhash:4].js'&/span&&span class=&p&&,&/span&
&span class=&nx&&chunkFilename&/span&&span class=&o&&:&/span& &span class=&s1&&'[name].[chunkhash:4].child.js'&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&module&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&rules&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&p&&{&/span&
&span class=&nx&&test&/span&&span class=&o&&:&/span& &span class=&sr&&/\.js[x]?$/&/span&&span class=&p&&,&/span&
&span class=&nx&&use&/span&&span class=&o&&:&/span& &span class=&s1&&'babel-loader'&/span&&span class=&p&&,&/span&
&span class=&nx&&include&/span&&span class=&o&&:&/span& &span class=&nx&&PROJECT_ROOT&/span&&span class=&p&&,&/span&
&span class=&nx&&exclude&/span&&span class=&o&&:&/span& &span class=&sr&&/node_modules/&/span&
&span class=&p&&}&/span&
&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&(),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env.NODE_ENV'&/span&&span class=&o&&:&/span& &span class=&nx&&JSON&/span&&span class=&p&&.&/span&&span class=&nx&&stringify&/span&&span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&||&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&UglifyJSPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&uglifyOptions&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&ie8&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&comments&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&beautify&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&mangle&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&keep_fnames&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&drop_console&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&s1&&'vendor'&/span&&span class=&p&&,&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&kc&&Infinity&/span&&span class=&p&&,&/span&
&span class=&p&&}),&/span&
&span class=&p&&],&/span&
&span class=&nx&&resolve&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&extensions&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'.js'&/span&&span class=&p&&,&/span& &span class=&s1&&'.jsx'&/span&&span class=&p&&]&/span&
&span class=&p&&},&/span&
&span class=&p&&};&/span&
&/code&&/pre&&/div&&p&运行打包可以看到:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: 34a71fcfd9a24e810c21&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 9618ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&0.2c65.child.js
[emitted]&/span&
&span class=&go&&1.6e26.child.js
[emitted]&/span&
&span class=&go&&2.e4bc.child.js
[emitted]&/span&
&span class=&go&&
index.4e2f.js
index&/span&
&span class=&go&& vendor.5fd1.js
vendor&/span&
&/code&&/pre&&/div&&p&可以看到 `vendor` 被单独打包出来了。&/p&&p&当我们改变业务代码时再次打包:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: cd3f1bc16b28ac97e20a&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 9750ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&0.2c65.child.js
[emitted]&/span&
&span class=&go&&1.6e26.child.js
[emitted]&/span&
&span class=&go&&2.e4bc.child.js
[emitted]&/span&
&span class=&go&&
index.4d45.js
index&/span&
&span class=&go&& vendor.bc85.js
vendor&/span&
&/code&&/pre&&/div&&p&vendor 包同样被打包出来的,然而它的文件 hash 却发生了变化,这显然不符合我们长缓存的需求。&/p&&p&这是因为 webpack 在使用 CommoChunkPlugin 的时候会生成一段 runtime 代码(它主要用来处理代码模块的映射关系),而哪怕没有改变 vendor 里的代码,这个 runtime 仍然是会跟随着打包变化的并且打入 verdor 中,所以 hash 就会开始变化了。解决方案则是把这部分的 runtime 代码也单独抽离出来,修改之前的 `CommonsChunkPlugin` 为:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&p&&...&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'vendor'&/span&&span class=&p&&,&/span& &span class=&s1&&'runtime'&/span&&span class=&p&&],&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&kc&&Infinity&/span&&span class=&p&&,&/span&
&span class=&p&&}),&/span&
&span class=&p&&...&/span&
&/code&&/pre&&/div&&p&执行打包可以看到生成的代码中多了 `runtime` 文件,同时即使改变业务代码,vendor 的 hash 值也保持不变了。&/p&&p&当然这段 `runtime` 实际上非常短,我们可以直接 inline 在 html 中,如果使用的是 `html-webpack-plugin` 插件处理 html,则可以结合 [`html-webpack-inline-source-plugin`](&a href=&/?target=https%3A///DustinJackson/html-webpack-inline-source-plugin& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&DustinJackson/html-webpack-inline-source-plugin&i class=&icon-external&&&/i&&/a&) 插件自动处理其 inline。&/p&&p&&b&(2)公共资源抽离&/b&&/p&&p&在我们打包出来的 js 资源包括不同入口以及子模块的 js 资源包,然而它们之间也会重复载入相同的依赖模块或者代码,因此可以通过 CommonsChunkPlugin 插件将它们共同依赖的一些资源打包成一个公共的 js 资源。&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&(),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env.NODE_ENV'&/span&&span class=&o&&:&/span& &span class=&nx&&JSON&/span&&span class=&p&&.&/span&&span class=&nx&&stringify&/span&&span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&||&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&UglifyJSPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&uglifyOptions&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&ie8&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&comments&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&beautify&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&mangle&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&keep_fnames&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&drop_console&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'vendor'&/span&&span class=&p&&,&/span& &span class=&s1&&'runtime'&/span&&span class=&p&&],&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&kc&&Infinity&/span&&span class=&p&&,&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&c1&&// ( 公共chunk(commnons chunk) 的名称)&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&s2&&&commons&&/span&&span class=&p&&,&/span&
&span class=&c1&&// ( 公共chunk 的文件名)&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s2&&&commons.[chunkhash:4].js&&/span&&span class=&p&&,&/span&
&span class=&c1&&// (模块必须被 3个 入口chunk 共享)&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&mi&&3&/span&
&span class=&p&&})&/span&
&span class=&p&&],&/span&
&/code&&/pre&&/div&&p&可以看到这里增加了 `commons` 的一个打包,当一个资源被三个以及以上 chunk 依赖时,这些资源会被单独抽离打包到 `commons.[chunkhash:4].js` 文件。&/p&&p&执行打包,看到结果如下:&/p&&div class=&highlight&&&pre&&code class=&language-console&&&span&&/span&&span class=&go&&Hash: d8b94114c8&/span&
&span class=&go&&Version: webpack 3.6.0&/span&
&span class=&go&&Time: 24009ms&/span&
&span class=&go&&
Chunk Names&/span&
&span class=&go&&0.2eee.child.js
[emitted]&/span&
&span class=&go&&1.cfbc.child.js
[emitted]&/span&
&span class=&go&&2.557a.child.js
[emitted]&/span&
&span class=&go&& vendor.66fd.js
vendor&/span&
&span class=&go&&
index.688b.js
index&/span&
&span class=&go&&commons.a61e.js
commons&/span&
&/code&&/pre&&/div&&p&却发现这里的 `commons.[chunkhash].js` 基本没有实际内容,然而明明在每个子模块中也都依赖了一些相同的依赖。&/p&&p&借助 &b&webpack-bundle-analyzer&/b& 来分析一波:&/p&&figure&&img data-rawheight=&1612& src=&/v2-c36ddabeca6f331a86809e_b.jpg& data-rawwidth=&2876& class=&origin_image zh-lightbox-thumb& width=&2876& data-original=&/v2-c36ddabeca6f331a86809e_r.jpg&&&/figure&&p&可以看到三个模块都依赖了 `lodash`,然而它并没有被抽离出来。&/p&&p&这是因为 CommonsChunkPlugin 中的 chunk 指的是 entry 中的每个入口,因此对于一个入口拆分出来的子模块(children chunk)是不生效的。&/p&&p&可以通过在 CommonsChunkPlugin 插件中配置 `children` 参数将拆分出来的子模块的公共依赖也打包进 `commons` 中:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&(),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env.NODE_ENV'&/span&&span class=&o&&:&/span& &span class=&nx&&JSON&/span&&span class=&p&&.&/span&&span class=&nx&&stringify&/span&&span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&||&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&UglifyJSPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&uglifyOptions&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&ie8&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&comments&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&beautify&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&mangle&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&keep_fnames&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&drop_console&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'vendor'&/span&&span class=&p&&,&/span& &span class=&s1&&'runtime'&/span&&span class=&p&&],&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&kc&&Infinity&/span&&span class=&p&&,&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&c1&&// ( 公共chunk(commnons chunk) 的名称)&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&s2&&&commons&&/span&&span class=&p&&,&/span&
&span class=&c1&&// ( 公共chunk 的文件名)&/span&
&span class=&nx&&filename&/span&&span class=&o&&:&/span& &span class=&s2&&&commons.[chunkhash:4].js&&/span&&span class=&p&&,&/span&
&span class=&c1&&// (模块必须被 3个 入口chunk 共享)&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&mi&&3&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&c1&&// (选择所有被选 chunks 的子 chunks)&/span&
&span class=&nx&&children&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&&span class=&p&&,&/span&
&span class=&c1&&// (在提取之前需要至少三个子 chunk 共享这个模块)&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&mi&&3&/span&&span class=&p&&,&/span&
&span class=&p&&})&/span&
&span class=&p&&],&/span&
&/code&&/pre&&/div&&p&查看打包效果:&/p&&figure&&img data-rawheight=&1612& src=&/v2-dcc5e563be3cfd6e8312268_b.jpg& data-rawwidth=&2880& class=&origin_image zh-lightbox-thumb& width=&2880& data-original=&/v2-dcc5e563be3cfd6e8312268_r.jpg&&&/figure&&p&其子模块的公共资源都被打包到 `index` 之中了,并没有理想地打包进 `commons` 之中,还是因为 `commons` 对于的是 entry 中的入口模块,而这里并未有 3 个 entry 模块共用资源;&/p&&p&在单入口的应用中可以选择去除 `commons`,而在子模块的 `CommonsChunkPlugin` 的配置中配置 `async` 为 `true`:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// webpack.config.js&/span&
&span class=&nx&&plugins&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&
&span class=&k&&new&/span& &span class=&nx&&BundleAnalyzerPlugin&/span&&span class=&p&&(),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&DefinePlugin&/span&&span class=&p&&({&/span&
&span class=&s1&&'process.env.NODE_ENV'&/span&&span class=&o&&:&/span& &span class=&nx&&JSON&/span&&span class=&p&&.&/span&&span class=&nx&&stringify&/span&&span class=&p&&(&/span&&span class=&nx&&process&/span&&span class=&p&&.&/span&&span class=&nx&&env&/span&&span class=&p&&.&/span&&span class=&nx&&NODE_ENV&/span& &span class=&o&&||&/span& &span class=&s1&&'production'&/span&&span class=&p&&)&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&UglifyJSPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&uglifyOptions&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&ie8&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&output&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&comments&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&beautify&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&},&/span&
&span class=&nx&&mangle&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&keep_fnames&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&nx&&compress&/span&&span class=&o&&:&/span& &span class=&p&&{&/span&
&span class=&nx&&warnings&/span&&span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&nx&&drop_console&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&
&span class=&p&&},&/span&
&span class=&p&&}&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&nx&&name&/span&&span class=&o&&:&/span& &span class=&p&&[&/span&&span class=&s1&&'vendor'&/span&&span class=&p&&,&/span& &span class=&s1&&'runtime'&/span&&span class=&p&&],&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&kc&&Infinity&/span&&span class=&p&&,&/span&
&span class=&p&&}),&/span&
&span class=&k&&new&/span& &span class=&nx&&webpack&/span&&span class=&p&&.&/span&&span class=&nx&&optimize&/span&&span class=&p&&.&/span&&span class=&nx&&CommonsChunkPlugin&/span&&span class=&p&&({&/span&
&span class=&c1&&// (选择所有被选 chunks 的子 chunks)&/span&
&span class=&nx&&children&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&&span class=&p&&,&/span&
&span class=&c1&&// (异步加载)&/span&
&span class=&nx&&async&/span&&span class=&o&&:&/span& &span class=&kc&&true&/span&&span class=&p&&,&/span&
&span class=&c1&&// (在提取之前需要至少三个子 chunk 共享这个模块)&/span&
&span class=&nx&&minChunks&/span&&span class=&o&&:&/span& &span class=&mi&&3&/span&&span class=&p&&,&/span&
&span class=&p&&})&/span&
&span class=&p&&],&/span&
&/code&&/pre&&/div&&p&查看效果:&/p&&figure&&img data-rawheight=&1608& src=&/v2-74bbde7a66_b.jpg& data-rawwidth=&2880& class=&origin_image zh-lightbox-thumb& width=&2880& data-original=&/v2-74bbde7a66_r.jpg&&&/figure&&p&子模块的公共资源都被打包到 `0.9c90.child.js` 中了,该模块则是子模块的 commons。&/p&&hr&&h2&&b&四、tree shaking&/b&&/h2&&blockquote&tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。这个术语和概念实际上是兴起于 ES2015 模块打包工具 rollup。&/blockquote&&p&在我们引入一个依赖的某个输出的时候,我们可能需要的仅仅是该依赖的某一部分代码,而另一部分代码则是 `unused` 的,如果能够去除这部分代码,那么最终打包出来的资源体积也是可以有可观的减小。&/p&&p&首先,webpack 中实现 tree shaking 是基于 webpack 内部支持的 es2015 的模块机制,在大部分时候我们使用 babel 来编译 js 代码,babel 默认会将 ESModule 编译成 CommonJS 方式,这导致 webpack 中的 tree shaking 处理失效。因此在 babel 的配置中需要关闭对模块加载的处理:&/p&&div class=&highlight&&&pre&&code class=&language-json&&&span&&/span&&span class=&err&&//&/span& &span class=&err&&.babelrc&/span&
&span class=&p&&{&/span&
&span class=&nt&&&presets&&/span&&span class=&p&&:&/span& &span class=&p&&[&/span&
&span class=&p&&[&/span&
&span class=&s2&&&env&&/span&&span class=&p&&,&/span& &span class=&p&&{&/span&
&span class=&nt&&&modules&&/span&&span class=&p&&:&/span& &span class=&kc&&false&/span&&span class=&p&&,&/span&
&span class=&p&&}&/span&
&span class=&p&&],&/span&
&span class=&s2&&&stage-0&&/span&
&span class=&p&&],&/span&
&span class=&err&&...&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&然后我们来看下 webpack 是如何处理打包的代码,举例有一个入口文件 `index.js` 和一个 `utils.js` 文件:&/p&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// utils.js&/span&
&span class=&kr&&export&/span& &span class=&kd&&function&/span& &span class=&nx&&square&/span&&span class=&p&&(&/span&&span class=&nx&&x&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nx&&x&/span& &span class=&o&&*&/span& &span class=&nx&&x&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&kr&&export&/span& &span class=&kd&&function&/span& &span class=&nx&&cube&/span&&span class=&p&&(&/span&&span class=&nx&&x&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nx&&x&/span& &span class=&o&&*&/span& &span class=&nx&&x&/span& &span class=&o&&*&/span& &span class=&nx&&x&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&sb&&```&/span&
&span class=&sb&&```&/span&&span class=&nx&&js&/span&
&span class=&c1&&// index.js&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&cube&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'./utils.js'&/span&&span class=&p&&;&/span&
&span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&cube&/span&&span class=&p&&(&/span&&span class=&mi&&10&/span&&span class=&p&&));&/span&
&span class=&sb&&```&/span&
&span class=&sb&&打包出来的代码:&/span&
&span class=&sb&&```&/span&
&span class=&c1&&// index.bundle.js&/span&
&span class=&cm&&/* 1 */&/span&
&span class=&cm&&/***/&/span& &span class=&p&&(&/span&&span class=&kd&&function&/span&&span class=&p&&(&/span&&span class=&nx&&module&/span&&span class=&p&&,&/span& &span class=&nx&&__webpack_exports__&/span&&span class=&p&&,&/span& &span class=&nx&&__webpack_require__&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&s2&&&use strict&&/span&&span class=&p&&;&/span&
&span class=&cm&&/* unused harmony export square */&/span&
&span class=&cm&&/* harmony export (immutable) */&/span& &span class=&nx&&__webpack_exports__&/span&&span class=&p&&[&/span&&span class=&s2&&&a&&/span&&span class=&p&&]&/span& &span class=&o&&=&/span& &span class=&nx&&cube&/span&&span class=&p&&;&/span&
&span class=&kd&&function&/span& &span class=&nx&&square&/span&&span class=&p&&(&/span&&span class=&nx&&x&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nx&&x&/span& &span class=&o&&*&/span& &span class=&nx&&x&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&span class=&kd&&function&/span& &span class=&nx&&cube&/span&&span class=&p&&(&/span&&span class=&nx&&x&/span&&span class=&p&&)&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nx&&x&/span& &span class=&o&&*&/span& &span class=&nx&&x&/span& &span class=&o&&*&/span& &span class=&nx&&x&/span&&span class=&p&&;&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&p&可以看到仅有 `cube` 函数被 `__webpack_exports__` 导出来,而 `square` 函数被标记为 `unused harmony export square`,然而在打包代码中既是 `square` 没有被导出但是它仍然存在与代码中,而如何去除其代码则可以通过添加 `UglifyjsWebpackPlugin` 插件来处理。&/p&&hr&&h2&&b&TIP&/b&&/h2&&p&关注我的博客:&a href=&/?target=https%3A//qiutc.me/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&阿城的日志&i class=&icon-external&&&/i&&/a& ;&/p&&p&该文章在博客中为原文:&a href=&/?target=https%3A//qiutc.me/post/resource-optimization-webpack.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&使用 webpack 优化资源&i class=&icon-external&&&/i&&/a&。&/p&
前言在前端应用的优化中,对加载资源的大小控制极其的重要,大多数时候我们能做的是在打包编译的过程对资源进行大小控制、拆分与复用。本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理…
谢邀,先给答案,有四个可能的答案:&br&&br&&b&1. 宇宙没有外&/b&&br&&b&2. 宇宙有外&br&3. 宇宙外面有什么,我们不知道&br&4. 宇宙外面有什么,我们可以猜&/b&&br&&br&最有意思的是,这四个答案,从不同的角度来看,都对。&br&&br&恩,接下来会用到些高维空间的知识,我就尽量说的简单点吧,一个一个来:&br&&br&&b&&u&1. 宇宙没有外&/u&&/b&&br&&br&&b&宇宙的大小是有限的,但是没有边界,也就没有外。&/b&&br&&br&很多人问:“我一直往一个方向一直走一直走,走到一个地方走不下去了,不就是有边界了嘛?” “我往宇宙外面扔一个球,如果被弹回来了,不就是宇宙的边界嘛?”&br&&br&没错,你不会走到尽头发现一堵墙写着“禁止通行”,也不会被宇宙边界弹回的球砸到脑袋。宇宙确实没有这样的边界。但这并不代表宇宙是无限的。&br&&br&为了理解我们的三维宇宙,就先降维到二维世界去看看吧。举第一个关于二维世界的例子,我们的地球。&br&&br&&figure&&img src=&/4c1bb85f1a555a_b.jpg& data-rawwidth=&343& data-rawheight=&336& class=&content_image& width=&343&&&/figure&&br&地球的表面是一个球体曲面,不考虑人类的飞行器飞离地球,人类生活的领域无非上至平流层的飞机,下至地壳表面的矿井深处。与整个地球的尺度比起来,我们相当于只是生活在地球二维表面的生物。&br&&br&在这样一个二维表面上,地球有边界么?——没有,你可以沿着经纬线一路走下去,不会有把你拦在外面的尽头。&br&在这样的一个二维表面上,地球的面积是有限的么?——有的,大概是5.1亿平方公里。&br&所以,&b&二维地球表面是大小有限且没有边界的。&/b&&br&&br&我们的三维宇宙,也是如此。&br&在地球上的小尺度范围内,你站在广袤的平原上,认为地是平的。可从太空俯瞰地球的话,其实地面是弯曲的。你沿着一个方向走下去,会绕地球一圈走回原地。&br&在我们的宇宙里,你以为从一点到另一点是直的,但大尺度范围来看,其实空间也是弯曲的。你拿着激光笔往远方直射,光线不会射到宇宙的壁上,而是会绕了一个大圈照到你的后脑勺。(如果你能等足够久的话)&br&你以为他是直的,其实他是弯的。&br&&br&在二维地球面上,不存在“外”。中国有外,你越过国境往北会去到蒙古。亚洲有外,往西翻越乌拉尔山会去到欧洲。但地球表面没有外,因为没有“边界”。&br&在三维宇宙里,也不存在“外”。“楚门的世界”有外,《楚门的世界》男主活在一个被创造的世界里,他划船远航,终于撞到了他那虚拟世界的边缘。太阳系有外,旅行者号假以时日,穿越过太阳系边缘的奥尔特云,就可以离开太阳系。整个宇宙没有外,刚才说了,没有“边界”。&br&&figure&&img src=&/49f18fa4ad0c40d0f323ffff01ddb450_b.jpg& data-rawwidth=&880& data-rawheight=&495& class=&origin_image zh-lightbox-thumb& width=&880& data-original=&/49f18fa4ad0c40d0f323ffff01ddb450_r.jpg&&&/figure&&i&《楚门的世界》剧照,男主划船出海,撞到了世界的边缘。&/i&&br&&br&当然,&b&没有”边界“,不代表它”大的没有边了“&/b&,一个没有边界的空间,也可以很小。&br&比如一个乒乓球的二维表面,没有边界,但表面积就小的可怜。&br&比如我们的宇宙也曾小过,我们的宇宙诞生于138亿年前的宇宙大爆炸,在大爆炸的起点(称之为Time 0),宇宙密度为无限大,所有的物质挤在一个体积为0的小空间里,然后迅速爆炸,过了138亿年,形成了现在我们看到的宇宙。可在刚刚爆发的一瞬,其实宇宙有一刻和一个苹果一样大,甚至可以放到你现在的手心里。&br&乒乓球的二维表面是有限面积的,宇宙的三维空间是有限体积的(体积多大?现在我们也不太确定)。&br&&br&&figure&&img src=&/999dd4dbf4dec6689b8afe01_b.jpg& data-rawwidth=&500& data-rawheight=&301& class=&origin_image zh-lightbox-thumb& width=&500& data-original=&/999dd4dbf4dec6689b8afe01_r.jpg&&&/figure&&br&&i&宇宙大爆炸时间演进图,在时间0点附近,宇宙小的可以放在你的手心里。&/i&&br&&br&第一部分完毕,&b&宇宙没有外,但它有限。&/b&&br&&br&&b&&u&2. 宇宙有外&/u&&/b&&br&&br&这时候一定有读者要问,你说二维地球表面没有外,但旅行者号不是离开地球了么?再看下面这张地球的图,B和C都在地球表面,但A不是在外面了么?A是不是地球的外面?对于宇宙来说,有没有这样的点A?答案是,没错,&b&在更高维度上,宇宙其实也有外面,但这个“外面”,跟我们平时了解的“外面”不一样。&/b&&br&&figure&&img src=&/8bef0e14ee37abcd56e1_b.jpg& data-rawwidth=&343& data-rawheight=&336& class=&content_image& width=&343&&&/figure&&br&A点确实在地球表面二维空间的“外面”,但这是升了一个维度,从二维球面来到了三维空间。那么如果我们在三维空间升一个维度,进入四维空间,那么,宇宙也存在这样的A点,宇宙有外。&br&但是,如果是只生活在地球二维球面,不懂什么是三维空间的二维生物,不会理解A点的存在。同样,对于我们这些生活在三维空间里的人类,也不会找到宇宙四维空间以外的A点。&br&&br&为什么说所谓的“外面”,和我们平时说的“外面”不一样?&br&因为&b&任何高维到低维的降维,都会将大量的信息压缩在一个狭窄的空间里。&/b&&br&比如,用铅笔在纸上划一道,你得到了一条线——这是一维。&br&用显微镜观察,你会发现这条线是有宽度的——这是二维。&br&镜头再拉近,你会发现一颗颗石墨颗粒粘在纸上——这是三维。&br&镜头从近到远,从三维回到二维再回到一维,降维了,相当于把一颗颗石墨颗粒复杂的三维空间信息挤压进了狭小的一维的一条线。&br&信息

我要回帖

更多关于 不花钱的网络游戏 的文章

 

随机推荐