一、开发环境:
1.优化打包构建速度,这样运行webpack就更快,就能更快看见构建效果。调试开发更加友好
2.优化代码调试功能
1.HMR:只会针对非入口文件进行使用
一旦修改了入口 文件,那么所有的都会变,所以这个不对入口文件使用
hot module replacement热模块替换/模块热替换
作用:一个模块发生变化,只会重新打包这一个模块,而不是打包所有,这样可以极大的提升代码构建速度
在devServer里配置: hot:true
并且样式文件:可以使用HMR功能,因为style-loader内部实现了
js文件:默认不可以使用HMR功能,所以需要修改js代码添加支持HMR功能的代码才可以使用
module会到全局找
这么添加之后,当print.js变化之后,只有print.js重新更新了,其他不变
html:默认不能使用HMR功能(因为html文件只有一个,一旦发生变化,没有其他的需要因此发生变化,不像js有很多个模块),同时会导致问题:html文件不能热更新了,怎么解决?:entry:改成一个数组,将html文件放进去,就可以热更新了
2.source-map
提供源代码到构建后代码的映射 技术,(因为构建后代码是很多个源代码的结合体,所以一旦构建后代码出错了,要找源头就很麻烦)(如果构建后代码出错了,通过映射关系可以追踪源代码错误,非常利于调试找错)
devtool:’source-map’ (inline-source-map/hidden-source-map/eval-source-map/nosources-source-map/cheap-source-map/moudle-source-map)
这些还可以俩俩组合
会生产一个sourcemap文件
上面是构建后的代码,下面是开发源代码,source-map可以提供详细准确的错误代码 提示信息和错误位置
不同环境采用哪个更好:
开发环境:要求速度快,调试更友好
速度快(eval>inline>cheap……)
还可以俩俩组合eval-cheap-source-map
调试友好:cheap-module-source-map
生产环境:源代码要不要隐藏?调试要不要更友好
二、生产环境:
1.oneof优化生产环境打包速度
之前每个文件都会被所有loader过一遍,比较费时,这样就不会反复被多个loader处理
如果有需要必须执行的loader,那可以将这个loader提取到外面
enforce:pre 会优先执行
2.优化缓存
1)babel+整体缓存资源(让第二次打包速度更快)
babel要对代码进行编译处理,编译成浏览器能识别的js,我们想如果只有一个js变,那就直接使用babel缓存(第一次编译将所有都缓存下来),不需要再重新构建多次
cacheDirectory:true
2)文件资源缓存(让代码上线运行缓存更好使用)
在缓存之后的build文件夹写一个服务器代码:server.js
在强制缓存期间不会访问服务器,直接读取本地缓存,如果强缓存期间出现严重bug,需要紧急修复,但又处在强制缓存,所以没法修复。这时候就可以给资源名称做手脚,加上个版本号,如果资源名称变了就重新缓存,没变就走强缓存的,一般加上哈希值。
每次webpack构建时会生成一个唯一的hash值,小问题:因为css和js打包都共享一个hash值,所以一旦重新打包,这俩是一起变的,所有缓存失效,而我只改动一个文件就导致所有一起变,这样不太好。
所以引入chunkhash值,根据chunk生成的hash值,打包来自同一个chuank,hash值就一样。
但当我换成chunkhash之后,js和css的hash值还是一样的,因为css是在js中被引入的,所以同属于一个chunk。所以这种方法耶不好用
所以第三种方法:contenthash:根据文件的内容生成hash值,不同文件hash值一定不一样,当文件内容不变hash值是恒不变的,
三、tree-shaking去除无用代码
将应用程序想做是一棵树,在应用程序中引入的源代码/第三方库,都可以想象成树上的绿叶,而没有引用的代码就想象成灰色枯萎的树叶。
为了去掉灰色的树叶,就可以摇动树叶,让它掉落。为了去除应用程序中没有使用的代码。减少代码体积
前提条件:
1.必须使用es6模块化
2.必须开启production环境
满足前提条件webpack自动会进行treeshaking
不同版本的tree-shaking会有点差异,有些可能会将css文件当作没用代码干掉,怎么解决?需要中package.json补上:
sideEffect:[“*.css”]
四、code split代码分割
将打包输出的一个chunk分割成多个文件,这样就可以并行加载/按需加载 ,从而速度更快
1.entry多入口
输出多个bundle文件,这样不太灵活,每次如果改了入口文件都需要自己再改
2.optimization:splitChunk
可以将node_modules中代码单独打包成一个chunk最终输出
并且会自动分析多入口chunk中,有没有公共的文件,如果有会打包成单独一个chunk
3.import动态导入语法:能将某个文件单独打包
通过js代码,让某个文件被单独打包成一个chunk
这样test文件就被单独打包了。
给打包出来的文件固定命名
五、懒加载、预加载
懒加载:放到异步回调函数中触发了再加载
js文件的懒加载,不是图片的
懒加载可以理解为:延迟加载,当触发了某些条件的时候再加载,而不是一上来就加载
将import语法加入到异步回调函数中,(这里也会进行代码分割的,先分成单独的文件,再进行加载)并且这样做,第二次操作的时候会使用缓存,而不会重新再加载
预加载:prefetch
会在使用之前,提前加载js文件
看上面截图打包出来的结果,还是两个文件,但多了个关键字(prefect)
看下面截图,第二次点击的时候,其实用的是上面加载过的缓存
预加载和懒加载正常加载有啥不一样呢?
正常加载可以认为是并行加载(同时加载多个文件,文件越多加载速度越慢,比如说因为http请求同一时间只能最多同时加载六个文件,换个域名又可以多再加载六个文件等)文件资源越多,后面的就得靠后加载,没有所谓的先后顺序,写在前面的就先加载,有可能这个先加载的暂时还没用,这样就浪费了大量时间。
而预加载是等其他资源加载完毕,浏览器空闲了,再偷偷加载资源。这样不会阻塞其他资源的加载。这个兼容性比较差,在移动端和IE有较大的兼容性问题,PC端就还好,所以慎用。
懒加载如果要加载的文件比较大,就会给用户体验不太好,延迟加载。
PWA
serviseWorker+cache 构成,作用:让我们的网页像app一样,离线也可以访问,性能也更好。
渐进式网络开发程序,有兼容性问题,淘宝就在使用,
访问掘金网站,看右边控制台,网络状态换成offline离线的时候
淘宝:大部分可以访问,少部分无法使用
PWA通过workbox库,借助插件:workbox-webpack-plugin
先npm插件,然后配置
这个插件可以帮助我们生成一个serviceWorker的配置文件,用这个配置文件去注册,注册一般在入口js文件中做配置,这时候要处理一下serviceWorker的兼容性问题:
编译之后会出现一个问题:eslint不认识navigator、window全局变量,怎么办?
在eslintConfig中添加配置,支持浏览器的全局变量
然后重新编译后还有个问题,serviceWorker的代码必须运行在服务器上,所以需要npm i serve -g这个会帮我们快速创建一个静态资源服务器
serve -s build 这个命令启动服务器,然后帮助我们把build里的资源作为(部署为)静态资源暴露出去。
重新编译之后,可以在控制台Application里找到注册的Service Workers资源:
同时在下面的cache API找到缓存的数据
切换离线状态,发现这些资源是从ServiceWork缓存的