Webpack基础知识
webpack干了什么事情
第一点:打包,webpack多个js文件打包成一个文件。减少服务器压力和下载带宽。减少请求次数和压缩js css img(对原始图片进行压缩处理、调整图片的分辨率和尺寸;服务器开启Gzip压缩功能压缩页面文本)
第二点:转换,能够把less,scss等扩展性语言,以及各种类型的js文件都转换成标准的能被浏览器识别的语言
第三点:优化。Webpack3.0以后,担任着优化和提升性能的责任(比如第三方类库的分离,提取公共代码等)
webpack的安装
webpack安装的两种方式
1 . 全局安装:npm install webpack webpack-cli -g
2.局部安装: npm install webpack webpack-cli -D
webpack 版本查看 :webpack -v
全局安装就是安装到全局目录下(通过 npm config set prefix “目录路径” 来设置。通过 npm config get prefix 来获取当前设置的目录)
但是对于大多数项目我们推荐安装到本地,原因是可防止不同项目依赖不同版本的 Webpack 而导致冲突。
使用webpack进行一个简单的打包
当然webpack默认路径是index.js->bulid.js
我们需要自己配置相关打包路径
我们可以在根目录下创建一个webpack.config.js文件,来作为webpack的配置文件:
继续执行webpack命令(npm run build),依然可以正常打包
webpack.config.js
注意:绝对路径
const path = require('path');
module.exports = {
//入口
entry: "./src/main.js",
//出口
output: {
//拼接当前文件所在路径和build文件夹形成一个绝对路径
path: path.resolve(__dirname, "./build"),
//打包的文件名
filename: "bundle.js"
}
}
webpack的loader配置
什么是loader
因为webpack本身只能处理js文件,不能处理对css img这些文件的模块处理,所以要使用对应的loader来进行处理
对于css文件的处理需要css-loader和style-loader,如果是less,再加上less-loader
注意:为什么还需要style-loader?
答:因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中;
如果我们希望再完成插入style的操作,那么我们还需要另外一个loader,就是style-loader; .
对于.vue文件需要使用vue-loader
对于img文件需要使用img-loader
注意:因为loader的执行顺序是从右向左(或者说从下到上,或者说从后到前的),所以我们需要将style-loader写到css-loader的前面;
loader的具体配置
这些loader是在rules中进行配置
module.rules的配置如下:
rules属性对应的值是一个数组: [Rule]
test属性:用于对resource (资源)进行匹配的,通常会设置成正则表达式;
use属性:对应的值时一个数组: [UseEntry]
UseEntry是一 个对象, 可以通过对象的属性来设置一些其他属性
➢loader:必须有一个loader属性,对应的值是一个字符串;
➢options:可选的属性,值是一个字符串或者对象, 值会被传入到loader中;
➢query:目前已经使用options来替代;
传递字符串(如: use: [ ‘style-loader’ ]) 是loader属性的简写方式(如: use: [ { loader: ‘style-loader’}]) ;
loader属性: Rule.use: [ { loader }]的简写。
module.exports = {
entry: "./src/main.js",
output: {
path: path.resolve(__dirname, "./build"),
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.css$/, //正则表达式进行匹配
use: [
"style-loader",
"css-loader",
"postcss-loader"
//options的写法,上面的是简写
// {
// loader: "postcss-loader",
// options: {
// postcssOptions: {
// plugins: [
// require("autoprefixer")
// ]
// }
// }
// }
]
}
]
}
}
处理img图片
要处理jpg、png等格式的图片,我们也需要有对应的loader
wepack5的方式已经不需要imgLoder和urlLoder了
weback现在对于图片文件已经不需要loader了,但是要配置如下规则
{
test: /\.(jpe?g|png|gif|svg)$/,
type: "asset"
},
处理背景图片的url,现在也不用url-loader了,用资源模块会自动转成base64格式
url-loader和file-loader的工作方式是相似的,但是可以将较小的文件,转成base64的URI
默认情况下url-loader会将所有的图片文件转成base64编码
base64编码:
优点:这是因为小的图片转换base64之后可以和页面一起被请求,减少请求数。
缺点:大的图片也进行转换下载,影响页面的请求速度;
所以对于小图片可以使用base64,对于大图片,单独打包请求
webpack的plugin配置
什么是plugin
Plugin可以用于执行更加广泛的任务,比如打包优化、资源管理、环境变量注入等;主要是为webpack做扩展
CleanWebpackPlugin
前面我们演示的过程中,每次修改了一些配置,重新打包时,都需要手动删除dist文件夹:
我们可以借助于一个插件来帮助我们完成,这个插件就是CleanWebpackPlugin;
引入后直接在plugin中进行配置即可
HtmlWebpackPlugin
我们的HTML文件是编写在根目录下的,而最终打包的dist文件夹中是没有index.html文件的。
在进行项目部署的时,必然也是需要有对应的入口文件index.html;
所以我们也需要对index.html进行打包处理;
对HTML进行打包处理我们可以使用另外一个插件:HtmlWebpackPlugin;
使用方法同上,甚至可以在配置中进行自定义index.html的配置
DefinePlugin
用途一:
在使用HtmlWebpackPlugin自定义index.html的配置时,编译后还是会报错,因为我们的模板中使用到一个BASE_URL的常量,我们并没有设置过这个常量值,所以会报错,这个时候可以去使用这个插件
用途二:在我们项目中可以通过这个插件设置一些全局变量,如判断当前是开发环境还是生产环境
webpack的Mode配置
Mode的默认值是production,可以配置的字段有none,production,development
如下设置会有如下影响,设置mode后会直接启用DefinePlugin,一般是在开发环境我们设置为development,在上线我们设置为production
webpack搭建本地服务器
为什么要搭建本地服务器?
为了避免代码发生变动后多次进行build来进行查看。
我们想让它在代码变动后进行自动编译
webpack-dev-server
先install webpack-dev-server -D
npm run serve的原理
之前我们每次build 后通过open in liveserve打开页面
npm run serve在编译后不会输出任何文件,是将打包后的bundle文件代码放到内存中,而,他读取的时候会直接从内存中读取,这样速度更快
HMR(模块热替换)
当我们改变代码时,不使用HMR的话webpack会将整个页面进行刷新,使用HMR后只会对当前模块进行刷新
webpack-dev-server的对应配置:hot:true
但是你会发现,当我们修改了某一个模块的代码时,依然是刷新的整个页面,其实hot属性默认就是true,这是因为我们需要去指定哪些模块发生更新时,进行HMR;
其实Vue和React框架已经给你做好了模块的HMR,你不需要去自己去指定哪些模块进行HMR
热更新的原理与Sokect长连接有关
webpack-dev-server其他配置
port设置监听的端口,默认情况下是8080
host设置主机地址,可以修改成0.0.0.0让别人访问,而127.0.0.1访问不了
open是否打开浏览器
compress是否采用gzip压缩
historyApiFallback
historyApiFallback是开发中一个非常常见的属性,它主要的作用就是解决SPA页面在路由跳转之后,进行页面刷新时,返回404的错误
boolean:默认值为false,如果值为true,那么在刷新时返回404时,会自动返回idnex.html的内容
object类型的值,可以配置rewrites属性,可以配置from来匹配路径,决定要跳转哪一个界面;
如果刷新界面之后找不到界面了,可以在vue.config.js文件中这样配置
proxy是我们开发中非常常用的一个配置选项,它的目的设置代理来解决跨域访问的问题:
比如我们的一个api请求是 http://localhost:8888,但是本地启动服务器的域名是 http://localhost:8000,这
个时候发送网络请求就会出现跨域的问题;
那么我们可以将请求先发送到一个代理服务器,代理服务器和API服务器没有跨域的问题,就可以解决我们的跨域问题了;
target:表示的是代理到的目标地址,比如 /api-hy/moment会被代理到 http://localhost:8888/api- hy/moment;
ppathRewrite:默认情况下,我们的 /api-hy 也会被写入到URL中,如果希望删除,可以使用pathRewrite;
psecure:默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false;
pchangeOrigin:它表示是否更新代理后请求的headers中host地址;
proxy: {
"/api": {
target: "http://localhost:8888",
pathRewrite: {
"^/api": ""
},
secure: false,
changeOrigin: true
}
}
请求
axios.get("/api/moment").then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
相当于请求
http://localhost:8888/moment接口
原理
在开发阶段中,webpack-dev-server会启动一个本地开发的服务器,即跨域所使用的代理服务器,通过利用http-proxy-middleware代理中间件,代理服务器会响应本地请求,继而转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,代理服务器再将数据返回给本地。
在此阶段中不涉及任何跨域问题,因为代理服务器跟本地同源,而服务器之间不存在跨域问题,跨域问题是浏览器安全策略限制。
webpack的reslove配置
resolve: {
extensions: [".js", ".json", ".mjs", ".vue", ".ts", ".jsx", ".tsx"],
alias: {
"@": path.resolve(__dirname, "./src"),
"js": path.resolve(__dirname, "./src/js")
}
},
extensions是解析到文件时自动添加扩展名:
默认值是 [‘.wasm’, ‘.mjs’, ‘.js’, ‘.json’];
所以如果我们代码中想要添加加载 .vue 或者 jsx 或者 ts 等文件时,我们必须自己写上扩展名;
另一个非常好用的功能是配置别名alias:
特别是当我们项目的目录结构比较深的时候,或者一个文件的路径可能需要 …/…/…/这种路径片段;我们可以给某些常见的路径起一个别名
webpack区分开发和生成环境
写两个js文件分别对应不同环境
webpack.dev.config.js
webpack.prod.config.js
对不同的环境运行相应的指令
"scripts": {
"build": "webpack --config ./config/webpack.prod.config.js",
"serve": "webpack serve --config ./config/webpack.dev.config.js"
},
webpack入口文件解析
之前会有一个config文件夹存放webpack.dev.config.js和webpack.prod.config.js,其中除了entry的路径是./src/index.js,其他配置的路径都变成了…/src/xxx
Webpack对比Vite
1.编译方式不同
webpack在编译过程中,会将所有模块打包为一个bundle.js文件,然后再运行这个文件。
而vite在开发模式下,没有打包的步骤,它利用了浏览器的ES Module Imports特性,只有在真正需要时才编译文件。在生产模式下,vite使用Rollup进行打包,提供更好的tree-shaking,代码压缩和性能优化。
2.开发效率不同
webpack的热更新是全量更新,即使修改一个小文件,也会重新编译整个应用,这在大型应用中可能会导致编译速度变慢。
vite的热更新是增量更新,只更新修改的文件,所以即使在大型应用中也能保持极快的编译速度。
3.扩展性不同
webpack有着成熟的插件生态,几乎可以实现任何你想要的功能,扩展性非常强。
vite虽然也支持插件,但相比webpack的生态,还有一些距离。
4.应用场景不同
webpack由于其丰富的功能和扩展性,适合于大型、复杂的项目。
而vite凭借其轻量和速度,更适合于中小型项目和快速原型开发。