webpack是什么
定义
webpack是一个JavaScript应用程序的静态模块打包器。它会分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(less,ES6等),将其转换和打包为合适的格式供浏览器使用。
工作原理
把项目当作一个整体,通过一个给定的主文件(如:main.js),Webpack将从这个文件开始找到你的项目所有依赖文件,使用loader处理它们。最后打包为一个(或多个)浏览器可识别的JS文件。
为什么要使用webpack
一、loader的转换,预处理
- webpack通过使用loader将浏览器不能直接运行的拓展语言转换为可识别的,例如:使用babel-loader转换ES6语法,使用less-loader转换less语法等。
二、模块化,按需加载
- 对于较大规模的Web 应用(特别是单页应用),把所有代码合并到单个文件是比较低效的做法,单个文件体积过大会导致应用初始加载缓慢,尤其如果其中很多逻辑只在特定情况下需要执行,每次都完整地加载所有模块就变得很浪费。
- webpack 提供了代码拆分的方案,可以将应用代码拆分为多个块(chunk),每个块包含一个或多个模块,块可以按需被异步加载。
三、提高加载速度
将多个资源打包成一个文件,可以合并代码,减少HTTP请求,再通过压缩减少文件体积,从而提高加载速度:
- 对于单页应用程序中用到很多素材,如果每一个素材都通过在HTML中以src属性或者link来引入,那么请求一个页面的时候,可能浏览器就要发起十多次请求。
- 往往请求的这些资源都是一些脚本代码或者很小的图片,这些资源本身才几k,下载连1秒都不需要,但是由于HTTP是应用层协议,它的下层是TCP这个运输层协议,TCP的握手和挥手过程消耗的时间可能比下载资源本身还要长,所以需要把这些小文件全部打包成一个文件,这样只要一次TCP握手和挥手的过程,就把多个资源给下载下来了。
- 并且多个资源由于都是共享一个HTTP请求,所以head等部分也是共享的,相当于形成了规模效应,让网页展现更快,用户体验更好。
四、扩展性强,插件机制完善
热加载的使用方便搭建本地测试环境
在传统的前端开发中,每次修改完代码都需要刷新页面才能让改动生效,并验证改动是否正确。虽然像LiveReload 这样的功能可以帮助我们自动刷新页面,但当项目变大时,刷新页面往往要耗时好几秒,只有等待页面刷新完成才能验证改动。而且有些功能需要经过特定的操作、应用处于特定状态时才能验证,刷新完页面后还需要手动操作并恢复状态,较为烦琐。针对这一问题,webpack 提供了模块热替换的能力,它使得在修改完某一模块后无须刷新页面,即可动态将受影响的模块替换为新的模块,在后续的执行中使用新的模块逻辑。
– 摘自互联网
核心
一、入口
- 定义:指示webpack应使用哪个模块,来作为构建内部依赖的主文件。即通过入口文件,找到引入的依赖文件,处理这些文件后,输出到bunldes文件中
module.exports = {
entry: './test/main.js'
}
二、输出
- 定义:告诉webpack在哪里输出所创建的bundles,以及如何命名(一般习惯用build.js)
三、loader
- 定义:用来处理非JS文件。将所有类型的文件转换为webpack能够处理的有效模块。
- 参数:
test - 用于标识出应该被对应的 loader 进行转换的某个或某些文件
use - 表示进行转换时,应该使用哪个 loader
四、插件
- 定义:插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量
Webpack常见问题汇总
1.dependencies与devDependencies之间的区别(即–save-dev 和 –save的区别)
- 两者都是pakeage.json文件中的对象。通过
npm install --save-dev
或npm install -D
安装的插件,被写入到 devDependencies 对象里面去;通过npm install --save
或npm install -S
安装的插件 ,则被写入到 dependencies 对象里面去。 - dependencies是发布到线上需要打包或用到的文件,即项目运行所依赖的模块,而devDependencies指本地开发所需要的模块,不需要被打包。
- pakeage.json文件的配置只起提示作用,并不影响实际的安装,npm安装模块后自动记录到pakeage.json中。使用
npm i
可以一键安装配置好的内容。
2. loader的作用和写法
- loader将浏览器不能识别的语言转换成可识别的
- loader的使用方式有三种:
配置(推荐):在 webpack.config.js 文件中指定 loader。
内联:在每个 import 语句中显式指定 loader。
CLI:在 shell 命令中指定它们。 - 语法格式见官网
示例一:
module.exports = {
module: {
rules: [
{test: /\.js$/, use: ['babel-loader'], exclude: /node_modules/},
]
}
};
//test:代表正则表达式
//use: 加载器
//exclude:用来排除一些不需要转换的JS
示例二:
module.exports = {
module: {
rules: [
{test: /\.less$/, use: ['style-loader','css-loader?sourceMap','less-loader?sourceMap']}
]
}
};
//?sourceMap定义出错位置
3.path和publicPath的区别
- path是JS文件(如:main.js)打包后生成的文件(如:build.js)输出目录的绝对路径
- publicPath是各种静态资源的引用路径,为虚拟路径
4.devServer.proxy
如果有单独的后端开发服务器 API,并且希望在同域名下发送 API 请求 ,使用devServer.proxy代理一些 URL
devServer: { //解决跨域,在同域名下发送 API 请求
port: 80,
disableHostCheck: true,
proxy: {
'/daikou/a': {
target: 'xxx', //目标域名
changeOrigin: true //本地虚拟一个服务端接收请求并发送该请求
}
}
}