KieSun / all-of-frontend

你想知道的前端内容都在这

Home Page:https://yuchengkai.cn/docs/frontend

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第十五题:webpack 优化

KieSun opened this issue · comments

commented

有做过哪些 webpack 优化?没有的话可以说下你了解的。

去答题

新建了一个大厂真题每日打卡群,有意愿学习打卡的再进,请备注打卡

marked

“面试官你也太 Low 了,现在都用 Vite 了,别问了,下一题吧。”

webpack的优化方法有:cdn加速、代码压缩、tree shaking和提取公共代码等

  • 提取公共代码
    主要用到了webpack的commonschunkPlugin插件,可以规定从哪些chunk中提取公共代码及提取出的新chunk的名称。一般将chunk中涉及的公共基础运行库代码提取到base中,其他相同代码提取到common中。同时可以设定minChunks,minChunks=3表示如果在给定的chunks中有3个chunk中都出现了同一段代码则提取。

  • CDN加速
    CDN指内容分发网络,目的是让用户能就近获取请求资源,提高用户访问系统的时间。本质是缓存,并且将数据缓存在离用户最近的地方。

  • 代码压缩
    使用到webpack的插件UglifyJSPlugin,
    在启动webpack时使用代码:webpack --optimize-minimize

-tree shaking
基于模块间的引用关系,将不被引用或没有使用到的模块删除,模块级别,不能处理函数冗余。

commented
没配置过,了解
  • 1、使用最新的 webpack 版本。我们会经常进行性能优化。 保持最新的 Node.js 也能够保证性能。除此之外,保证你的包管理工具 (例如 npm 或者 yarn ) 为最新也能保证性能。较新的版本能够建立更高效的模块树以及提高解析速度。

  • 2、将 loaders 应用于最少数的必要模块中。

  • 3、使用 DllPlugin 将更改不频繁的代码进行单独编译。这将改善引用程序的编译速度,即使它增加了构建过程的复杂性。

  • 4、减少编译的整体大小,以提高构建性能。尽量保持 chunks 小巧。 - 使用 更少/更小 的库。 - 在多页面应用程序中使用 CommonsChunksPlugin。 - 在多页面应用程序中以 async 模式使用 CommonsChunksPlugin 。 - 移除不使用的代码。 - 只编译你当前正在开发部分的代码。

  • 5、使用 cache-loader 启用持久化缓存。使用 package.json 中的 "postinstall" 清除缓存目录。

  • 6、基础包分离:使用 html-webpack-externals-plugin,将基础包通过 CDN 引入,不打入 bundle 中使用 SplitChunksPlugin 进行(公共脚本、基础包、页面公共文件)分离(Webpack4内置) ,替代了 CommonsChunkPlugin 插件

  • 7、多进程/多实例构建:HappyPack(不维护了)、thread-loader

- 1: exclude

- 2: noParse 告诉webpack 可以忽略解析包的依赖

- 3: 配置alias resolve: { alias: { "@": path.resolve(__dirname, '../src') }, },

- 4: ProvidePlugin 可以让我们不用再使用某些包的时候 再去编写 import new webpack.ProvidePlugin({ identifier: 'module1', // ... });

- 5 IgnorePlugin 忽略某些包中的不必要的文件 new webpack.IgnorePlugin({ resourceRegExp: /^./locale/,contextRegExp:/moment/, }); new webpack.IgnorePlugin(/./locale/,/moment/); // import moment from 'moment' import 'monent/local/dddd.js

- 6 多进程打包 thread-loader

- 7 减小文件搜索范围
resolve: { modules: ['node_modules','src'], },

- 8 可以不用安装某些包 而是直接通过cdn的方式引入,而且再我们的模块中还可以正常通过 import导入 externals: { jquery: 'jQuery', },

Webpack 性能优化

webpack 打包速度分析

  1. speed-measure-webpack-plugin

先从打包流程分析具体是哪里耗时

  1. 初始化 webpack.config.js
  2. loader 解析
  3. 搜索依赖文件
  4. 打包生成Chunk

耗时部分

  1. loader解析部分
  2. 搜索依赖文件
  3. 打包生成 Chunk

缩短 loader解析时间

  1. rules 规则优化,include 指定目录 exclude 排除掉不需要使用的内容
  2. 多进程加速loader解析时间 happy-pack好像已经没有再维护了 thread-loader 可以使用 thread-loader 预热 warnup
  3. 加缓存 cache-loader,babel-loader 自带缓存配置的也可以使用具体参考文档
  4. cache-loader 缓存流程 cache-loader 和 thread-loader 优先级是 thread-loader 更高

缩短搜索依赖文件的时间

  1. resolve.module
  2. resolve.alias
  3. resolve.extension

缩短打包时间

  1. 缓存生成 chunk
  2. 使用 SplitChunksPlugin 分包 移除未使用代码 具体配置看 Webpack SplitChunkPlugin
  3. webpack-bundle-analyzer 分析包大小,那些公共的引用模块可以提出来

其他方式

  1. DLL
  2. noParse
  3. IgnorePlugin
  • DLL 预先编译 第一次打包的时候预先编译好 第三方库的代码 如果不升级的话下次打包也不会打包他(DLL配置不方便,不推荐使用,Webpack4使用帮助已经不大了)
  • noParse 指不需要 Webpack指定的模块 不需要编译的模块(不存在任何模块化语法在其中 没有 required 没有 import)
  • IgnorePlugin 忽略大型包里引用的东西,大型包的模块化加载,需要引入的时候再进行引用 (在使用 moment 包的时候 会用到这个技巧)

1.配置 resolve.modules
减少搜索范围
2.配置装载机的 include & exclude
减少不必要的遍历,从而减少性能损失。
对于不需要处理的目录,予以排除,从而进一步提升性能。
3.安装webpack-parallel-uglify-plugin 压缩代码
减少构建时间
4.安装HappyPack 来加速代码构建

webpack性能优化

减少资源的大小

  • 压缩图片大小,url-loaderfile-loader通过limit判断图片大小是否要压缩,进行不同的配置,小的图片转换成Base64位
  • 参数mode,平时开发选择develpment,production 模式下 webpack 会对代码进行优化,如减小代码体积,删除只在开发环境用到的代码。
  • 使用es6 模块,进行树摇(tree shaking){presets: ['es2015']}
  • 提取公共模块 SplitChunksPlugin

文件缓存(让未修改的文件使用缓存,提高打包效率)

  • webpack⽂件指纹策略:对文件名设置hash,chunkhash(同一个chunk),contenthash(针对文件内容)值,来区分不同的版本
  • cache-loader/cacheDirectory:可以在一些开销大的loader上配置,用于缓存到磁盘中
  • Dll缓存

缩小构建范围

  • 使用resolve字段
  • noParse:不依赖其他库的文件,可以直接引入不需要解析
  • include,exclude:include表示可以引入的文件,exclude表示排除的文件,一些第三方模块并不需要babel-laoder,例如jquery,它本身是es5,所以可以直接排除
  • oneOf 把一些文件使用特定的loader加载

多进程

  • uglifyjs-webpack-plugin 多核压缩
  • 使用ParallelUglifyPlugin开启多进程压缩js文件

其他

  • 熟知的HMR 热模块更新
  • 使用mock,解决跨域问题
  • souceMap的参数配置 eval> inline> cheap
  • optimization.splitChunks分包
  • 检测工具 webpack-bundle-analyzer
  • 基础包分离,html-webpack-externals-plugin,将一些基础包分离出来
  • 使用clean-webpack-plugin清除dist,参数配置cleanOnceBeforeBuildPatterns 使dist⽬录下某个⽂件不被清理
  • 在文件引入模块时使用预加载 预获取
import(/* webpackPrefetch: true */ '');
import(/* webpackPreload: true */ '');
  • 使用CDN加速静态资源加载

webpack优化

我主要用vuecli脚手架,内部也是用的webpack打包,从vuecli3到vuecli5,现在都有项目

为什么要优化

默认的一些配置不能满足实际生产,webpack本身定制化和插件很成熟,能实现很多功能。

自己动手实现了一些常用的优化

  1. 路由按需加载 分块命名 import(/* webpackChunkName:'login'*/ '../component/Login.vue');
  2. 利用vue cli的环境变量,区分本地开发测试/正式环境,打包测试/正式环境
  3. 编写node脚本实现一键部署更新
  4. 资源一键上传七牛云,替换html引入的资源为cdn路径
  5. 自定义配置打包是否预渲染,是否页面单位像素自适应(rem)
  6. 同一项目仓库,多入口页面
  7. css预处理器支持sass语法
  8. 根据需求添加一些、引入loader
  9. webpack-dev-server 处理跨域请求
  10. 配置optimization.minimize实现代码打包后、压缩、美化、去除日志代码等。
  11. 配置optimization.splitChunks实现核心代码打包不拆分,并做文件大小的拆分限制等处理。
commented

打包体积优化

  • extends:防止将import进来的包打包的bundle中,在运行时通过script引入这些依赖
  • scope hosting
  • tree shaking
  • 公共资源压缩
  • 图片压缩
  • 动态polyfill

构建性能优化

  • 缩小文件查找范围
    • loader中配置include/exclude
    • resolve中的alias、extensions、modules、mainFiels
    • modules中的nopase 忽略部分非模块化模块的递归解析
  • 使用高版本的node和webpack
  • 开启多进程
    • happyPack
    • hread-loader
    • parallel-webpack
    • ParallelUglifyPlugin
  • 分包:DLLPlugin(动态链接库)进行分包,DllReferencePlugin对manifest.json引用
  • 开启缓存:支持缓存的开启缓存 比如在babel-loader中,可以通过设置cacheDirectory来开启缓存
    不支持缓存的,可以使用cache-loader

强推深入浅出webpack, 感觉这个看了 webpack理论就差不多了。
http://webpack.wuhaolin.cn/


自己的话再描述一遍

  • 缩小文件搜索范围 (webpack根据导入语句去找文件,然后给对应的loader处理)
    • 优化loader配置。通过include进行限制
    • 优化 resolve.modules。 给绝对路径 去查node-modules
    • 优化resolve.mainFields 。及第三方模块入口文件配置
    • resolve.alias。 导入路径映射
    • resolve.extensions。 后缀尝试
    • module.noParse 忽略没有采用模块化标准的库 例如 jq
  • 使用 DllPlugin 动态链接库
  • HappyPack 开启子进程
  • ParallelUglifyPlugin ,Uglify** 压缩代码
  • 热更新;自动刷新;区分环境;
  • webpack 静态资源接入cdn
  • Tree Shaking 把不引用的模块摇下来 这个很好玩,依赖静态模块化
  • 按需加载;提取公共代码;
  • 运行时效率优化:Prepack
  • Scope Hoisting 作用域提升

  • 其他
    • 打包静态文件到云端,通过不同环境区分前缀,提交代码携带manifest.json即可

提取公共代码
CDN加速
提取公共代码
使用高版本wepack
学习参考大佬的内容

  1. 打包体积优化
    静态资源压缩(css, js, 图片资源)
    按需引入,tree shaking
    提取公共代码
  2. 打包速度优化
    文件搜索(includes,exclude, alias等的数量要适度,过多会导致文件搜索费时)
    多进程打包thread-loader
  3. 充分利用缓存,每次打包的时候只需要打包新增或者改变的内容(cache-loader , dll plugin等 ),具体细节没用过。

强推深入浅出webpack, 感觉这个看了 webpack理论就差不多了。
http://webpack.wuhaolin.cn/

自己的话再描述一遍

  • 缩小文件搜索范围 (webpack根据导入语句去找文件,然后给对应的loader处理)

    • 优化loader配置。通过include进行限制
    • 优化 resolve.modules。 给绝对路径 去查node-modules
    • 优化resolve.mainFields 。及第三方模块入口文件配置
    • resolve.alias。 导入路径映射
    • resolve.extensions。 后缀尝试
    • module.noParse 忽略没有采用模块化标准的库 例如 jq
  • 使用 DllPlugin 动态链接库

  • HappyPack 开启子进程

  • ParallelUglifyPlugin ,Uglify** 压缩代码

  • 热更新;自动刷新;区分环境;

  • webpack 静态资源接入cdn

  • Tree Shaking 把不引用的模块摇下来 这个很好玩,依赖静态模块化

  • 按需加载;提取公共代码;

  • 运行时效率优化:Prepack

  • Scope Hoisting 作用域提升

  • 其他

    • 打包静态文件到云端,通过不同环境区分前缀,提交代码携带manifest.json即可

这本书好像蛮久的了 有些概念到现在Webpack 4 Webpack5 不太适用了 例如4-11 提取公共代码 是 Webpack3的概念

现在HappyPack都没人维护了,DLL也已经过时,可以看看 cache-loader thread-loader