2023前端开发最新面试题收集-Webpack篇
webpack整理
谈谈webpack的理解
webpack是一个静态模块打包器。当webpack处理应用程序时,会递归构建一个依赖关系图,其中包括应用程序所需的所有模块,最后将这些模块打包成一个或多个bundle,并输出到配置的位置。
Webpack的执行顺序/加载机制
webpack就像一个生产流水线,要经过一些列的loader来处理不同的文件,将这些文件编译转换成JS结果。这些loader的处理功能都是单一的,多个流程存在依赖关系,只有当前处理完才能进行一个流程去处理。
plugin插件是一个插入到生产线中的功能,在特定的时机会对资源进行处理。webpack的处理过程中会广播事件,插件只在监听到它所关注的事件才会加入流水线进行处理。
vite 和 webpack 区别
- webpack: 开发阶段运行项目的打包,其实是在内存中完成,所以每次修改代码都会运行打包,如果依赖太多运行打包速度就会变慢
- vite:开发阶段没有打包过程,效率高很多
- 他是直接启动一个开发服务器,
- 然后请求模块到开发服务器中进行编译,
- 根据页面所需依赖去加载文件,
- 最后开发服务器把编译结果返回给页面
- vite 的优势:
- 利用新版浏览器 ES Module(异步)功能,在开发阶段快速编译
- 打包生成环境使用 传统的 rollup
- 代码中不用使用CommonJs
打包过程/构建过程
1、初始化编译参数:从webpack.config.js配置文件和shell命令中读取并合并参数
2、开始编译:从初始化编译参数构建complier对象,加载所有的配置plugin,执行complier对象的run方法,开始编译
3、确定入口:根据配置中entry,找到编译的所有入口文件,作为起点。
4、编译模块:从入口文件触发,调用所配置的loader对文件进行编译,通过递归找到文件所有的依赖,进行编译。
5、完成模块编译:完成所有模块的编译,得到每个模块编译后的最终内容以及对应依赖关系图
6、输出资源:根据依赖关系图,组装一个或多个模块的代码块chunk,再把每个代码块chunk转化成一个单独的文件加入输出列表,根据输出配置确定输出的路径和名称。
Loader
loader是webpack提供一种处理多种文件格式的机制。因为webpack只识别JS和JSON,因此需要通过loader来预处理其他格式文件
对源文件进行转换
loader支持链式调用,调用的顺序是从右到左,链式中每个loader会处理之前处理的文件,最终转化成JS文件
通过loader的预处理函数,可以为webpack提供很好的生态功能。
常见的loader有哪些
css-loader 将css合并到 JS中
less-loader 将less解析成css
style-loader 将js中的css通过style标签引入html中
source-map-loader 保留原文件的映射,便于开发调试排查问题
image-loader 图片压缩编译
postcss-loader css兼容处理,增加前缀
Plugin
plugin功能非常强大,主要用来处理loader无法处理的问题,比如打包优化,代码压缩,提取分离
plugin始终贯穿webpack流程,在监听到对应的事件,它会参入编译运行,帮助webpack处理一些特定的功能,比如清理打包文件,生成html
常见的Plugin
htmlWebpackPlugin 处理html文件,生成一个html,引入打包的所有资源css/js
cleanWebpackPlugin 每次打包时会清除上一次打包文件
minicssExtractPlugin 抽出压缩在JS中的css
webpack-bundle-analyzer 分析打包的文件
Loader和Plugin区别
loader是运行在编译过程,功能单一,解析特定的文件,而Plugin时运行整个webpackd的生命周期,处理loader无法处理的功能
webpack生命周期:entry loaders output
loader:1、下载 2、使用
plugin:1、下载 2、引用 3、使用
webpack的优化
1、开发环境
- 热更新:只更新重新构建的模块,提高打包速度
- source-map:用于调试,提供源码映射
2、生产环境
- 打包构建速度优化
- Babel缓存:第二构建时,读取之前的缓存,只重构变化的模块
- oneof 找到第一个loader就不会继续遍历,不能有两个配置处理同一个文件
- tree-shaking:对于引入但未被使用的模块进行删除,减少文件体积,提高打包效率
- 多进程打包: thread-loader, 将其放在耗时的loader前执行
- 缩小处理范围:合理使用exclude和include
- 使用DLL进行分包:处理node_modules中一些不常更新的框架和库进行打包成一个chunk
- 思路:将vue、elementui基础包通过cdn引入,而不打包入bundle中
- 使用 html-wepack-externals-plugin
plugin: [ new HtmlWebpackExternalsPlugin({ externals: [ { module: 'vue', // 库暴露出来的 entry: 'https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.cjs.js', global: 'Vue' // 全局变量 } ] }) ]
- 代码运行性能优化
- 文件资源缓存 资源缓存在浏览器中,当文件没有变化,不需要更hash,走缓存资源
- tree-shaking 删除未使用的代码
- code split 代码分割,减少代码加载时间
- 路由懒加载/预加载 vue import引入组件 webpackPrefetch:true 预加载
- pwa 离线访问
- 骨架屏 vue-skeleton-webpack-plugin,它将骨架屏看着路由组件,在构建时用Vue预渲染功能,将骨架屏组件的渲染结果HTML片段插入HTML页面模版的挂载点中,将样式内敛到head标签中。这样等前端渲染完成时,Vue将使用客户端混合,将挂载点中的骨架屏内容替换成真正的页面内容
webpack 拆分 optimization.splitchunk
1、在optimization配置项中配置该插件作为压缩器进行压缩
optimization.splitChunks({ chunks: "all", cacheGroups: { libs: { // 第三方组件 }, elementUI: { }, commons: { name: 'chunk-commons', test: resolve('src/components') } } })
2、在plugins中使用该插件进行压缩
JS:用 terser-webpack-plugin 默认开启
CSS: 用 mini-css-extrack-plugin
performance
用来是否提示文件大小的警告,可以配置文件大小,maxAssetSize \ maxEntrypointSize
vue-server-renderer SSR服务器渲染
在服务端进行渲染生成HTML文件,返回给浏览器生产页面。
- 好处
- 有利于SEO,即网络爬虫抓取你的页面
- 低级爬虫:只请求URL,URL返回的HTML是什么内容就爬什么内容
- 高级爬虫:请求URL,加载并执行JS来渲染页面,爬取的是JS渲染后的内容
- 因此对于低级爬虫来说,使用服务器渲染可以抓取,而前端渲染无能为力。低级爬虫一般都是老旧爬虫代码。
- 出现白屏的时间更短
- 因为不需要经过JS去服务器请求数据,待响应后在渲染,JS越重,渲染所需的时间越长
- 缺点:
- 增加了服务器运行负载
- 代码复杂度增加:需要兼容服务端和客户端两种运行情况
- 涉及构建设置和部署的更多要求
- 框架:vue 使用 Nuxt.js react可以用 Next.js
- nuxt.js是一个基于Vue.js的通用应用框架,通过对客户端/服务端基础架构的抽象组织。
- 基于Vue.js
- 自动代码分层
- 服务端渲染
- 强大的路由功能,支持异步数据
- 静态文件服务
- ES6/7语法支持
- 打包和压缩 JS和CSS
- HTML头部标签管理
- 本地开发支持热更新
- 集成ESlint
- 支持各种样式预处理器: sass less stylus
1、gulp 和 webpcak
- gulp是基于任务和数据流处理设计的,简单的代码压缩和合并,适合看开发多页面应用开发
- 一般通过配置一系列的task,定义task处理的事务,如文件压缩,合并雪碧图,强调前端开发流程
- webpack是基于模块打包的,适合SPA单页面应用开发
- 把开发中的所有资源,如图片、js、css等看作模块,通过loader和plugins对资源进行处理,强调的是模块化开发,同时附带压缩合并、预处理css功能