Webpack对jsx支持
在我们编写react代码时,react使用的语法是jsx, jsx是可以直接使用babel来转换的。
对react jsx代码进行处理需要如”下的插件:
- @babel/plugin-syntax-jsx
- @babel/plugin-transform-react-jsx
- @babel/plugin-transform-react-display-name
但是开发中,我们并不需要一个个去安装这些插件,我们依然可以使用preset来配置:
npm install @babel/preset-react -D
更改一下webpack.config.js
module: {
rules: [
// 针对jsx?代码进行babel处理
{
test: /.jsx?$/, // x?:标识0或者1
use: {
loader: "babel-loader"
}
},
]
}
再去babel.config.js中使用就可以了
presets: [
["@babel/preset-env", {
// 在开发中针对babel的浏览器兼容查询使用browserslist工具,而不是设置target
// 因为browserslist工具,可以在多个前端工具之间进行共享浏览器兼容性(postcss/babel)
// targets: ">0.5%"
// corejs: 3,
// false 不使用我们的polyfill进行填充
// useBuiltIns: "entry"
}],
// 对react代码进行处理
["@babel/preset-react"]
]
Webpack对TypeScript支持
在项目开发中,我们会使用TypeScript来开发,那么TypeScript代码是 需要转换成JavaScript代码。 可以通过TypeScript的compiler来转换成JavaScript:
npm install typescript -D
另外TypeScript的编译配置信息我们通常会编写一个tsconfig.json文件:
tsc --init
生成文件如下
之后我们可以运行npx tsc来编译自己的ts代码
使用ts-loader
如果我们希望在webpack中使用TypeScript,那么我们可以使用ts-loader来处理ts文件:
npm install ts-loader -D
配置ts-loader:
// 针对ts代码进行处理
{
test: /.ts$/,
use: "ts-loader"
}
之后,我们通过npm run build打包即可。
使用babel-loader
除了可以使用TypeScript Compiler来编译TypeScript之外,我们也可以使用Babel:
- Babel是有对TypeScript进行支持;
- 我们可以使用插件: @babel/tranform-typescript; .
- 但是更推荐直接使用preset: @babel/preset-typescript;
我们来安装@babel/preset-typescript:
npm install @babel/ preset-typescript -D
presets: [
["@babel/preset-env", {
// 在开发中针对babel的浏览器兼容查询使用browserslist工具,而不是设置target
// 因为browserslist工具,可以在多个前端工具之间进行共享浏览器兼容性(postcss/babel)
// targets: ">0.5%"
// corejs: 3,
// false 不使用我们的polyfill进行填充
// useBuiltIns: "entry"
}],
["@babel/preset-react"],
// 对ts进行babel处理
["@babel/preset-typescript", { corejs: 3, useBuiltIns: "usage" }]
]
ts-loader和babel-loader选择
那么我们在开发中应该选择ts-loader还是babel-loader呢?
使用ts-loader (TypeScript Compiler)
- 来直接编译TypeScript,那么只能将ts转换成js;
- 如果我们还希望在这个过程中添加对应的polyfill,那么ts-loader是无能为力的; .
- 我们需要借助于babel来完成polyill的填充功能;
使用babel-loader (Babel)
- 来直接编译TypeScript,也可以将ts转换成js, 并且可以实现polyill的功能;
- 但是babel-loader在编译的过程中,不会对类型错误进行检测;
最佳实践
也就是说我们使用Babel来完成代码的转换,使用tsc来进行类型的检查。
但是,如何可以使用tsc来进行类型的检查呢?
- 在这里,我在scripts中添加了两个脚本,用于类型检查;
- 我们执行npm run type-check可以对ts代码的类型进行检测;
- 我们执行npm run type-check-watch可以实时的检测类型错误;
就可以检测到类型错误的地方
Webpack本地服务器
本地服务器server
为什么我们需要搭建本地服务器?
目前我们开发的代码,为了运行需要有两个操作:
- 操作一: npm run build,编译相关的代码;
- 操作二:通过live server或者直接通过浏览器,打开index.htmI代码, 查看效果;
这个过程经常操作会影响我们的开发效率,我们希望可以做到,当文件发生变化时,可以自动的完成编译和展示; .
为了完成自动编译,webpack提供了几种可选的方式:
- webpack watch mode
- webpack-dev-server (常用)
- webpack-dev-middleware
webpack-dev-server
上面的方式可以监听到文件的变化,但是事实上它本身是没有自动刷新浏览器的功能的:
- 当然,目前我们可以在VSCode中使用live-server来完成这样的功能;
- 但是,我们希望在不适用live-server的情况下,可以具备live reloading (实时重新加载)的功能;
安装webpack-dev-server
npm install webpack-dev-server -D
修改配置文件,启动时可以加上参数
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack ",
"serve":"webpack serve",
},
webpack-dev-server在编译之后不会写入到任何输出文件,而是将bundle文件保留在内存中:
- 事实上webpack- dev-server使用了-个库叫memfs (memory-fs webpack自己写的)
server的静态资源
devServer的static
devServer中static对于我们直接访问打包后的资源其实并没有太大的作用,它的主要作用是如果我们打包后的资源,又依赖于其他的一些静态资源,那么就需要指定从哪里来查找这个内容:
-
比如在index.html中,我们需要依赖一-个abc.js文件,这个文件我们存放在public文件中;
-
在index.htmI中,我们应该如何去引入这个文件呢?
- 比如代码是这样的: < script src="./public/abc.js"> < /script>;
- 但是这样打包后浏览器是无法通过相对路径去找到这个文件夹的;
- 所以代码是这样的: < script src= "/abc.js"> < /script>;
- 但是我们如何让它去查找到这个文件的存在呢?设置static即可;
// webpack服务器配置
devServer: {
// 静态文件配置 默认为public 可以自定义文件夹
static: ['public', 'content']
},
需要使用时就直接./xxx就可以用
<link rel="icon" href="./icon.png">
server的其他配置
host配置
host设置主机地址:
- 默认值是localhost;
- 如果希望其他地方也可以访问,可以设置为0.0.0.0;
localhost和0.0.0.0的区别:
-
localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1;
-
127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收;
- 正常的数据库包经常应用层-传输层-网络层-数据链路层-物理层;
- 而回环地址,是在网络层直接就被获取到了,是不会经常数据链路层和物理层的;
- 比如我们监听127.0.0.1时,在同一个网段下的主机中,通过ip地址是不能访问的;
-
0.0.0.0:监听IPV4. 上所有的地址,再根据端口找到不同的应用程序;
- 比如我们监听0.0.0.0时,在同一一个网段下的主机中,通过ip地址是可以访问的;
port
port设置监听的端口,默认情况下是8080
open
open是否打开浏览器:
- 默认值是false,设置为true会打开浏览器;
- 也可以设置为类似于Google Chrome等值;
compress
compress是否为静态文件开启gzip compression:
- 默认值是false,可以设置为true;
// webpack服务器配置
devServer: {
// 静态文件配置 默认为public
static: ['public', 'content'],
// 网关地址
host: '0.0.0.0',
// 端口号
port: 8080,
// 是否自动打开
open: true,
// 是否开启本地服务器代码压缩
compress: true
},
server的proxy代理
proxy是我们开发中非常常用的一个配置选项,它的目的设置代理来解决跨域访问的问题:
- 比如我们的一-个api请求是http://ocalhost:8888,但是本地启动服务器的域名是http://ocalhost:8080,这个时候发送网络请求就会出现跨域的问题;
- 那么我们可以将请求先发送到-个代理服务器,代理服务器和API服务器没有跨域的问题,就可以解决我们的跨域问题了;
我们可以进行如下的设置:
- target:表示的是代理到的目标地址,比如/apihy/moment会被代理到htp://localhost:8888/api-hy/moment;
- pathRewrite:默认情况下,我们的/api-hy也会被写入到URL中,如果希望删除,可以使用pathRewrite;
- changeOrigin:它表示是否更新代理后请求的headers中host地址;
// webpack服务器配置
devServer: {
// 本地服务代理
proxy: {
// 将目标前缀为/api 代理成需要的地址
'/api': {
target: "http://localhost:9000",
// 重写请求地址
pathRewrite: {
"^/api": ""
},
changeOrigin: true
}
}
},
发送网络请求
// 8.发送网络请求获取数据
import axios from "axios";
axios.get('/api/users/list').then(res => {
console.log(res.data);
})
changeOrigin作用
- 如果后端没有做校验,无论什么地址都可以拿到数据
- 如果做好了校验,那么可能只能是同地址才可以拿到数据
- 所以changeOrigin作用就是修改我们去哪数据时的请求地址,让服务器认为是同地址发送的请求
服务器接收请求图
没有开启changeOrigin
开启changeOrigin
changeOrigin的解析
这个changeOrigin官方说的非常模糊,通过查看源码我发现其实是要修改代理请求中的headers中的host属性:
- 因为我们真实的请求,其实是需要通过http://localhost:8888来请求的;
- 但是因为使用了代码,默认情况下它的值时http://localhost:8000;
- 如果我们需要修改,那么可以将changeOrigin设置为true即可;
historyApiFallback
historyApiFallback是开发中一个非常常见的属性,它主要的作用是解决SPA页面在路由跳转之后,进行页面刷新时,返回404的错误。
boolean值:默认是false
- 如果设置为true,那么在刷新时,返回404错误时,会自动返回index.html 的内容;
object类型的值,可以配置rewrites属性:
- 可以配置from来匹配路径,决定要跳转到哪一个页面;
事实上devServer中实现historyApiFallback功能是通过connect-history-api-fallback库的:
// webpack服务器配置
devServer: {
// 刷新路由转跳处理
historyApiFallback: true
},