2020.11.28
浏览器请求各种静态资源 脚本is slow,得想办法把这些整合起来,
而使用es6模块化的require引入资源,浏览器不支持 浏览器端的模块系统无法使用,不只是require了,即使是es6标准的import很多低版本的浏览器也无法支持,尤其是IE,目前并没有很好的解决方案使得浏览器端自然的使用各个模块系统,只能使用webpack等工具预先将所有的依赖打包,最终在浏览器换进中运行
npm init -y
npm install webpack webpack-cli -D
1.新建 src/index.js 文件
npx webpack或者npx webpack --mode=development 进行构建,默认是 production 模式,我们为了更清楚得查看打包后的代码,使用 development 模式
使用 babel-loader,将打包的JS代码向低版本转换
npm install babel-loader -D
npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
npm install @babel/runtime @babel/runtime-corejs3
2.新建 webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
use: ['babel-loader'],
exclude: /node_modules/ //排除 node_modules 目录
}
]
}
}
新建 .babelrc 配置**babel**,也可以在 webpack.config.js 中进行配置
{ "presets": ["@babel/preset-env"], "plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": 3 } ] ]}
运行npx webpack --mode=development 看效果,打包的代码变多了,看不懂~
npm install html-webpack-plugin -D
注:指定打包文件中带有 hash,那么每次生成的 js 文件名会有所不同,不用每次手动去修改HTML)
npm install cross-env -D 兼容Windows与mac
npm install webpack-dev-server -D 在浏览器中实时查看效果,版本有问题,使用webpack serve
3.处理css
webpack借助loader处理css
我们需要的 loader 通常有: style-loader、css-loader,考虑到兼容性问题,还需要 postcss-loader,而如果是 less 或者是 sass 的话,还需要 less-loader 和 sass-loader
npm install style-loader less-loader css-loader postcss-loader autoprefixer less -D
style-loader 动态创建 style 标签,将 css 插入到 head 中.css-loader 负责处理 @import 等语句。postcss-loader 和 autoprefixer,自动生成浏览器兼容性前缀 —— 2020了,应该没人去自己徒手去写浏览器前缀了吧less-loader 负责处理编译 .less 文件,将其转为 css
4.图片/字体文件处理
npm install url-loader -D
npm install file-loader -D
有警告信息还得安装precss cssnano
奇怪:require 有的图片生效有的不生效???------需要重新构建。。npm run dev是仅仅运行,npx webpack 重新打包,或者是npm run build----再跑
5.入口与出口配置
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'), //必须是绝对路径
filename: 'bundle.[hash].js',
publicPath: '/' //通常是CDN地址
}
}
由于每次文件修改后,重新打包,导致 dist 目录下的文件越来越多
npm install clean-webpack-plugin -D 帮助打包前清空目录
//webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
//...
plugins: [
//也可以不传参数,它可以找到 outputPath
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns:['**/*', '!dll', '!dll/**'] //不删除dll目录下的文件
})
]
}
6.按需加载
不同阶段去加载所需要的代码 , 使用 import(***),会生成一些chunk
webpack 遇到 import(****) 这样的语法的时候,会这样处理:以**** 为入口新生成一个 Chunk
7.打包清空dist
npm install clean-webpack-plugin -D
//webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
//...
plugins: [
//不需要传参数喔,它可以找到 outputPath
new CleanWebpackPlugin()
]
}
8.webpack解决跨域问题
新建server.js模拟接口,使用到express
let express = require('express');
let app = express();app.get('/user', (req, res) => {
res.json({name: '周星星'});});app.listen(4000);
// node server.js 浏览器输入即可http://localhost:4000/api/user
在入口文件请求接口
fetch("/api/user") .then(response => response.json()) .then(data => console.log(data)) .catch(err => console.log(err));
webpack修改配置
devServer: {
port: '3000', //默认是8080
// 实现跨域
proxy: {
// "/api": "http://localhost:4000"
'/api': { // server.js去前缀写法
target: 'http://localhost:4000',
pathRewrite: {
'/api': ''
}
}
}
},
9.构建流程
初始化配置参数 -> 加载plugin,实例化compiler -> 确定Entry逐一遍历 -> 调用loader去加载模块 -> 输出文件
10. 优化
gzip文件压缩( Nginx 开启 gzip,服务端压缩浏览区解压)、CDN(减少Webpack打包出来的js体积)、图片压缩、去除sourceMap
devServer: { port: 8080, proxy: 'http://192.168.0.249/', },
// 表示当前项目启动端口为8080,即localhost:8080
在开发阶段, webpack-dev-server 会启动一个本地开发服务器,运行在localhost:8080
所以我们的应用在开发阶段是独立运行在 localhost的一个端口上,而后端服务又是运行在另外一个地址上http://192.168.0.249/
当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地
通过设置webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者
!!!服务器与服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制
Q1:webpack没有配置跨域 竟然没报错是什么原因?---使用的CORS,只需要后端配置access-control-allow-origin:*,浏览器在发送请求时,检测到跨域时,会自动加上一个额外的 Origin 头部,前端不用做任何操作即可访问
Q2:配置pathrewrite??---通常是因为API对应了多个服务器域名,用作区分匹配,匹配完之后再改回来,如果没有做区分可以不加pathrewrite
Q3: get请求—带#号是什么意思??—获取到资源文件
Q4:'/api': 'http://localhost:3000'表示----'/api',表示如果API中有这个字符串,会被代理到请求 http://localhost:3000/api/xxx,target表示需要跨域的地址,设置target后,devserver会弄一个代理服务器去模拟浏览器发送请求。如果target是个域名,需要设置changeOrigin:true,否则会代理失败;如果要设置支持https协议,设置secure:false,不检查安全问题 axios: url:'/assess/xxx',baseUrl:'/api',baseUrl自动加在url前面除非url是个绝对URL,假设你vue-cli起了一个开发环境,地址为http://localhost:8080,那么最终请求地址就是http://localhost:8080/api/assess/xxx