当前位置: 首页 > news >正文

【Vue五分钟】五分钟了解webpack的高级概念

📚 前言

📑博客主页:@丘比特惩罚陆

💖欢迎关注:点赞收藏⭐留言✒
💬系列专栏:web前端、嵌入式、笔记专栏
🎮 加入社区: 灌水乐园
🥇人生格言:选对方向,每走一步都是进步!
✒️欢迎大佬指正,一起学习!一起加油!

👏 希望大家能小手一动,帮忙点个赞!

😁资源邮箱:2237814512@qq.com;微信:lss0901lili1130

目录

📚 前言

1.Tree Shaking部分 

2.Development和Production模式的区分打包

3.webpack和codesplitting

4.splitChunksPlugin配置参数

5.Lazy Loading懒加载 

6.打包分析、preloading、prefetching

7.CSS文件的代码分割

8.webpack与浏览器缓存

9.shimming的作用

10.环境变量的使用方法


1.Tree Shaking部分 

其实如果配置了 useBuiltIns 就不会需要再 import babel profill。 实际上目前的话虽然只是引入了某个模块的某个方法,在打 包还是会把模块的所有方法引入,最好是引入什么打包什么, 这就需要 tree shaking,摇掉不需要的内容。 注意 tree shaking 只支持 ES 模块的引入。 如果想开启,在开发环境下添加↓即可。如下:

optimization: {
   usedExports:true
},

如此配置后引入如果并没有导出内容但是确实是有用的(如 profill)就会被直接忽略了,就会出错,所以才加上 sideEffects, 指定不需要 tree shaking 的文件,若是设置为 false,就全部 都要 tree shaking。 一般 css 也需要放进去。

"sideEffects":[

"*.css"
]

  当然了在开发环境下,tree shaking 并不会把代码直接从打包 后的 js 中剔除掉,只是提示一下,因为直接改的话 source map 映射就不对了,改为线上环境则会生效(而且 tree shaking
一些默认配置甚至已经写好了,都不用写,直接改个环境就 行)。

2.Development和Production模式的区分打包

  开发环境 source map 比较全,但是线上就简洁。 开发环境代码一般不压缩,线上则压缩。 如果切换环境要一直更改 webpack.config.js 文件则比较麻烦, 可以复制拆成 dev、prod 两个 js 文件

"script": {
   "dev":"webpack-dev-server --config webpack.dev.js",
"bulid":"webpack -- config webpack.prod.js"
},

当你开发完成并打包线上环境代码,形成文件,放到服务器,和后端相互结合就可以了;但是是这样子存在大量重复的代码,我们可以创建一个webpack.common.js文件存放共同的代码。

const HtmlWebpackPlugin = require('html-webpack-plugin ' );
const CleanwebpackPlugin = require( 'clean-webpack-plugin' );
module.exports = {
entry: {

main:'./src/ index.js·},

然后依靠一个第三方模块 webpack-merge,在导出的时候合 并配置即可,

const merge = require( 'webpack-merge');
const commonConfig = require( './webpack.common.js ');
const prodConfig= {
mode: 'production' ,
devtool: 'cheap-module-source-map'}
module.exports = merge( commonConfig, prodConfig);
const webpack = require( 'webpack' );
const merge = require( 'webpack-merge ' );
const commonConfig = require( ' ./webpack.common.js ');
const devConfig = {
mode: 'development',
devtool: 'cheap-module-eval-source-map ' ,devServer: i
contentBase: './dist',open: true,
port: 8080,hot: true3,
plugins:[
new webpack.HotModuleReplacementPlugin(],
optimization: {
usedExports: true}
}
module.exports = merge( commonConfig,devConfig);

3.webpack和codesplitting

Code splitting 就是代码分割。 注意 clean 插件会以 webpack.config.js 所在目录为根目录,也 就只能清除根目录下面的内容,无法清除根目录外的内容, 不过我们可以添加一个 root 参数重新指定根路径。

plugins: [
new HtmlwebpackPlugin({
template: 'src/index.html'}),
new cleanWebpackPlugin(['dist'l,{
root: path.resolve(_ dirname, '../')})
],
output: {
filename: '[name] .js ',
path: path.resolve(_dirname, '../dist ')}

 当我们引入一个工具库,且在下面写了非常多业务逻辑,目 前最终也是打包到一个文件中,当然无异常,只是这个 js 文 件会非常大,用户需要等到这个文件加载完成;另外如果只 是简单的改变了一点业务逻辑,用户又需要重新加载这个文 件。可以通过在其它文件引入工具库,挂载到 window 就能在其 它文件中使用该库,然后其它文件就写业务逻辑,当然入口 要 2 个。

  如此就换了一个打包方式(将单文件拆成几个文件),打包 后会生成两个 JS 文件,浏览器可以并行加载,可能会比单独 加载一个大文件要快一些,同时业务逻辑变更也只是需要加 载业务逻辑文件。 这种拆分公用部分代码的做法就是 code splitting,这个其实 与 webpack 没有任何关系,是我们自己拆分,当然了 webpack 现在内置有处理拆分代码的插件,就捆绑到一起了,拆分变 得更加简单。 目前简单配置如下↓,打包后会有 main.js(只有业务逻辑了) 和 vendors-main.js(提取了类库的代码),因为这是同步的模 块引入,可以分析提取。

entry :{
  main:'./src/index.js'
}
optimization: {
splitChunks:{
chunks: 'all'}
},

但是如果是异步加载呢(需要先安装处理异步语法的 babel, 因为还是实验性质语法),打包后依然只是index放业务逻辑,0.js 放类库。也就是说异步加载可以不写 optimization 配置, 也能实现代码分割。

function getcomponent( {
return import( ' lodash' ).then(({ default: -})=>{
var element = document.createElement('div');.element.innerHTML = _.join(['Dell', ‘Lee'],'-');return elepent;
})
}
getcomponent( ).then(element>i
document. body-appendChild(element);})

4.splitChunksPlugin配置参数

目前打包异步代码生成的文件名是以 id 命名,如果想自定义 名字可以采用魔法注释命名;

function getComponent() {
return import(/* webpackCbunkName: "lodash"*/ 'lodash ")
element.innerHTML = _.join( I'Dell',‘Lee']','-');return element;
})

当然了之前安装的处理异步第三方插件不支持魔法注释,需要换一个官方的。

presets: [
"@babel/preset-env",{
targets: {
chrome: "67",},
useBuiltIns: 'usage'}
],
"@babel/preset-react"],.t,-1..
piugins: ["@babel/plugin-syntax-dynamic-import"]}

最终生成的文件名就是 vendors~lodash.js,当然了如果想去 掉 vendors 可以修改 splitChunks 的参数。

optimization: {
splitChunks: {
chunks: 'all',cacheGroups: {
vendors: false,defadlt: false}
}

不管是同步异步都最好使用配置,而且配置都对它们有效。
 

optimization: i
splitChunks: {
chunks: 'async'minSize: 3000o,|maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,maxInitialRequests: 3,
automaticNameDelimiter: '~',name: true,
cacheGroups: i
vendors: false,default: false}
}},

Chunks 参数代表是对同步/异步/全部代码生效,比如 async 就是只对异步代码有效

cacheGroups: i
vendors: i
test: /[N/]node_modules [V/]/,priority:-10
},
default: false}

CacheGroups 是确定需要处理的代码(chunks 属性)后就走 到这里,test 检验是否是在 node 模块目录下(类库)引入, 是就可以分割,并且归于 vendors 这个组(这就是代码会有 vendors 前缀),也可以通过 filename 属性自定义打包后的名 字。minSize 是引入的类库,大于这个值才做代码分割(这里就是 30kb)。
  CatchGroups 中的 default 就是处理没有任何组接收的文件, 因此自定义的模块就是写到 default~main.js,当然也还是可 以 filename 自定义名字,可以看到不管怎么说这些配置最终 都和 catchGroups 有关。 MaxSize 是对比较超过它的值尝试对代码进行二次拆分,拆 分 n 个该值大小的文件,基本不行,可以不配置。 MinChunks 就是代码至少被引入多少次才做代码分割。 MaxAsyncRequests 是最大同时加载的请求,也就是最多拆分 多少个。

5.Lazy Loading懒加载 

 之前写成异步加载的模式就是为了能够懒加载(异步加载模 块,什么时候真正执行该模块才加载该模块,具体是和 ES6 的实验性方法 import()有关,与 webpack 无关,只不过是 webpack 可以识别需要懒加载的模块)。

function getcomponent(O {
return import(/* webpackChunkName : "lodash"*/‘lodash')
var element =document.createElement ( 'div');._.);
return element;
})
}
document.addEventListener( 'click',O)=>{
getcomponent().then(element ->i
document.body -appendChild(element);});
})

如此就是一开始不会加载 lodash,除非点击了页面才会去加 载这个模块。 每一个 JS 文件都是一个 Chunk。可以直接按照以下配置即可(有默认值)↓

6.打包分析、preloading、prefetching

打包分析是分析打包后的文件,看看是否合理。 首先需要生成一个打包过程描述文件↓(--profile...json,也 就是把描述文件放到 stats.json 中)。然后需要开 webpack.github.io/analyse 工具网站,上传刚刚 的 json 文件。



 当然了也还有其它很多可视化分析工具,比如 webpack-chart ( 以 图 表 的 形 式 分 析 json 文 件 ) 等 等 , 一 般 使 用 webpack-bundle-analyzer 比较多。 为什么一开始 webpack 对 chunks 默认值是 async?因为 all 的话其实是让第二次加载页面无需重复加载类库性能更高 而已,而 webpack 希望第一次就很快,则异步代码我们最好 放到一个模块里面去,然后再到需要的地方引用,当触发操 作需要使用该模块才加载。 Command+shift+p 输入 code coverage 可以录制页面,查看文件的命令使用情况(百分比),就是目前加载的内容执行了 多少。

   因此现在不再是去纠结缓存而是去看看文件的利用率,将一 开始没有用到的内容以异步的方式优化掉,性能才会更好, webpack 认为只有异步的代码(提高代码利用率)才能真正 提高性能,这就是为什么默认是 async。 比如可以把首页的登录弹窗留到点击登录才加载,不过这样 子容易有登录交互体验比较差,加载慢的问题,这就需要 prefetching 和 preloading 了,也就是等待页面基本加载完成 了,带宽空闲了,再偷偷加载这里的逻辑而非点击登录才下 载(其实还是要再下载,只不过下载过一次,有缓存了,非 常快)。 使用如下魔法注释即可实现;

7.CSS文件的代码分割

 入口文件名会看 filename,而间接生成的文件名(就是在入 口文件中引入的文件)会看 ChunkFilename。 在默认情况下,我们打包并不会单独生成 CSS 文件,因为都 写在 js 中。 MiniCssExtractPlugin 插件(不支持 HMR,一般在线上使用) 可以对 CSS 进行代码分割然后单独生成 CSS 文件。 安装该插件,在配置文件引入插件,而且还需要更改之前处 理 CSS 的 loader(线上环境配置时)。

 如此依然没有单独的 CSS,因为之前的 tree shaking 把 CSS 给 摇掉了,记得 sideEffect 整一下。 如果 CSS 文件直接被 html 引用就走 filename,如果被间接引
用才走 chunkFilename。 如果需要对 CSS 代码做压缩,还需要安装引入对应插件。

8.webpack与浏览器缓存

Performance:false 可以关闭有关性能问题的警告。 目前如果已经访问过有缓存的 JS 文件有所变动,普通刷新的 情况下还是读取原本缓存下的 JS 文件,因为文件名字没有变, 这就可以引入一个 contenthash 来解决缓存问题。

  老版本的webpack可能出现即使没有改变文件也会出现hash 不一样的情况,因为 webpack 对业务逻辑与类库做了关联处 理,叫 manifest,既存在于业务逻辑也存在于类库,而可能 打包后它变得不一样,这里就用 runtime 抽离这些 manifest, 不影响我们的内容。

9.shimming的作用

  实际上我们打包的内容还需要做不少兼容问题(变片),比 如 babel-profill 处理低版本浏览器的语法不存在问题。 Webpack 中引入的变量只能在当前模块使用,但是如果我想 在其它模块使用呢(就是当前模块没有引入),可以利用插 件。如下即代表如果我在一个模块使用了$就会自动引入 jquery 模块且命名为$(表面看起来就我当前模块没有引入变 量却可以使用变量,实际上已经偷偷的引入了)。

new webpack.ProvidePlugin({
$jquery'
}),

我们可以在这里定义非常多的在各地使用的变量;一个模块的 this 默认就是指向自身,如果一定要指向 window?可以安装 imports-loader(修改 webpack 默认行为, 也就是变片的一种)。

10.环境变量的使用方法 

module.exports = (env) →>{
if(env && env.production){
return merge( commonConfig,prodConfig);}else i
return merge( commonConfig,devConfig);}

 env 就是环境变量,在 scripts 命令中传递它对应的属性也就 代表开启什么模式,名字可以改。不过一般不会用这个,还是跟之前一样指定每个命令对应的 config 文件。

相关文章:

  • 【Linux】云服务器的购买与Linux远程连接
  • c++介绍与入门基础(详细总结)
  • 羊了个羊,日赚500万
  • Vue3+Element-Plus 前端项目配置
  • Qt5开发从入门到精通——第七篇二节( 图形视图——QSlider类)
  • java php nodejs python旅游网站设计与开发需求分析Springboot SpringcloudVue汇总一览
  • 第1章 算法和数据结构
  • Python3中.whl文件介绍
  • 垃圾回收机制
  • Autosar MCAL-ADC详解(一)-基于Tc27x的cfg软件
  • 2022百度之星程序设计大赛 - 复赛 1003 最大值
  • 2022数学建模国赛 A 题 波浪能最大输出功率设计
  • 在ubuntu64下实现 小型 C 运行时库
  • 助力防疫,基于安防摄像头的人脸佩戴口罩检测
  • C++可视化和图表库
  • 30秒的PHP代码片段(1)数组 - Array
  • extract-text-webpack-plugin用法
  • flutter的key在widget list的作用以及必要性
  • gops —— Go 程序诊断分析工具
  • IP路由与转发
  • JavaScript-Array类型
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • magento2项目上线注意事项
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • Swoft 源码剖析 - 代码自动更新机制
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • v-if和v-for连用出现的问题
  • Vue.js 移动端适配之 vw 解决方案
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 对JS继承的一点思考
  • 高程读书笔记 第六章 面向对象程序设计
  • 工程优化暨babel升级小记
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 今年的LC3大会没了?
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 如何利用MongoDB打造TOP榜小程序
  • 少走弯路,给Java 1~5 年程序员的建议
  • 数组大概知多少
  • 物联网链路协议
  • 怎样选择前端框架
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • #Java第九次作业--输入输出流和文件操作
  • #Linux(帮助手册)
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • (3)nginx 配置(nginx.conf)
  • (六)软件测试分工
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (十五)使用Nexus创建Maven私服
  • (转载)虚函数剖析
  • *(长期更新)软考网络工程师学习笔记——Section 22 无线局域网
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】