最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • webpack4打包优化(HappyPack、thread-loader)

    正文概述 掘金(秃头了更帅的金水)   2020-12-29   503

    一、速度分析

    安装插件speed-measure-webpack-plugin

    npm install --save-dev speed-measure-webpack-plugin
    

    引入插件、创建插件对象

    const SpeedMeasurePlugin = require('speed-measure-webpack-plugin'); //引入插件
    const smp = new SpeedMeasurePlugin(); //创建插件对象
    

    使用插件的wrap()方法将配置包起来

    module.exports = smp.wrap({
      entry: {
        index: './src/index.js',
        search: './src/search.js',
      }, 
      output: {
        path: path.join(__dirname, 'dist'), //__dirname(当前模块的目录名) + dist
        filename: '[name]_[chunkhash:8].js', //打包后输出的文件名,添加文件指纹 chunkhash
      },
    plugpins: [],
    .....
    });
    

    打包完成后控制台会输出各个loader的打包耗时,可根据耗时进一步优化打包速度 webpack4打包优化(HappyPack、thread-loader)

    二、体积分析

    体积分析可以分析哪些问题?

    1. 依赖的第三方模块文件大小
    2. 业务里面的组件代码大小

    打包后可以很清晰直观的看出各个模块的体积占比

    安装插件webpack-bundle-analyzer

    npm install --save-dev webpack-bundle-analyzer
    

    引入插件、创建插件对象

    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
    

    添加plugpins配置

     plugins: [
        new BundleAnalyzerPlugin()
      ],
    

    打包完成后浏览器会打开http://127.0.0.1:8888/显示打包后的体积分析

    webpack4打包优化(HappyPack、thread-loader)

    三、打包速度优化

    webpack构建过程中直接影响构建效率的,一个是文件的编译,另一个是文件的分类打包。相较之下文件的编译更为耗时,而且在Node环境下文件只能一个一个去处理,因此这块的优化需要解决。那么要怎样优化打包速度呢?

    1. 使用高版本的webpack和node.js

    webpack4新版本的优化使用v8引擎,v8带来的优化包括

    • for of 替代 forEach
    • Map和Set 替代Object
    • includes 替代 indexOf()
    • 默认使用更快的md4 hash算法 替代 md5算法,md4较md5速度更快
    • webpack AST 可以直接从loader传递给AST,从而减少解析时间
    • 使用字符串方法替代正则表达式

    更高版本的node.js对原生js api和js数据结构做出进一步的优化

    2. 多进程/多实例构建(资源并行解析)

    在webpack构建过程中,我们需要使用Loader对js,css,图片,字体等文件做转换操作,并且转换的文件数据量也是非常大的,且这些转换操作不能并发处理文件,而是需要一个个文件进行处理,我们需要的是将这部分任务分解到多个子进程中去并行处理,子进程处理完成后把结果发送到主进程中,从而减少总的构建时间。

    可选方案

    • thread-loader(官方推出)
    • parallel-webpack
    • HappyPack
    HappyPack

    注:由于HappyPack作者对js的兴趣逐步丢失,所以之后维护将变少,webpack4及之后推荐使用thread-loader 原理:每次webpack解析一个模块,HappyPack会将它及它的依赖分配给worker进程中; HappyPack会将模块进行一个划分,比如我们有多个模块,这些模块交给HappyPack,首先在webpack compiler(钩子)的run方法之后,进程就会到达HappyPack,HappyPack会做一些初始化,初始化之后会创建一个线程池,线程池会将构建任务里面的模块进行一个分配,比如会将某个模块以及它的一些依赖分配给其中的一个HappyPack线程,以此类推,那么一个HappyPack的一个线程池会包括多个线程,这时候线程池的这些线程会各自去处理其中的模块以及它的依赖,处理完成之后会有一个通信的过程,会将处理好的资源传输给HappyPack的一个主进程,完成整个的一个构建过程。

    webpack4打包优化(HappyPack、thread-loader)

    将src目录下复制出多个相同页面 webpack4打包优化(HappyPack、thread-loader) 在没引入HappyPack之前执行打包 webpack4打包优化(HappyPack、thread-loader) 安装 npm install --save-dev happypack 注:如果在webpack4使用需要HappyPack5.0的版本 引入之后将rules对js的编译改为happypack/loader

    rules: [
          {
            test: /.js$/, //对所有js后缀的文件进行编译
            use: [
              // 'babel-loader'
              'happypack/loader',
            ],
          },
    ]
    

    在插件中加入happypack-loader

      plugins: [
        new HappyPack({
          // 3) re-add the loaders you replaced above in #1:
          loaders: ['babel-loader'],
        }),
    ]
    

    webpack4打包优化(HappyPack、thread-loader) 很明显可以看出使用happypack之后打包速度加快很多

    thread-loader

    原理:与HappyPack类似,每次webpack解析一个模块,thread-loader会将它及它的依赖分配给worker进程中; 安装

    npm install --save-dev thread-loader
    

    在rule中添加thread-loader,thread-loader可以进行一些配置,例如workers(进程数)

    rules: [
          {
            test: /.js$/, //对所有js后缀的文件进行编译
            include: path.resolve('src'), //表示在src目录下的.js文件都要进行一下使用的loader
            use: [
              'babel-loader',
              {
                loader: 'thread-loader',
                options: {
                  workers: 3,
                },
              },
              // 'happypack/loader',
            ],
          },
    ]
    

    webpack4打包优化(HappyPack、thread-loader) 使用thread-loader之后打包速度也有明显提升

    3. 多进程/多实例进行代码压缩(并行压缩)

    在代码构建完成之后输出之前有个代码压缩阶段,这个阶段也可以进行并行压缩来达到优化构建速度的目的;

    可选方案

    • webpack-parallel-uglify-plugin
    • uglifyjs-webpack-plugin
    • terser-webpack-plugin**(webpack4.0推荐使用,支持压缩es6代码)**
    npm install terser-webpack-plugin --save-dev
    
    const TerserPlugin = require('terser-webpack-plugin');
    

    optimization中添加TerserPlugin插件,开启parallel

      optimization: {
        minimize: true,
        minimizer: [
          new TerserPlugin({
            //代码压缩插件
            parallel: 4, //开启并行压缩
          }),
        ],
      },
    

    4. 通过分包提升打包速度

    可以使用html-webpack-externals-plugin分离基础包,分离之后以CDN的方式引入所需要的资源文件,缺点就是一个基础库必须指定一个CDN,实际项目开发中可能会引用到多个基础库,还有一些业务包,这样会打出很多个script标签

    new HtmlWebpackExternalsPlugin({
      externals: [
        {
          module: 'react',
          entry: 'https://unpkg.com/react@16/umd/react.development.js',
          global: 'React',
        },
      ],
    })
    

    进一步分包,采用预编译资源模块 采用webpack官方内置的插件DLLPlugin进行分包,DdllReferenceRlugin对manifest.json引用 DLLPlugin可以将项目中涉及到的例如react、reactdom、redux等组件和框架库打包成一个文件,同时生成manifest.json文件 manifest.json是对分离出来的包进行一个描述,实际项目就可以引用manifest.json,引用之后就会关联DLLPlugin分离出来的包,这个文件是用来让 DLLReferencePlugin 映射到相关的依赖上去

    1. 首先使用DLLPlugin进行分包

    创建一个单独的构建配置文件,webpack.dll.js,在该配置文件中指定出需要分离的包 在package.json中添加dll的编译语句

      "scripts": {
        "dll": "webpack --config webpack.dll.js"
      }
    

    webpack.dll.js

    const webpack = require('webpack');
    const path = require('path');
    
    module.exports = {
      mode: 'development',
      entry: {
        //对应output 中的library
        library: ['react', 'react-dom'],
      },
      output: {
        filename: '[name]_[chunkhash].dll.js', //分离出来的文件名称,一个占位符+hash.dll.js  [name]对应的是entry的library
        path: path.join(__dirname, 'build/library'), //输出到当前目录下的build目录
        library: '[name]', //打包后暴露出的库的名字
      },
      plugins: [
        new webpack.DllPlugin({
          name: '[name]_[hash]', //打包后library.json中的name
          path: path.join(__dirname, 'build/library/[name].json'), //打包后生成[name].json的路径
        }),
      ],
    };
    

    npm run dll之后在build目录下会生成两个文件 webpack4打包优化(HappyPack、thread-loader) 也就是前面提到的manifest.json

    构建好之后使用DllReferencePlugin引用manifest.json

    plugins: [
        new webpack.DllReferencePlugin({
          manifest: require('./build/library/library.json'),
        }),
    ]
    

    5. 通过缓存提升二次打包速度

    • babel-loader 开启缓存
    • terser-webpack-plugin 开启缓存
    • 使用cache-loader或者 hard-source-webpack-plugin
        new HappyPack({
          loaders: ['babel-loader?cacheDirectory=true'],
        })
    

    设置babel-loader的cacheDirectory=true开启缓存

      optimization: {
        minimize: true,
        minimizer: [
          new TerserPlugin({
            //代码压缩插件
            parallel: 4, //开启并行压缩
            cache: true,
          }),
        ],
      },
    

    设置terser-webpack-plugin插件的cache: true开启缓存

    使用hard-source-webpack-plugin

    npm install --save-dev hard-source-webpack-plugin
    
      plugins: [
        new HardSourceWebpackPlugin()  
    ]
    

    第一次运行开始写入缓存文件 webpack4打包优化(HappyPack、thread-loader)

    webpack4打包优化(HappyPack、thread-loader) 开启缓存之后明显提升了打包速度

    6. 缩小构建目标

    尽可能的少构建模块,比如babel-loader不解析 node_modules

    • 优化resolve.modules配置(减少模块搜索层级)
    • 优化resolve.mainFields配置
    • 优化resolve.extensions配置

    四、打包体积优化

    主要对打包后图片、js、css文件的资源体积优化

    1. 图片压缩

    使用Node库的imagemin,配置image-webpack-loader对图片优化,改插件构建时会识别图片资源,对图片资源进行优化 imagemin优点分析

    • imagemin有很多定制选项
    • 可以引入更多第三方优化插件,例如pngquant
    • 可以引入多种图片格式

    imagemin的压缩原理

    • pngquant:是一款PNG的压缩器,通过将图像转换为具有alpha通道(通常比24/32位PNG文件小60%-80%)的更高效的8位PNG格式,可显著减小文件大小;

    阿尔法通道(Alpha Channel)是指一张图片的透明和半透明度

    • pngcrush:其主要目的是通过尝试不同的压缩级别和PNG过滤方法来降低PNG IDAT数据流的大小;
    • optipng:其涉及灵感来自于pngcrush。optipng可将图像文件重新压缩位更小的尺寸,而不会丢失任何信息;
    • tingpng:也是将24位png文件转化为更小具有索引的8位图片,同时所有非必要的metadata也会被剥离掉;

    npm install image-webpack-loader --save-dev

    rules: [
          {
            test: /.(png|jpg|gif|jpeg)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  name: '[name]_[hash:8].[ext]',
                },
              },
              {
                loader: 'image-webpack-loader',
                options: {
                  mozjpeg: {
                    progressive: true,
                    quality: 65,
                  },
                  // optipng.enabled: false will disable optipng
                  optipng: {
                    enabled: false,
                  },
                  pngquant: {
                    quality: [0.65, 0.9],
                    speed: 4,
                  },
                  gifsicle: {
                    interlaced: false,
                  },
                  // the webp option will enable WEBP
                  webp: {
                    quality: 75,
                  },
                },
              },
            ],
          }
    ]
    

    2. 擦除无用到的css

    可以同通过插件遍历代码,识别已经用到的css class 安装插件 npm i purgecss-webpack-plugin -D

    const PurgecssPlugin = require('purgecss-webpack-plugin');
    const PATHS = {
      src: path.join(__dirname, 'src'),
    };
    plugins: [
    new PurgecssPlugin({
          paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
        }),
    ]
    

    3. 动态Polyfill

    什么是Polyfill? babel默认只转换新的JavaScript语法(syntax),如箭头函数等,而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码;因此我们需要polyfill; 链接:https://www.jianshu.com/p/4822852792d1

    官方解释

    • 它是一项服务,接受对一组浏览器功能的请求,并且仅返回请求浏览器所需的polyfill。
    • 全世界有许多不同的浏览器和版本的浏览器在使用,每种浏览器都具有与其他浏览器完全不同的功能集。这会使浏览器开发成为一项艰巨的任务。流行浏览器的最新版本可以完成许多旧浏览器无法完成的任务-但是您可能仍必须支持旧浏览器。通过尝试使用polyfills重新创建缺少的功能,Polyfill.io使支持不同的浏览器变得更简单:您可以在支持或不支持的浏览器中使用最新和最强大的功能。

    通过caniuse查询可知,promise有96.17%的兼容性 webpack4打包优化(HappyPack、thread-loader)

    由于Polyfill是非必须的,对一些不支持es6新语法的浏览器才需要加载polyfill,为了百分之3.几的用户让所有用户去加载Polyfill是很没有必要的;

    我们可以通过polyfill-service,只给用户返回需要的polyfill 每次用户打开一个页面,浏览器端会请求polyfill-service,polyfill-service会识别用户User Agent,下发不同的polyfill 如何使用动态Polyfill service 通过polyfill.io官方提供的服务,自建polyfill服务polyfill.io/v3/url-buil…

    或者通过引入cdn<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>来加载polyfill-service 可以通过加载polyfill.io/v3/polyfill…网址来查看不同浏览器User Agent的情况;

    webpack4对打包构建速度优化和体积优化的内容到此结束,该文章通过学习程柳锋老师的《玩转webpack》课程实践总结得出,欢迎讨论和指正,以上。


    起源地下载网 » webpack4打包优化(HappyPack、thread-loader)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元