zoukankan      html  css  js  c++  java
  • Webpack 模块化打包优化

    一、 早期的前端打包工具有很多,主要是Grunt和Gulp等,他们早期的打包思路是通过一个配置文件告诉工具,哪些文件应该被绑定在一起输出到一个文件中,这样可以减少了http请求,还可以做一些压缩。

     而webpack的核心优势在于它从入口文件出发,递归构建依赖关系图。通过这样的依赖梳理,webpack打包出的bundle不会包含重复或未使用的模块,实现了按需打包,极大的减少了冗余。

    二、webpack做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(less、Sass/Scss,TypeScript,ES6+等),并将其转换和打包为合适的格式或版本供浏览器使用。

    三、 webpack最核心的理念是

    • 一切皆模块:JS,CSS,Image,Html,Font
    • 按需加载:默认会打包出一个bundle.js,可能很大,所以首屏速度很慢,所以webpack还可以使用一些特性对代码分割出多个“bundle”小文件,还可以实现按需异步加载等。

    四、本文主要记录webpack优化,主要有两个大的维度,一是打包速度,二是打包出来的体积。

    打包速度

    首先可以通过一些webpack自带的stats统计分析,还可以通过speed-measure-webpack-plugin专业插件进行分析,他可以分析各个plugin和loader具体耗时。

    也可以通过wbpack-bundle-analyzer工具启动一个图形化工具来进行标注,面积越大的区域,说明体积占用越多,比如很多项目引入全量的babel-ployfill,往往会占很大的面积,可通过user-agent去请求在线服务里的包,不同版本的浏览器可能需要的包大小不同。

    1. 首先应该使用更高版本的webpack,如现在是V4,它比V3版本提高了50%-98%的速度。

    • nodejs版本更高,使用了更高版本的V8引擎
    • ES6新的更优秀的语法,for of代替foreach, includes代替index of,map set代替 object,md4 代替md5, 字符串方式代替正则,多进程打包V4的thread-loader代替happy-pack
    • mode:production方式,默认自动内置了10来中优化插件。

    2. 充分利用缓存Cache

    • babel-loader,加入参数Cache-Directory=true
    • terser-webpack-plugin,配置cache:true,V3中使用uglifyJS-webpack-plugin(它也可以开启并行压缩,也有并行压缩的版本)压缩,但V4中不推荐使用了。
    • hard-source-webpack-plugin,对模块转换缓存

    他们都会在node_modules目录下.cache文件夹来缓存结果,这样就加快第二次打包速度。

    3. 缩小构建目标,减少对JS/JSX的分析,减少文件的搜索范围

      在loader中使用include、exclude来指定只分析某些目录,或者不分析某些目录

      webpack4有一个resolve节点,比如alias,可以直接告诉webpack某些第三方包(react,react-dom...)从哪里去获取,不用一层一层的遍历查找, extendsion,指定为JS,mainField指定为 main。

    4. 并行打包/压缩

      v3中使用的HappyPackPlugin(作者已经不维护升级了),ParallelUglifyJS并行压缩(对ES6支持不好),因此V4中推荐使用thread-loader(多进程)和terser-webpack-plugin(并行压缩)

    5. DllPlugin和DLLReferencePlugin

     官方维护的两个插件,他们支持分离基础包,提前把一些第三方基础架构包分离出来,比如生成一个vendor.js, 放到html模块中添加相对路径引用,同时也可以引用放到CDN缓存中的包。

    打包体积优化

    1. mode:production

      生产模式会默认使用10来个优化插件,比如TreeShaking(对代码静态分析,把没用的代码除去,减少体积),如没用使用的JS方法,变量,返回值,if(false){ xxx }语句等筛除,他还可以通过scop-hoisting减少闭包代码的生成。

     css需要通过uncss和purifycssplugin做TreeShaking。

    2. 图片压缩,会对图片再次压缩,这里和(url-loader)小图片base64编码内嵌到源文件中方式不同。

     image-webpack-loader。

    3. ployfill在线方法, 它很大,可以使用在线的CDN服务,它是一个在线服务器,根据user-agent只下载当前浏览器不支持的特性,相对包很小。

    4. 压缩,出掉空格,注释,换行符,长方法名混淆压缩为短方法名

     mini-css-extract-plugin,parallelUglifyJSPlugin, terser-webpack-plugin

    5. 代码分割

    • 首屏只加载首屏需要的JS
    • 按需动态import,这个需要babel插件(babel-plugin-syntax-dynamic-import),可以把一些第三方库,比如pdf,使用React.lazy和Suspense进行组件延迟加载,这里使用的是promise技术; 还可以使用react-loader等技术。
    • 使用splitChunksPlugin,对调用n次的代码,分成一个公共文件,webpack4中,它被内置放到optimization节点中进行配置。
    •  entry多入口,多页面,SEO更好,页面解耦。
    • require.ensure(), commonJS中使用等。

    webpack其他碎片知识

    loader/plugin

    babel-loader,ts-loader

    less/scss-loader(less/scss转换为css) -> css-loader(css转换为CommonJSObject) -> style-loader(内嵌到Html头部的style区域中),注意他们的顺序需要正确

    file-loader, 处理图片(jpg,jpeg,png,gif),字体等

    url-loader,可以把小文件内置到元素中,不用多一个请求。

    postcss-loader + autoprefixer自动给css加前缀(-moz-,-webkit-,-ms-,-o-)

    cleanwebpackplugin, 先清理生成目录

    raw-loader,减少http请求,比如一些初始化的css使用<script>require('raw-loader')内联进来,避免闪动。

    WDS (webpack-dev-server)

    主要模块是HMR-Server和HMR Runtime(浏览器端),HMR Server增量编译,得出差异,通知HMR-Runtime,HMR-Runtime通过jsonp方式传输变化的数据,再对浏览器局部刷新。

    文件指纹,版本管理

    hash,一个项目一个

    chunkHash,一个入口一个,一个页面入口一个,页面的css,js共有这个指纹

    contentHash,一个文件一个,文件内容不变,它的值不变。

    JS用chunkHash,如在output节点中的文件名使用:[name][chunkhash:8].js

    css用contentHash,在miniCssExtractPlugin配置,fileName:[name][contenthash:8].css

    注意:图片文件的指纹,他与前面几个不同,它的hash是它自身的md5值,所以options:{name:image/[name][hash:8].[ext]} 

    sourceMap

    eval: 使用eval包裹模块代码

    souce map:分离的一个个map文件

    cheap: 不包括列信息

    inline: JS和source map文件在一起

    module,包含loader的source map

    他们还可以排列组合出10多种类别,production模式下,设置为none

    服务端渲染 SSR,同构应用

    第一个请求就返回了首屏必要的data,由后端(Node)计算出Data后,renderToString插入(替换)到html模块的placeholder占位符中,再返回给客户端直接展示,常把数据挂在window.__initData__变量中。

    good:减少请求数量,加快显示,减少首屏白屏时间;SEO优化,有利于爬虫分析;

    bad:window,document等很多对象不能识别,需要hack处理,css不生效,需要使用css-in-jss等方式;fetch,ajax需要改成服务端兼容的axios,isomorphic-fetch;mode不能直接使用production,因为它会吃掉占位符;

  • 相关阅读:
    Spring Boot 使用 Micrometer 集成 Prometheus 监控 Java 应用性能
    Prometheus 通过 consul 实现自动服务发现
    Prometheus 通过 consul 分布式集群实现自动服务发现
    使用 PushGateway 进行数据上报采集
    AlertManager 之微信告警模板,UTC时间错8个小时的解决办法
    Prometheus 监控报警系统 AlertManager 之邮件告警
    Elasticsearch:使用 IP 过滤器限制连接
    Elasticsearch:创建 API key 接口访问 Elasticsearch
    Elasticsearch:反向代理及负载均衡在 Elasticsearch 中的应用
    Kibana:如何周期性地为 Dashboard 生成 PDF Report
  • 原文地址:https://www.cnblogs.com/roy1/p/13748824.html
Copyright © 2011-2022 走看看