webpack是开发工具,面试考点重点在配置和使用,原理理解不需要太深。
webpack 本质上是一个函数,它接受一个配置信息作为参数,执行后返回一个 compiler 对象,调用 compiler 对象中的 run 方法就会启动编译。run 方法接受一个回调,可以用来查看编译过程中的错误信息或编译信息。
Loader 本质上就是接收资源文件,并对其进行转换,最终输出转换后的文件。
Plugin 本质上就是一种事件流的机制,到了固定的时间节点就广播特定的事件,用户可以在事件内执行特定的逻辑,类似于生命周期。
一、基本配置
1、拆分配置和merge
将公共配置跟dev和prod的配置拆分,然后通过webpack-merge对配置进行整合。
2、启动本地服务
dev环境启动devserver配置。
3、处理ES6
使用babel-loader,针对对应目录的js进行代码转换。
4、处理样式
使用postcss-loader、css-loader、style-loader等,这里有个考点是loader的执行顺序是从后往前执行。
5、处理图片
在dev环境直接使用file-loader进行图片的直接引用,prod环境会使用url-loader对小图片进行base64编码。
6、模块化
webpack天生支持模块化。
二、高级配置
1、配置多入口
entry设置多入口文件,在output输出文件使用[name]根据entry的key动态生成输出文件名
plugins要设置多个HtmlWebpackPlugin,根据多入口生成多个html文件,同时要设置chunks,来引入相应入口文件,如果不设置则会把全部入口文件都引入 。
2、每次打包清除dist原有文件
在plugins使用new CleanWebpackPlugin(),会默认清空 output.path 指定的文件夹内容。
3、抽离css文件
mini-css-extract-plugin使用这个插件的loder来替换style-loader。
在plugins里面配置mini-css-extract-plugin的filename,用于设置存放抽离的css具体目录和名字。
使用webpack的optimization的minimizer加入 terser-webpack-plugin 和 optimize-css-assets-webpack 插件来压缩抽离的css。
4、抽离公共代码
使用webpack的optimization的splitChunks
optimization:{
splitChunks:{
chunks: 'all',
// 缓存分组
cacheGroups:{
//第三方模块
vendor:{
name:'vendor', // chunk 名称
priority:1, // 权限最高,优先抽离,重要!!
test:/node_modules/, // 匹配目录规则
minSize:0, // 大小限制
minChunks:1, // 最少复用过几次
}
//公共模块
common:{
name:'common', // chunk 名称
priority:0, // 优先级
minSize:0, // 公共模块的大小限制
minChunks:2, // 公共模块最少复用过几次
}
}
}
}
5、异步加载js
import语法webpack天生支持异步加载。
异步加载会产生单独的chunk。
6、处理JSX
安装配置 @babel/preset-react 即可。
7、处理VUE文件
安装配置 vue-loader 即可
三、优化构建速度
1、优化 babel-loader(可用于生产)
{
test: /\.js$/,
use: ['babel-loader?cacheDirectory'], // 开启缓存
include: path.resolve(__dirname, 'src'), // 明确范围
// 排除范围,include 和 exclude 两者选一个即可
// exclude: path.resolve(__dirname, 'node_modules')
}
开启缓存后,es6没有改的会使用缓存不会重新编译
设置使用范围可以缩小编译量
2、IgnorePlugin(可用于生产)
忽略正则匹配的 js
3、noParse(可用于生产)
不去解析正则匹配的库的依赖
4、happyPack(可用于生产)
JS单线程,使用happyPack开启多进程打包,提高构建速度,特别是多核CPU。
5、ParallelUglifyPlugin(只用在生产)
webpack内置Uglify工具压缩JS,开启多进程压缩JS,原理和happyPack相同。
new ParallelUglifyPlugin({
// 传递给UglifyJS的参数,值不过开启了多进程压缩
uglifyJS:{
output:{
beautify:false, // 最紧凑的输出
comments:false, // 删除所有注释
},
compress:{
// 删除所有的 console 语句,可以兼容ie
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true,
}
}
})
关于开启多进程要按需使用,
项目大,打包速度慢,开启多进程提高速度
项目小,打包速度快,开启多进程反而降低速度
6、自动刷新(不可用于生产)
{
watch:true, // 开启监听,默认 false
// 注意,开启监听之后,webpack-dev-server 会自动开启刷新浏览器
// 监听配置
watchOptions:{
ignored: /node_modules/, // 忽略内容
// 监听到变化发生后等300ms再去执行动作,防止文件更新太快导致重新编译频率太高
aggregateTimeout:300, // 默认为300ms
// 判断文件是否发生变化时通过不停的去询问系统指定文件有没变化实现的
poll:1000, // 默认每隔1000ms询问一次
}
}
以上配置一般开发不会配置到,因为开启webpack-dev-server会自动带上自动刷新的配置。以上配置是为了理解自动刷新有哪些内容。
7、热更新(不可用于生产)
自动刷新:整个网页全部刷新,速度较慢,状态会丢失
热更新:新代码生效,网页不刷新,状态不丢失
热更新使用插件:HotModuleReplacementPlugin
在entry入口中要新增两行配置:
entry:{
index:[
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
path.join(srcPath,'index.js')
]
}
然后在plugin中使用HotModuleReplacementPlugin插件。
最后在devServer中增加一个属性:hot:true,开启热更新。
配置热更新后,需要增加需要热更新模块的逻辑代码,如下
if(module.hot){
moudule.hot.accept(['./math'],()=>{
// 热更新模块里面的回调函数
})
}
8、DllPlugin 动态链接库(不可用于生产)
使用前提:
前端框架如vue、react体积大,构建慢,比较稳定,不常升级。
同一个版本只构建一次即可,不用每次都重新构建。
webpack已内置DllPlugin支持。
使用过程:
DllPlugin先打包出dll文件
DllReferencePlugin再使用dll文件
四、优化产出代码
优化方向:体积更小,合理分包,不重复加载,速度更快,内存使用更少
1、小图片Base64编码
2、bundle加hash
3、懒加载
4、提取公共代码
5、IngorePlugin
6、使用CDN加速:
在output设置publicPath,会修改所有js跟css文件添加cdn前缀
在url-loader设置publicPath,可以修改图片的cdn前缀
7、使用production
开启production模式跟development相比的差异点:
(1)自动开启代码压缩
(2)Vue React等会自动删掉调试代码(如开发环境的warning)
(3)自动启动Tree-Shaking,必须用ES6 Module 才能让tree-shaking生效,commonjs就不行
ES6 Module 静态引入,编译时引入
Commonjs动态引入,执行时引入
只有静态引入才能进行静态分析,实现Tree-Shaking
8、Scope Hosting
开启之后,会将多个引用文件合并成一个函数,减少函数作用域,代码体积更小,代码可读性更好
如何配置:
引用ModuleConcatenationPlugin插件,使用插件即可开启。
针对npm中第三方模块优先采用 jsnext:main 中指向的 ES6 模块化语法的文件
resolve:{
mainFields: ['jsnext:main','brower','main']
}
五、babel
基本配置:.babelrc文件
plugins是写如何翻译语法的插件,presets是集合多个插件整合的一个包。
{
"presets":[
["@babel/preset-env"]
],
"plugins":[]
}
babel-polyfill:兼容低版本浏览器,重写低版本没有的新语法。
core-js和regenerator两个库可以满足最大多数新语法的polyfill,babel-polyfill就是前两个库的集合。
babel 7.4之后已经弃用了babel-polyfill,而推荐直接使用core-js和regenerator。
直接使用的弊端是由于重写全局方法会污染全局环境。
babel-runtime:
使用runtime配置,可以使polyfill重写的方法不污染全局环境,相当于重命名方法,代码也是自动替换成新名称的方法。
面试真题:
1、前端代码为什么要进行构建和打包?
代码层面:
(1)体积更小(Tree-Shaking、压缩、合并),加载更快
(2)编辑高级语言或语法(TS、ES6+、模块化,scss)
(3)兼容性和错误检查(Polyfill、postcss、eslint)
研发流程:
(1)统一、高效的开发环境
(2)统一的构建流程和产出标准
(3)集成公司构建规范(提测、上线等)
2、module chunk bundle 分别什么意思,有何区别?
module - 各个源码文件,webpack 中一切皆模块
chunk - 多模块合并成的,如 entry import() splitChunk
bundle - 最终的输出文件
3、loader和plugin的区别?
loader模块转换器,如 less 转 css。说出一些常用的loader
plugin扩展插件,如 HtmlWebpackPlugin。说出一些常用的plugin
4、babel和webpack的区别?
babel是JS新语法编译工具,不关系模块化
webpack是打包构建工具,是多个 loader plugin 的集合
5、如何产出一个 lib
output:{
// lib的文件名
filename: 'lodash.js',
// 输出 lib 到dist 目录下
path: distPath,
// lib 的全局变量名
library: 'lodash'
}
6、webpack如何实现懒加载?
import()语法实现
结合 Vue React 异步组件,结合 Vue-router React-router 异步加载路由来简要说下。
7、webpack常见性能优化?
将上面的三、四的优化内容根据实际效果讲下
8、babel-runtime和babel-polyfill的区别?
babel-polyfill会污染全局
babel-runtime不会污染全局
产出第三方 lib 要用 babel-runtime
9、为何Proxy 不能被 polyfill?
Class 可以用 function 模拟, Promise 可以用 callback 来模拟
但是Proxy的功能用Object.defineProperty 无法模拟
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
我正在尝试按Rails相关模型中的字段进行排序。我研究的所有解决方案都没有解决如果相关模型被另一个参数过滤?元素模型classItem相关模型:classPriority我正在使用where子句检索项目:@items=Item.where('company_id=?andapproved=?',@company.id,true).all我需要按相关表格中的“位置”列进行排序。问题在于,在优先级模型中,一个项目可能会被多家公司列出。因此,这些职位取决于他们拥有的company_id。当我显示项目时,它是针对一个公司的,按公司内的职位排序。完成此任务的正确方法是什么?感谢您的帮助。PS-我
假设您有一个可执行文件foo.rb,其库bar.rb的布局如下:/bin/foo.rb/lib/bar.rb在foo.rb的header中放置以下要求以在bar.rb中引入功能:requireFile.dirname(__FILE__)+"../lib/bar.rb"只要对foo.rb的所有调用都是直接的,这就可以正常工作。如果你把$HOME/project和符号链接(symboliclink)foo.rb放入$HOME/usr/bin,然后__FILE__解析为$HOME/usr/bin/foo.rb,因此无法找到bar.rb关于foo.rb的目录名.我意识到像rubygems这
术语中文解释Ability原子化服务帮助用户完成任务的原子化服务,和用户的意图进行关联。Fulfillment服务履行通过图标,卡片,语音等形式呈现用户意图。开发者通过接口的方式,处理用户意图,返回内容。Intent意图用于表达用户想要达成的目标或完成的任务。HUAWEIAssistant智能助手“无微不智”的个人助手,通过不断的学习用户的使用习惯,不断的为用户提供贴心的精准的便捷的个性化服务。AISearch全局搜索用户可快速搜索关键词,与之匹配的原子化服务则会出现在搜索结果中。SmartService智慧服务用户订阅原子化服务,在到达特定触发条件(时间、地点、事件)后,卡片推送至用户智能助
目录H2数据库入门以及实际开发时的使用1.H2数据库的初识1.1H2数据库介绍1.2为什么要使用嵌入式数据库?1.3嵌入式数据库对比1.3.1性能对比1.4技术选型思考2.H2数据库实战2.1H2数据库下载搭建以及部署2.1.1H2数据库的下载2.1.2数据库启动2.1.2.1windows系统可以在bin目录下执行h2.bat2.1.2.2同理可以通过cmd直接使用命令进行启动:2.1.2.3启动后控制台页面:2.1.3spring整合H2数据库2.1.3.1引入依赖文件2.1.4数据库通过file模式实际保存数据的位置2.2H2数据库操作2.2.1Mysql兼容模式2.2.2Mysql模式
这个错误已经有好几个月了,在这里:http://www.ruby-forum.com/topic/1094002其中显示代码更改的两个链接:https://github.com/godfat/ruby/commit/f4e0e8f781b05c767ad2472a43a4ed0727a75708https://github.com/godfat/ruby/commit/c7a6cf975d88828c2ed27d253f41c480f9b66ad6我有Ruby1.9.2和rvm。我会把这些更改粘贴到适当的文件中,但我不知道如何粘贴。这在几天前就奏效了。我不能像这样执行RubyonRai
?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是: 如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。 如果m不为0,则将时读出来,然后将分读出来,如5
我对相关搜索有疑问。以下请求的结果很奇怪:Candidate.search('martin',fields:[:first_name,:last_name],match::word_start,misspellings:false).map(&:name)["KautzerMartina","FunkMartin","JaskolskiMartin","GutmannMartine","WiegandMartina","SchuellerMartin","DooleyMartin","StiedemannMartine","BartellMartina","GerlachMartine
我是Rails的新手。当我启动我的应用程序时,我不断看到这些弃用警告:DEPRECATIONWARNING:refisdeprecatedandwillberemovedfromRails3.2.(calledfromatD:/dev/AquaticKodiak/config/application.rb:12)DEPRECATIONWARNING:newisdeprecatedandwillberemovedfromRails3.2.(calledfromatD:/dev/AquaticKodiak/config/application.rb:12)好的,第12行是什么?这个:Bun