1.webpack和vite区别
1.底层的语言
webpack
是基于nodejs
构建,js
是以毫秒计数。vite
是基于esbulid
预构建依赖,esbulid
是采用go
语言编写的,go
语言是纳秒级别的。
因为js
是毫秒级别,go
语言是纳秒级别。所以vite
比webpack
打包器快10-100倍。
2.打包过程
webpack:分析各个模块之间的依赖=>然后进行编译打=>打包后的代码在本地服务器渲染。随着模块增多,打包的体积变大,造成热更新速度变慢。
vite:启动服务器=>请求模块时按需动态编译显示。(vite遵循的是ES Modlues模块规范来执行代码,不需要打包编译成es5模块即可在浏览器运行。)
vite启动的时候不需要分析各个模块之间的依赖关系、不需要打包编译。vite可按需动态编译缩减时间。当项目越复杂、模块越多的情况下,vite明显优于webpack
3.热更新
webpack:模块以及模块依赖的模块需重新编译
vite:浏览器重新请求该模块即可
4.使用方面
vite开箱即用,更加简单,基于浏览器esm,使得hmr更加优秀,达到极速的效果;
webpack更加灵活,api以及插件生态更加丰富。
5.原理不同
webpack是bundle,自己实现了一套模块导入导出机制。
vite是利用浏览器的esm能力,是bundless。
2.如何优化webpack打包速度?
打包速度优化:
1、使用高版本的webpack和Node.js
2、多进程打包:happyPack或thread-loader
3、多进程并行压缩:parallel-uglify-plugin、uglifyjs-webpack-plugin 开启 parallel 参数、terser-webpack-plugin 开启 parallel 参数
4、预编译资源模块:DLLPlugin
5、缓存(babel-loader、terser-webpack-plugin、cache-loader)
6、exclude、include缩小构建目标,noParse忽略、IgnorePlugin
7、resolve配置减少文件搜索范围(alias、modules、extensions、mainFields)
打包体积优化:
1、Tree-shaking擦除无用代码
2、Scope Hoisting优化代码
3、图片压缩(image-webpack-loader)
4、公共资源提取(CommonsChunkPlugin)
5、动态Polyfill
6、分包设置Externals,使用 html-webpack-externals- plugin,将 react、react-dom 基础包通过 cdn 引入,不打入 bundle 中
7、删除无用CSS代码(purgecss-webpack-plugin)
8、JS、CSS压缩(UglifyJsPlugin(3)、terser-webpack-plugin(4)、optimize-css-assets-webpack-plugin)
3.说说webpack中常见的Plugin?解决了什么问题
HtmlWebpackPlugin:将打包后的JS、CSS等文件自动注入到HTML文件中,方便开发者使用。
MiniCssExtractPlugin:将CSS文件从JS文件中分离出来,避免JS文件过大,提高页面加载速度。
CleanWebpackPlugin:每次打包前清空输出目录,避免旧文件对新文件的影响。
DefinePlugin:定义全局变量,方便在代码中使用。
HotModuleReplacementPlugin:热更新插件,可以在不刷新页面的情况下更新代码,提高开发效率。
UglifyJsPlugin:压缩JS代码,减小文件体积,提高页面加载速度。
CopyWebpackPlugin:将静态资源文件复制到输出目录中,方便开发者使用。
4.说说如何借助webpack来优化前端性能?
如何优化
通过webpack
优化前端的手段有:
- JS代码压缩
- CSS代码压缩
- Html文件代码压缩
- 文件大小压缩
- 图片压缩
- Tree Shaking
- 代码分离
- 内联 chunk
JS代码压缩
terser
是一个JavaScript
的解释、绞肉机、压缩机的工具集,可以帮助我们压缩、丑化我们的代码,让bundle
更小
在production
模式下,webpack
默认就是使用 TerserPlugin
来处理我们的代码的。如果想要自定义配置它,配置方法如下:
1const TerserPlugin = require('terser-webpack-plugin')
2module.exports = {
3 ...
4 optimization: {
5 minimize: true,
6 minimizer: [
7 new TerserPlugin({
8 parallel: true // 电脑cpu核数-1
9 })
10 ]
11 }
12}
属性介绍如下:
- extractComments:默认值为true,表示会将注释抽取到一个单独的文件中,开发阶段,我们可设置为 false ,不保留注释
- parallel:使用多进程并发运行提高构建的速度,默认值是true,并发运行的默认数量: os.cpus().length - 1
- terserOptions:设置我们的terser相关的配置:
- compress:设置压缩相关的选项,mangle:设置丑化相关的选项,可以直接设置为true
- mangle:设置丑化相关的选项,可以直接设置为true
- toplevel:底层变量是否进行转换
- keep_classnames:保留类的名称
- keep_fnames:保留函数的名称
CSS代码压缩
CSS
压缩通常是去除无用的空格等,因为很难去修改选择器、属性的名称、值等
CSS的压缩我们可以使用另外一个插件:css-minimizer-webpack-plugin
1npm install css-minimizer-webpack-plugin -D
配置方法如下:
1const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
2module.exports = {
3 // ...
4 optimization: {
5 minimize: true,
6 minimizer: [
7 new CssMinimizerPlugin({
8 parallel: true
9 })
10 ]
11 }
12}
Html文件代码压缩
使用HtmlWebpackPlugin
插件来生成HTML
的模板时候,通过配置属性minify
进行html
优化
1module.exports = {
2 ...
3 plugin:[
4 new HtmlwebpackPlugin({
5 ...
6 minify:{
7 minifyCSS:false, // 是否压缩css
8 collapseWhitespace:false, // 是否折叠空格
9 removeComments:true // 是否移除注释
10 }
11 })
12 ]
13}
设置了minify
,实际会使用另一个插件html-minifier-terser
文件大小压缩
对文件的大小进行压缩,减少http
传输过程中宽带的损耗
1npm install compression-webpack-plugin -D
1new ComepressionPlugin({
2 test:/\.(css|js)$/, // 哪些文件需要压缩
3 threshold:500, // 设置文件多大开始压缩
4 minRatio:0.7, // 至少压缩的比例
5 algorithm:"gzip", // 采用的压缩算法
6})
图片压缩
一般来说在打包之后,一些图片文件的大小是远远要比 js
或者 css
文件要来的大,所以图片压缩较为重要
配置方法如下:
1module: {
2 rules: [
3 {
4 test: /\.(png|jpg|gif)$/,
5 use: [
6 {
7 loader: 'file-loader',
8 options: {
9 name: '[name]_[hash].[ext]',
10 outputPath: 'images/',
11 }
12 },
13 {
14 loader: 'image-webpack-loader',
15 options: {
16 // 压缩 jpeg 的配置
17 mozjpeg: {
18 progressive: true,
19 quality: 65
20 },
21 // 使用 imagemin**-optipng 压缩 png,enable: false 为关闭
22 optipng: {
23 enabled: false,
24 },
25 // 使用 imagemin-pngquant 压缩 png
26 pngquant: {
27 quality: '65-90',
28 speed: 4
29 },
30 // 压缩 gif 的配置
31 gifsicle: {
32 interlaced: false,
33 },
34 // 开启 webp,会把 jpg 和 png 图片压缩为 webp 格式
35 webp: {
36 quality: 75
37 }
38 }
39 }
40 ]
41 },
42 ]
43}
Tree Shaking
Tree Shaking
是一个术语,在计算机中表示消除死代码,依赖于ES Module
的静态语法分析(不执行任何的代码,可以明确知道模块的依赖关系)
在webpack
实现Trss shaking
有两种不同的方案:
- usedExports:通过标记某些函数是否被使用,之后通过Terser来进行优化的
- sideEffects:跳过整个模块/文件,直接查看该文件是否有副作用
两种不同的配置方案, 有不同的效果
usedExports
配置方法也很简单,只需要将usedExports
设为true
1module.exports = {
2 ...
3 optimization:{
4 usedExports
5 }
6}
使用之后,没被用上的代码在webpack
打包中会加入unused harmony export mul
注释,用来告知 Terser
在优化时,可以删除掉这段代码
如下面sum
函数没被用到,webpack
打包会添加注释,terser
在优化时,则将该函数去掉
预览
sideEffects
sideEffects
用于告知webpack compiler
哪些模块时有副作用,配置方法是在package.json
中设置sideEffects
属性
如果sideEffects
设置为false,就是告知webpack
可以安全的删除未用到的exports
如果有些文件需要保留,可以设置为数组的形式
1"sideEffecis":[ "./src/util/format.js", "*.css" // 所有的css文件]
上述都是关于javascript
的tree shaking
,css
同样也能够实现tree shaking
css tree shaking
css
进行tree shaking
优化可以安装PurgeCss
插件
1npm install purgecss-plugin-webpack -D
1const PurgeCssPlugin = require('purgecss-webpack-plugin')module.exports = { ... plugins:[ new PurgeCssPlugin({ path:glob.sync(`${path.resolve('./src')}/**/*`), {nodir:true}// src里面的所有文件 satelist:function(){ return { standard:["html"] } } }) ]}
- paths:表示要检测哪些目录下的内容需要被分析,配合使用glob
- 默认情况下,Purgecss会将我们的html标签的样式移除掉,如果我们希望保留,可以添加一个safelist的属性
代码分离
将代码分离到不同的bundle
中,之后我们可以按需加载,或者并行加载这些文件
默认情况下,所有的JavaScript
代码(业务代码、第三方依赖、暂时没有用到的模块)在首页全部都加载,就会影响首页的加载速度
代码分离可以分出出更小的bundle
,以及控制资源加载优先级,提供代码的加载性能
这里通过splitChunksPlugin
来实现,该插件webpack
已经默认安装和集成,只需要配置即可
默认配置中,chunks仅仅针对于异步(async)请求,我们可以设置为initial或者all
1module.exports = { ... optimization:{ splitChunks:{ chunks:"all" } }}
splitChunks
主要属性有如下:
- Chunks,对同步代码还是异步代码进行处理
- minSize: 拆分包的大小, 至少为minSize,如何包的大小不超过minSize,这个包不会拆分
- maxSize: 将大于maxSize的包,拆分为不小于minSize的包
- minChunks:被引入的次数,默认是1
内联chunk
可以通过InlineChunkHtmlPlugin
插件将一些chunk
的模块内联到html
,如runtime
的代码(对模块进行解析、加载、模块信息相关的代码),代码量并不大,但是必须加载的
1const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin')const HtmlWebpackPlugin = require('html-webpack-plugin')mod
5.说说webpack的热更新是如何做到的?原理是什么
- 通过
webpack-dev-server
创建两个服务器:提供静态资源的服务(express)和Socket服务 - express server 负责直接提供静态资源的服务(打包后的资源直接被浏览器请求和解析)
- socket server 是一个 websocket 的长连接,双方可以通信
- 当 socket server 监听到对应的模块发生变化时,会生成两个文件.json(manifest文件)和.js文件(update chunk)
- 通过长连接,socket server 可以直接将这两个文件主动发送给客户端(浏览器)
- 浏览器拿到两个新的文件后,通过HMR runtime机制,加载这两个文件,并且针对修改的模块进行更新
6.说说webpack proxy工作原理?为什么能解决跨域?
一、是什么
webpack proxy
,即webpack
提供的代理服务
基本行为就是接收客户端发送的请求后转发给其他服务器
其目的是为了便于开发者在开发模式下解决跨域问题(浏览器安全策略限制)
想要实现代理首先需要一个中间服务器,webpack
中提供服务器的工具为webpack-dev-server
webpack-dev-server
webpack-dev-server
是 webpack
官方推出的一款开发工具,将自动编译和自动刷新浏览器等一系列对开发友好的功能全部集成在了一起
目的是为了提高开发者日常的开发效率,只适用在开发阶段
关于配置方面,在webpack
配置对象属性中通过devServer
属性提供,如下:
1// ./webpack.config.js
2const path = require('path')
3
4module.exports = {
5 // ...
6 devServer: {
7 contentBase: path.join(__dirname, 'dist'),
8 compress: true,
9 port: 9000,
10 proxy: {
11 '/api': {
12 target: 'https://api.github.com'
13 }
14 }
15 // ...
16 }
17}
devServetr
里面proxy
则是关于代理的配置,该属性为对象的形式,对象中每一个属性就是一个代理的规则匹配
属性的名称是需要被代理的请求路径前缀,一般为了辨别都会设置前缀为 /api
,值为对应的代理匹配规则,对应如下:
- target:表示的是代理到的目标地址
- pathRewrite:默认情况下,我们的 /api-hy 也会被写入到URL中,如果希望删除,可以使用pathRewrite
- secure:默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false
- changeOrigin:它表示是否更新代理后请求的 headers 中host地址
二、工作原理
proxy
工作原理实质上是利用http-proxy-middleware
这个http
代理中间件,实现请求转发给其他服务器
举个例子:
在开发阶段,本地地址为http://localhost:3000
,该浏览器发送一个前缀带有/api
标识的请求到服务端获取数据,但响应这个请求的服务器只是将请求转发到另一台服务器中
1const express = require('express');
2const proxy = require('http-proxy-middleware');
3
4const app = express();
5
6app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));
7app.listen(3000);
8
9// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
三、跨域
在开发阶段, webpack-dev-server
会启动一个本地开发服务器,所以我们的应用在开发阶段是独立运行在 localhost
的一个端口上,而后端服务又是运行在另外一个地址上
所以在开发阶段中,由于浏览器同源策略的原因,当本地访问后端就会出现跨域请求的问题
通过设置webpack proxy
实现代理请求后,相当于浏览器与服务端中添加一个代理者
当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地
预览
在代理服务器传递数据给本地浏览器的过程中,两者同源,并不存在跨域行为,这时候浏览器就能正常接收数据
注意:服务器与服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制
7.说说webpack中常见的Loader?解决了什么问题?
loader
用于对模块的"源代码"进行转换,在 import
或"加载"模块时预处理文件
webpack
做的事情,仅仅是分析出各种模块的依赖关系,然后形成资源列表,最终打包生成到指定的文件中。如下图所示:
预览
在webpack
内部中,任何文件都是模块,不仅仅只是js
文件
默认情况下,在遇到import
或者load
加载模块的时候,webpack
只支持对js
文件打包
像css
、sass
、png
等这些类型的文件的时候,webpack
则无能为力,这时候就需要配置对应的loader
进行文件内容的解析
在加载模块的时候,执行顺序如下:
预览
当 webpack
碰到不识别的模块的时候,webpack
会在配置的中查找该文件解析规则
关于配置loader
的方式有三种:
- 配置方式(推荐):在 webpack.config.js文件中指定 loader
- 内联方式:在每个 import 语句中显式指定 loader
- CLI 方式:在 shell 命令中指定它们
配置方式
关于loader
的配置,我们是写在module.rules
属性中,属性介绍如下:
-
rules
是一个数组的形式,因此我们可以配置很多个loader
- 每一个
loader
对应一个对象的形式,对象属性test
为匹配的规则,一般情况为正则表达式 - 属性
use
针对匹配到文件类型,调用对应的loader
进行处理
代码编写,如下形式:
1module.exports = {
2 module: {
3 rules: [
4 {
5 test: /\.css$/,
6 use: [
7 { loader: 'style-loader' },
8 {
9 loader: 'css-loader',
10 options: {
11 modules: true
12 }
13 },
14 { loader: 'sass-loader' }
15 ]
16 }
17 ]
18 }
19};
二、特性
这里继续拿上述代码,来讲讲loader
的特性
从上述代码可以看到,在处理css
模块的时候,use
属性中配置了三个loader
分别处理css
文件
因为loader
支持链式调用,链中的每个loader
会处理之前已处理过的资源,最终变为js
代码。顺序为相反的顺序执行,即上述执行方式为sass-loader
、css-loader
、style-loader
除此之外,loader
的特性还有如下:
- loader 可以是同步的,也可以是异步的
- loader 运行在 Node.js 中,并且能够执行任何操作
- 除了常见的通过
package.json
的main
来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用loader
字段直接引用一个模块 - 插件(plugin)可以为 loader 带来更多特性
- loader 能够产生额外的任意文件
可以通过 loader 的预处理函数,为 JavaScript 生态系统提供更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如:压缩、打包、语言翻译和更多其他特性
三、常见的loader
在页面开发过程中,我们经常性加载除了js
文件以外的内容,这时候我们就需要配置响应的loader
进行加载
常见的loader
如下:
- style-loader: 将css添加到DOM的内联样式标签style里
- css-loader :允许将css文件通过require的方式引入,并返回css代码
- less-loader: 处理less
- sass-loader: 处理sass
- postcss-loader: 用postcss来处理CSS
- autoprefixer-loader: 处理CSS3属性前缀,已被弃用,建议直接使用postcss
- file-loader: 分发文件到output目录并返回相对路径
- url-loader: 和file-loader类似,但是当文件小于设定的limit时可以返回一个Data Url
- html-minify-loader: 压缩HTML
- babel-loader :用babel来转换ES6文件到ES
下面给出一些常见的loader
的使用:
css-loader
分析 css
模块之间的关系,并合成⼀个 css
1npm install --save-dev css-loader
1rules: [
2 ...,
3 {
4 test: /\.css$/,
5 use: {
6 loader: "css-loader",
7 options: {
8 // 启用/禁用 url() 处理
9 url: true,
10 // 启用/禁用 @import 处理
11 import: true,
12 // 启用/禁用 Sourcemap
13 sourceMap: false
14 }
15 }
16 }
17]
如果只通过css-loader
加载文件,这时候页面代码设置的样式并没有生效
原因在于,css-loader
只是负责将.css
文件进行一个解析,而并不会将解析后的css
插入到页面中
如果我们希望再完成插入style
的操作,那么我们还需要另外一个loader
,就是style-loader
style-loader
把 css-loader
生成的内容,用 style
标签挂载到页面的 head
中
1npm install --save-dev style-loader
1rules: [
2 ...,
3 {
4 test: /\.css$/,
5 use: ["style-loader", "css-loader"]
6 }
7]
同一个任务的 loader
可以同时挂载多个,处理顺序为:从右到左,从下往上
less-loader
开发中,我们也常常会使用less
、sass
、stylus
预处理器编写css
样式,使开发效率提高,这里需要使用less-loader
1npm install less-loader -D
1rules: [
2 ...,
3 {
4 test: /\.css$/,
5 use: ["style-loader", "css-loader","less-loader"]
6 }
7]
raw-loader
在 webpack
中通过 import
方式导入文件内容,该loader
并不是内置的,所以首先要安装
1npm install --save-dev raw-loader
然后在 webpack.config.js 中进行配置
1module.exports = { ..., module: { rules: [ { test: /\.(txt|md)$/, use: 'raw-loader' } ] }}
file-loader
把识别出的资源模块,移动到指定的输出⽬目录,并且返回这个资源在输出目录的地址(字符串)
1npm install --save-dev file-loader
1rules: [ ..., { test: /\.(png|jpe?g|gif)$/, use: { loader: "file-loader", options: { // placeholder 占位符 [name] 源资源模块的名称 // [ext] 源资源模块的后缀 name: "[name]_[hash].[ext]", //打包后的存放位置 outputPath: "./images", // 打包后文件的 url publicPath: './images', } } }]
url-loader
可以处理理 file-loader
所有的事情,但是遇到图片格式的模块,可以选择性的把图片转成 base64
格式的字符串,并打包到 js
中,对小体积的图片比较合适,大图片不合适。
1npm install --save-dev url-loader
复制1rules: [ ..., { test: /\.(png|jpe?g|gif)$/, use: { loader: "url-loader", options: { // placeholder 占位符 [name] 源资源模块的名称
8.说说你对webpack的理解?解决了什么问题?
webpack
是一个用于现代JavaScript
应用程序的静态模块打包工具
- 静态模块
这里的静态模块指的是开发阶段,可以被 webpack
直接引用的资源(可以直接被获取打包进bundle.js
的资源)
当 webpack
处理应用程序时,它会在内部构建一个依赖图,此依赖图对应映射到项目所需的每个模块(不再局限js
文件),并生成一个或多个 bundle
webpack
的能力:
编译代码能力,提高效率,解决浏览器兼容问题
模块整合能力,提高性能,可维护性,解决浏览器频繁请求文件的问题
万物皆可模块能力,项目维护性增强,支持不同种类的前端模块类型,统一的模块化方案,所有资源文件的加载都可以通过代码控制
9.webpack的构建流程是什么
- 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
- 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
- 确定入口:根据配置中的 entry 找出所有的入口文件;
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
- 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
10.webpack的Loader和Plugin的不同
不同的作用:
-
Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到
loader
。 所以Loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。 - Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
不同的用法:
-
Loader在
module.rules
中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个Object
,里面描述了对于什么类型的文件(test
),使用什么加载(loader
)和使用的参数(options
) -
Plugin在
plugins
中单独配置。 类型为数组,每一项是一个plugin
的实例,参数都通过构造函数传入。
11.谈谈你对 Webpack的认识
WebPack是一个模块打包工具,可以使用 WebPack管理模块依赖,并编译输岀模块所需的静态文件。它能够很好地管理与打包Web开发中所用到的HTML、 JavaScript 、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源, WebPack有对应的模块加载器。Web Pack模块打包器会分析模块间的依赖关系,最后生成优化且合并后的静态资源。
WebPack的两大特色如下。
(1)代码切割( code splitting)
(2) loader可以处理各种类型的静态文件,并且支持串行操作WebPack以 CommonJS规范来书写代码,但对 AMD/CMD的支持也很全面,方便对项目进行代码迁移。
WebPack具有 require.js和 browserify的功能,但也有很多自己的新特性,
(1)对 CommonJS、AMD、ES6的语法实现了兼容。
(2)对 JavaScript、CSS、图片等资源文件都支持打包
(3)串联式模块加载器和插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、 EMAScript 6的支持
(4)有独立的配置文件 webpack.config. js。
(5)可以将代码切割成不同的块,实现按需加载,缩短了初始化时间。
(6)支持 SourceUrls和 SourceMaps,易于调试。
(7)具有强大的 Plugin接口,大多是内部插件,使用起来比较灵活
(8)使用异步I/O,并具有多级缓存,这使得 WebPack速度很快且在增量编译上更加快。
12.webpack如何搭建vue
要搭建一个使用Webpack的Vue项目,可以按照以下步骤进行操作:
-
创建项目文件夹并初始化npm: 在命令行中执行以下命令来创建一个新的项目文件夹,并使用
npm init
初始化npm。mkdir my-vue-project cd my-vue-project npm init -y
-
安装依赖: 安装所需的开发依赖项和生产依赖项。Vue项目通常需要安装
vue
、vue-loader
、vue-template-compiler
等包。此外,还需要安装Webpack及其相关的插件和加载器。执行以下命令来安装这些依赖项:npm install webpack webpack-cli vue vue-loader vue-template-compiler --save-dev
-
创建Webpack配置文件: 在项目根目录下,创建一个名为
webpack.config.js
的文件,并添加以下基本的Webpack配置:const path = require('path'); module.exports = { entry: './src/main.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', }, }, ], }, resolve: { extensions: ['.vue', '.js'], alias: { '@': path.resolve(__dirname, 'src'), }, }, };
在这个配置中,入口文件是
src/main.js
,输出文件将被打包到dist/bundle.js
。 -
创建Vue组件: 在项目的
src
目录下创建一个main.js
文件作为入口文件,并在其中创建Vue实例。还可以创建其他的Vue组件文件(以.vue
为后缀),并在main.js
中引入和使用它们。import Vue from 'vue'; import App from './App.vue'; new Vue({ render: (h) => h(App), }).$mount('#app');
这里的
App.vue
是一个示例的Vue组件。 -
创建HTML模板文件: 在项目根目录下创建一个
index.html
文件作为Webpack打包生成的HTML文件的模板。可以在其中添加一个具有唯一ID的空``元素,用于挂载Vue应用。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My Vue Project</title> </head> <body> <div id="app"></div> </body> </html>
-
编写Vue组件和样式: 在
src
目录下编写所需的Vue组件和样式文件。 -
构建并运行项目: 在命令行中执行以下命令来构建并运行项目:
npx webpack --mode development
这将使用Webpack将项目打包,并在本地服务器上启动应用程序。你可以在浏览器中访问
http://localhost:8080
来查看运行结果。
这些步骤仅提供了基本的配置和操作,你可能还需要根据具体需求和项目复杂性进行额外的配置和调整。
13.gzip压缩
gzip是一种常用的文件压缩算法,可以通过减小文件的体积来提高传输效率。在Web开发中,使用gzip压缩可以减小静态资源(如HTML、CSS、JavaScript等)的大小,从而加快网页加载速度。
Webpack支持使用gzip来压缩输出的静态资源。以下是实现gzip压缩的步骤:
-
在Webpack配置文件中,使用
compression-webpack-plugin
插件安装并引入:const CompressionPlugin = require('compression-webpack-plugin');
-
在Webpack配置文件中,添加该插件的实例到
plugins
数组中:plugins: [ new CompressionPlugin({ algorithm: 'gzip', test: /\.(js|css|html)$/, // 压缩JavaScript、CSS和HTML文件 threshold: 10240, // 文件超过10KB才会被压缩 minRatio: 0.8 // 压缩比例达到0.8时才会被压缩 }) ]
-
执行Webpack构建命令,生成的静态资源文件将会被gzip压缩。
注意事项:
- 使用gzip压缩只对文本类型的文件起作用,例如文本文件(如HTML、CSS、JavaScript)和JSON文件。对于已经被压缩过的图片、音视频等二进制文件,gzip不会再次进行压缩。
- 客户端浏览器必须支持gzip编码,通常现代浏览器都支持。
- 在配置gzip压缩的同时,服务器还需要进行相应的设置,以便在请求中适当地告知浏览器该资源已经被压缩。
使用gzip压缩可以有效地减小传输文件大小,提高网页加载速度,但也会增加服务器的CPU负载。因此,在权衡服务器性能和文件传输效率时,需要根据具体情况做出合理的配置选择。
14.css压缩去除无用空格用什么
可以使用CSS压缩工具来去除无用空格和压缩CSS文件的大小。以下是一些常用的CSS压缩工具:
- cssnano:cssnano是一个流行且功能强大的CSS压缩工具,它能够深度压缩CSS并去除无用空格、注释和其他不必要的字符。你可以通过在构建过程中使用cssnano插件或使用命令行工具来压缩CSS文件。
- UglifyCSS:UglifyCSS是另一个常用的CSS压缩工具,它能够通过移除空格、注释和不必要的代码来有效减小CSS文件的大小。你可以通过安装UglifyCSS并在命令行中运行相应的命令来进行压缩。
- Clean-CSS:Clean-CSS是一个功能强大的CSS优化工具,它能够压缩CSS文件并去除无用空格、注释以及其他冗余代码。你可以通过使用Clean-CSS提供的CLI工具或集成到构建流程中来使用它进行CSS压缩。
这些工具都可以帮助你自动压缩CSS文件并去除无用空格,提高网页加载速度。根据你的项目需求选择适合的工具,并将其集成到构建过程中,以便在每次构建时自动进行CSS压缩
15.对文件大小压缩如何实现
压缩文件大小的方法主要有两种:有损压缩和无损压缩。下面我会对这两种方法进行简要说明:
- 有损压缩: 有损压缩是通过舍弃一定的数据精度或细节来减小文件大小的压缩方式,常用于图像、音频和视频等多媒体文件。在有损压缩中,一些不太显眼或重复的数据被删除或近似表示,从而降低文件大小。虽然这种压缩方式可以显著减小文件大小,但也会导致一定程度的质量损失。常用的有损压缩算法有JPEG(图像)、MP3(音频)和H.264(视频)等。
- 无损压缩: 无损压缩是通过保留所有数据的精确性和完整性,减小文件大小的压缩方式。这意味着在解压缩后能够还原出与原始文件完全相同的数据。无损压缩适用于文本文件、代码文件、压缩文件等。常用的无损压缩算法有ZIP、GZIP和PNG等。
以下是一些实现文件大小压缩的具体方法:
- 图片压缩:使用专业的图像处理软件(如Adobe Photoshop)或在线工具对图片进行有损压缩,调整图像的质量、分辨率、色彩空间等参数以减小文件大小。还可以使用无损压缩算法(如PNG)来压缩图像文件。
- 音频压缩:使用音频编辑软件或在线工具将音频文件转换为压缩格式(如MP3、AAC),调整比特率、采样率等参数以减小文件大小。
- 视频压缩:使用视频编辑软件或在线工具将视频文件转换为压缩格式(如MP4、AVC),调整分辨率、帧率、比特率等参数以减小文件大小。
- 文本文件压缩:对文本文件使用无损压缩算法(如ZIP、GZIP)进行压缩,可以有效减小文件大小。对于代码文件,可以使用专门的压缩工具(如UglifyJS、CSSNano)对代码进行压缩和优化。
- 压缩文件格式:选择合适的压缩文件格式,各种格式对不同类型的文件优化得更好。例如,对于图像文件,JPEG 格式适用于照片等大尺寸
16.代码分离如何实现,内联thunk
代码分离是将应用程序或网站的代码拆分为多个较小的块,以便在需要时按需加载。这样可以提高页面加载速度并减少初始加载时间。以下是一种常见的实现代码分离的方法和内联thunk的解释:
-
动态导入: 使用动态导入(Dynamic Import)可以实现代码分离。动态导入是一种在运行时异步加载模块的技术。通过将代码拆分为独立的模块,你可以使用
import()
函数或webpack等构建工具的import()
语法来延迟加载特定模块。例如:import('./module').then((module) => { // 在需要时使用模块 });
这将使得
'./module'
在运行时被异步地加载。 -
Webpack 的代码分离: 如果你使用Webpack作为构建工具,它提供了很多选项来实现代码分离。其中一个常见的方式是通过使用Webpack的
splitChunks
配置选项将代码拆分为独立的块。你可以根据实际需求设置不同的配置参数,例如按需加载异步模块、提取公共代码等。示例:module.exports = { // ... optimization: { splitChunks: { chunks: 'all', }, }, };
这将把所有公共代码和第三方库打包到单独的块中,并在需要时进行加载。
关于内联thunk的理解可能有一些误导。Thunk是一种用于实现惰性计算或延迟执行的编程技术,与代码分离并不直接相关。内联指的是将JavaScript代码直接嵌入到HTML文档中,而不是将其放在外部的JavaScript文件中。通常情况下,内联脚本的体积较小,可以减少请求数量并提高页面加载速度。然而,在实际开发中,为了可维护性和代码复用性,将大部分代码封装在外部的JavaScript文件中是更好的做法
17.Webpack Dev Server开启原理
以下是Webpack Dev Server开启的基本原理:
- 创建Dev Server实例:通过配置webpack.config.js文件,设置devServer选项来创建Webpack Dev Server的实例。
- 启动本地服务器:当我们运行启动脚本(如
npm run dev
)时,Webpack Dev Server会自动在配置中指定的端口上启动一个本地服务器。一般默认使用的端口号是8080。 - 监听文件变化:Webpack Dev Server会监视项目中的文件变化,包括源码文件、静态资源等。当有文件变动时,它会触发重新编译并发送更新给客户端。
- 内存中编译与打包:Webpack Dev Server将源码文件编译并打包到内存中,而不是写入硬盘。这样可以提高编译速度,并且避免频繁的IO操作。
- 实时页面刷新:当源码发生变化并完成重新编译后,Webpack Dev Server会通知客户端进行实时页面刷新,以展示最新的变动。
- 模块热替换:除了实时页面刷新外,Webpack Dev Server还支持模块热替换(Hot Module Replacement,HMR)。当某个模块发生变化时,它会通过WebSocket等技术,将新的模块代码替换到正在运行的网页中,而不需要进行完整的页面刷新。这样可以保持应用的状态及页面的部分内容,提升开发效率。
18.webpack中的proxy代理
在Webpack中使用proxy代理是为了解决开发环境下的跨域问题。通过配置proxy,可以将请求转发到指定的目标服务器,从而避免浏览器的同源策略限制。
要在Webpack中配置proxy代理,你需要在webpack配置文件中添加以下代码:
module.exports = {
// ...其他配置项
devServer:
}
19.treeShaking开启原理
Tree Shaking是一种用于优化打包输出的技术,主要用于去除未使用的代码,减小最终构建文件的体积。它依赖于ES6模块系统中的静态结构特性。
以下是Tree Shaking开启的基本原理:
- ES6模块系统:Tree Shaking的核心是基于ES6模块系统中的静态结构特性。在ES6模块系统中,模块的导入和导出关系在编译阶段就能够确定,而不是在运行时动态决定。
- 代码的标记:Webpack根据import和export语句对代码进行标记。在代码被标记为导出时,Webpack会将其视为潜在的被使用代码。
- 依赖关系分析:Webpack会对整个项目进行静态分析,追踪模块之间的依赖关系。通过这种方式,Webpack能够确定哪些导出的代码最终没有被使用到。
- 无副作用代码:如果某个模块的导出没有被其他模块引用,并且该模块也没有副作用(例如改变全局状态、执行网络请求等),那么Webpack会将其标记为无副作用的代码。
- 无副作用代码的消除:在构建过程中,Webpack会将标记为无副作用的未使用代码从最终输出中删除,以实现代码体积的优化。
值得注意的是,Tree Shaking的开启还需要满足一些条件:
- 使用ES6模块语法进行导入和导出。
- 在Webpack配置中开启production模式(例如设置
mode: 'production'
)或者启用相关的优化插件(如UglifyJsPlugin)。 - 保证代码没有副作用,即不会对全局状态进行修改或执行网络请求等操作。
通过以上原理和条件,开启Tree Shaking能够帮助我们消除未使用代码,减小打包后文件的体积,提升项目的性能与加载速度。
20.常见的plugin
以下是一些常见的Webpack插件:
- HtmlWebpackPlugin:生成HTML文件,并自动将打包后的资源文件(如JS、CSS)注入到HTML中。
- MiniCssExtractPlugin:将CSS代码提取到单独的文件中,而不是使用style-loader将样式内联到HTML中。
- CleanWebpackPlugin:在每次构建前清理输出目录,防止旧的打包文件残留。
- DefinePlugin:定义全局常量,在代码中可以直接使用,例如用于区分开发环境和生产环境。
- CopyWebpackPlugin:将指定的文件或目录复制到构建目录中,常用于复制静态资源文件。
- HotModuleReplacementPlugin:启用模块热替换(Hot Module Replacement),在开发过程中实现不刷新页面更新模块。
- UglifyJsPlugin:将JavaScript代码进行压缩和混淆,减小文件体积。
- OptimizeCSSAssetsPlugin:优化和压缩CSS资源。
- ProvidePlugin:自动加载模块,在代码中不需要显式引入,例如直接使用jQuery库等。
- ExtractTextWebpackPlugin:用于将CSS等样式文件单独提取到一个文件中,适用于Webpack3及以下版本。
这些是常见的Webpack插件,通过在Webpack配置中使用它们,可以进一步增强打包过程的功能和自定义特性。根据具体项目需求,选择合适的插件来优化构建过程。
21.bable原理
Babel 是一个广泛使用的 JavaScript 编译器,用于将较新版本的 JavaScript 代码转换为向后兼容的旧版 JavaScript 代码。它的工作原理可以简述如下:
- 解析(Parsing):首先,Babel 会将输入的源码解析成抽象语法树(AST)。AST 是源代码的结构化表示,使得代码可以被理解和操作。
- 转换(Transformation):接下来,Babel 将遍历这棵 AST,对其中的节点进行修改、添加或删除,以实现特定的转换操作。例如,将较新的语法转换成旧版的语法,或者在代码中添加一些运行时的辅助函数。
- 生成(Generation):完成转换后,Babel 将根据修改后的 AST 重新生成对应的 JavaScript 代码字符串。
Babel 的转换过程主要依赖于插件(Plugins)。每个插件负责处理特定类型的转换任务。当 Babel 遍历 AST 时,它会根据插件的规则匹配 AST 的节点,并执行相应的转换操作。
Babel 还支持预设(Presets),即一组预定义的插件集合。预设可以方便开发者快速配置常见的转换需求,而无需逐个安装和配置相关插件。
总结起来,Babel 的核心原理是通过解析源码成 AST,利用插件对 AST 进行遍历、修改和生成,从而实现将较新版本的 JavaScript 代码转换为向后兼容的旧版 JavaScript 代码。这使得开发者能够在当前的 JavaScript 运行环境中使用较新的语法和特性,同时保持代码的兼容性。
22.热更新如何做到
热更新(Hot Module Replacement,HMR)是一种技术,它允许在应用程序运行时替换、添加或删除模块,而不需要刷新整个页面或重新加载整个应用程序。下面是热更新的一般实现方式:
- 监听文件变化:开发工具或框架会在后台监听项目文件的变化,包括 JavaScript 文件、样式文件等。
- 构建更新补丁:当有文件发生变化时,工具会进行增量构建,生成一个称为更新补丁(update patch)的文件,该文件记录了哪些模块发生了变化以及如何处理这些变化。
- 通知客户端更新:工具通过 WebSocket 或其他通信机制与客户端保持连接,并向客户端发送更新补丁的消息。
- 客户端实时更新:客户端收到更新补丁的消息后,会根据补丁中的信息自动进行相应的模块替换、添加或删除操作,从而实现实时更新,而不中断应用程序的运行。
需要注意的是,热更新的实现方式可能因开发工具或框架而异。例如,在前端开发中,Webpack 是常用的打包工具之一,它提供了 Hot Module Replacement 的功能。Webpack 使用独立的开发服务器来监听文件变化并生成更新补丁,然后将补丁通过 WebSocket 通知给客户端,客户端利用特定的 HMR runtime 来处理补丁,并使应用程序保持更新。文章来源:https://www.toymoban.com/news/detail-520675.html
总结起来,热更新通过监听文件变化、生成更新补丁、通知客户端和客户端实时更新的方式,实现了在应用程序运行时不中断地替换、添加或删除模块的能力。这样可以提供更好的开发体验,以及更快速的代码迭代和调试过程。文章来源地址https://www.toymoban.com/news/detail-520675.html
到了这里,关于webpack相关面试题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!