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,因为它会吃掉占位符;

  • 相关阅读:
    买房的贷款时间是否是越长越好?https://www.zhihu.com/question/20842791
    asp.net cookie and session
    leelazero and google colab
    download file by python in google colab
    physical processor, core, logical processor
    通过powershell操作eventlog
    openxml in sql server
    get the page name from url
    How to Execute Page_Load() in Page's Base Class?
    Difference between HttpContext.Request and Request
  • 原文地址:https://www.cnblogs.com/roy1/p/13748824.html
Copyright © 2011-2022 走看看