文章目录
理解webpack
最重要的四大模块
- 入口
- 出口
- 装载器loader: webpack只能理解js和json文件,使用loader之后可以处理其他类型的文件,并将他们转转成webpack可识别的模块。比如babel-loader: 将es6转成es5,react-loader: 加载react文件,vue-loader同理,以及css-loader,加载css文件,sass-loader将sass代码转成css代码,image-loader,ts-loader:将ts转成js代码等
- 插件plugin:打包优化,资源管理,注入环境变量。例如
创建webpack工程
-
生成package.json文件
npm init -y -
安装webpack
cnpm install -D webpack webpack-cli
-D -S 把依赖包保存在package.json文件中
-S 保存的包是需要发布的
-D 是不需要发布的
默认安装的是最新版本, 版本过高 webpack@4
node自带npm npx
cnpm和yarn不是node自带的
webpack零配置
打包命令: npx webpack
默认入口 src/index.js
默认出口 dist/main.js
只打包js,生成main.js
指定webpack配置
let path = require("path");
let HtmlWebpackPlugin = require("html-webpack-plugin");
// module 是node 的语法,webpack是基于node的
module.exports = {
// 入口
entry: "./src/index.js",
/**
* 打包的模式,只有两种,一种是production生产模式,
* 这个打包之后代码是压缩之后的,不便于我们查看;另一种development 开发模式,打包之后代码没有压缩,
* 在浏览器中可以查看代码,便于我们调试
* */
mode: "development",
// 出口
output: {
// __dirname 当前路径
path: path.resolve(__dirname, "dist"), // 绝对路径 ,在根目录生成一个dist的文件夹,里面是打包之后的文件
filename: "index.js", // 修改打包之后的js文件名
},
devServer: {
// 配置webpack-dev-server 开发使用
port: 8081, // 配置web服务器端口,端口不能相同
open: true, // 启动成功之后自动打开浏览器
progress: true, // 进度
contentBase: "./dist", // 指定web服务的根目录,服务一打开就直接去dist文件夹下找index.html文件,有就直接打开
},
plugins: [
// HtmlWebpackPlugin这个插件是将html模板打包进dist文件夹里,因为webpack 零配置只打包js文件
new HtmlWebpackPlugin({
template: "./src/index.html", // 指定输出的文件模板
filename: "index.html", // 修改打包之后的模板名称,最好使用index.html,
}),
],
};
注意:HtmlWebpackPlugin下的filename最好命名为index.html,因为系统会自动去找index.html,如果不改成其它名字,访问地址的时候就不会直接显示页面,也是显示项目文件,让你自己去选择html.效果就如下了,这个效果是不好的,记住
如何启动服务 webpack-dev-server
- 首先安装webpack-dev-server命令
npm install -D webpack-dev-server
yarn add webpack-dev-server -D
- 然后在package.json文件下scripts写如下代码
// package.json
{
"name": "01",
"version": "1.0.0",
"description": "- 入口 - 出口 - 装载器loader - 插件plugin",
"main": "index.js",
"scripts": {
"start": "webpack serve", // 执行命令 npm start
"dev": "webpack serve",// 命令npm run dev ,执行的命令其实是webpack serve
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.3.1",
"webpack": "^5.24.4",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
}
}
- 最后你就可以使用命令(npm start or npm run dev)启动你的项目服务,项目就跑起来拉
配置webpack-dev-server 开发使用
在webpack.config.js文件里
devServer: {
// 配置webpack-dev-server 开发使用
port: 8081, // 配置web服务器端口,端口不能相同
open: true, // 启动成功之后自动打开浏览器
progress: true, // 进度
contentBase: "./dist", // 指定web服务的根目录,服务一打开就直接去dist文件夹下找index.html文件,有就直接打开
},
css /js/es6 es7支持 装载器 loader,插件plugin
css(装载器)
-
webpack默认只加载js,不支持加载css;
-
需要css装载器 css-loader;
-
再 安装style-loader 把css直接添加到html的
**装载器执行顺序 **
先加载 css 后整合到html的< style>
执行顺序:从右到从。
// 先安装css-loader ,style-loader ,yarn add css-loader -D
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"], // 执行顺序是从右向左
},
],
},
less (装载器)
cnpm i -D less less-loader
use: ['style-loader','css-loader','less-loader']
// 具体
module: {
{
test: /\.less$/,
use: ["style-loader", "css-loader", "less-loader"], // 现将less文件装载到less-loader转化成css ,然后再装载到css 里,最后渲染到style 标签上
},
],
},
抽取css作为单独的文件 mini-css-extract-plugin(插件)
- 将 CSS 提取为独立的文件的插件,对每个包含 css 的 js 文件都会创建一个 CSS 文件,支持按需加载 css 和 sourceMap.只能用在 webpack4 中,对比另一个插件 extract-text-webpack-plugin 有以下特点:
- 异步加载
- 不重复编译,性能更好
- 更容易使用
- 只针对 CSS
这个插件应该只用在生产环境配置,并且在 loaders 链中不使用 style-loader, 而且这个插件暂时不支持 HMR
let MiniCssExtractPlugin = require('mini-css-extract-plugin');
use: [MiniCssExtractPlugin.loader, 'css-loader']
new MiniCssExtractPlugin({
filename: 'index.css'
})
# css js压缩
css:optimize-css-assets-webpack-plugin 或者 css-minimizer-webpack-plugin
在指定css压缩后 js压缩就无效了,需要再次指定js: terser-webpack-plugin
let TerserPlugin = require('terser-webpack-plugin') // js压缩
let OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin') //css压缩
let CssPlugin = require('css-minimizer-webpack-plugin') // css压缩
optimization: {
//压缩
minimizer: [new TerserPlugin(), new CssPlugin()] // [new TerserPlugin(), new OptimizeCssPlugin()]
},
** es6 es7支持**
- 首先需要babel-loader的装载器,@bable/core,@bable/preset-env(转换器,将se7转es6或者将es6转es5的)
- 需要一个插件 babel-plugin-proposal-decorators 这个就是es7上的注解@xx,将这个编译成es6的插件
安装命令:
yarn add babel-loader -D
yarn add @bable/core -D
yarn add @bable/preset-env -D
yarn add @babel-plugin-proposal-decorators -D
babel-loader 插件 ;可以在babel官网上查询相应的插件,如@babel/plugin-proposal-decorators
module:{
rules:[
{
test:/\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
"@babel/preset-env"
],
"plugins": [
// es6,es7 转化插件
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }]
]
}
}
},
]
}
js 模块化
commonjs:导出:module.exports ;导入:require
es6: 导出: export default, export xxx ;导入: import xx from xxx
使用上面的装载器之后就可以直接打包成功
tree shaking 【摇树】(过滤掉没有调用到的代码)
webpack4有这个功能,很弱,只支持当前js文件中无用的代码;webpack5加强了这个功能。
如:a.js(有无用的代码, a=1,b=2)---》被index.js引入(只引了部分,输出a)
会检查整个链路中属性的使用情况,确定没有使用就去掉。
但是只会在生产模式下才会过滤,开发模式都会打包。
webpack.config 1
// webpack.config
let path = require('path');
let HtmlWebpackPlugin = require("html-webpack-plugin"); // html 插件 自动在html 引入js文件
let MiniCssExtractPlugin = require('mini-css-extract-plugin'); //插件 抽取css作为单独的文件
let TerserPlugin = require('terser-webpack-plugin') // js压缩
let OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin') // css压缩
let CssPlugin = require('css-minimizer-webpack-plugin') // css压缩
module.exports = {
optimization: {
//压缩
minimizer: [new TerserPlugin(), new CssPlugin()]
},
//入口 出口 loader plugin
entry: "./src/index.js", //输入
mode: 'production', //production development // 模式
output: { // 输出
//__dirname 表示当前目录
path: path.resolve(__dirname, "dist"), //绝对路径
filename: "index.js" //输出的文件名
},
devServer: { //配置webpack-dev-server
port: 8083, //配置web服务端口
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist' //指定web服务器的根目录
},
module: { //装载器
rules: [
{
test:/\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
"@babel/preset-env"
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }]
]
}
}
},
{
test: /\.css$/,
// use: ['style-loader','css-loader'] // 执行顺序:从右到从,其他规则一直
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.less$/,
// use: ['style-loader','css-loader','less-loader']
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
}
]
},
plugins: [ // 插件
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'index.html' //指定输出dist的文件名
}),
new MiniCssExtractPlugin({
filename: 'index.css'
})
]
}
package.json1
{
"name": "01",
"version": "1.0.0",
"description": "- 入口 - 出口 - 装载器loader - 插件plugin",
"main": "index.js",
"scripts": {
"start": "webpack serve",
"dev": "webpack serve",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/plugin-proposal-decorators": "^7.13.5",
"@babel/preset-env": "^7.13.10",
"babel-loader": "^8.2.2",
"css-loader": "^5.1.3",
"css-minimizer-webpack-plugin": "^1.3.0",
"html-webpack-plugin": "^5.3.1",
"less": "^4.1.1",
"less-loader": "^8.0.0",
"mini-css-extract-plugin": "^1.3.9",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^5.1.1",
"webpack": "^5.24.4",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
}
}
打包生成文件动态名字及hash
没有分类存储 js css,可以output.filename: “js/index.js”,filename: ‘css/index.css’ 这样解决
使用hash值的时候,第一次打包发布, index.123.js 文件会被浏览器自动缓存。
当第二次修改打包发布,若文件名不变,浏览器会不会下载新的文件?
答案是不会。浏览器304代表的是缓存,如果文件名不变,浏览器觉得文件没更新,就不会从服务器重新请求。
hash—内容如果有改变,hash值就会改变
output: {
//__dirname 表示当前目录
path: path.resolve(__dirname, "dist"), //绝对路径
// filename: "js/index.js" // index.js //输出的文件名
filename: "js/[name].[hash:4].js" //hash 输出动态文件名
},
plugins: [
// HtmlWebpackPlugin这个插件是将html模板打包进dist文件夹里,因为webpack 零配置只打包js文件
new HtmlWebpackPlugin({
template: "./src/index.html", // 指定输出的文件模板
filename: "index.html", // 修改打包之后的模板名称,最好使用index.html,
}),
new MiniCssExtractPlugin({
filename: "css/[name].[hash:4].css", // //hash 输出动态文件名
}),
]
全局变量
使用import导入,需要在使用的地方都要导入一次
全局变量配置
webpack.ProvidePlugin能够给所有组件注入全局变量$
plugins:[
new webpack.ProvidePlugin({ //全局变量
$: 'jquery'
})
]
问题:打包时会把jquery等三方包一起打包,怎么把第三方包剔除出去呢,不要打包第三方包?
打包时,可以使用externals把三方包拆开,但是需要在Html上手动引入三方包,可以使用cdn有钱最好使用收费的三方报,比较稳定;把第三方下载下来放到你的目录,但是这样子会增加你的带宽;
plugins:[],
externals: { //排除三方包
jquery: '$'
}
图片
图片的加载需要 file-loader/url-loader 装载器
file-loader 默认使用es6模块化
\1. 使用js方式导入
\2. 使用css方式导入
css文件在根目录ok
css文件在css目录中,需要打包时将图片加上…/前缀,
图片加载到指定目录images
\3. 在html上加载图片,使用标签
<body>
<div id="test">webpack package</div>
<div id="test2">webpack package</div>
html上加载图片
<img src="./1.jpeg" />
</body>
配置文件
// 图片 js引入
var jpg = require("./1.jpeg");
console.log(jpg)
let img = new Image();
img.src = jpg;
// file-loader使用es6模块化
// var jpg = require("./1.jpeg"); 这里用import 引入需要 jpg.default吗?待测试。
// img.src = jpg.default;
// file-loader使用commonjs
document.body.appendChild(img)
//a.css
#test {
color: brown;
width: 300px;
height: 300px;
background: url('./2.jpeg');
}
// webpack.config
{
test: /\.css$/,
// use: ['style-loader','css-loader']
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../' //给css中所有图片添加相对路径 如果less等也用到图片 也要配置
// 配置路径根据打包后的文件路径配置,如果都是根目录就不需要配,这里因 // 为在css文件夹下
}
}, 'css-loader', 'postcss-loader']
},
{
test: /\.(jpeg|jpg|png)$/,
// use: {
// loader: 'file-loader',
// options: {
// esModule: false, //使用commonjs
// outputPath: 'images' //把图片加载到目录下
// }
// }
},
图片加载转换
使用url-loader代替file-loader, url-loader包含了file-loader
-
- 对于小于多少的图片,可以打包时转换为base64,图片转为base64可以减少http请求
-
- 对于较大的图片,直接提供url,让浏览器下载,可以使用cdn优化
{
test: /\.(jpeg|jpg|png)$/,
use: {
loader: 'url-loader',
options: {
esModule: false,
outputPath: 'images', // 图片加载到指定目录images
limit: 20*1024 //小于20kb的图片转base64
}
}
}
样式兼容性
w3c提出一些新样式,css3包括很新标准样式 aaa
浏览厂商:微软ie edge chrome ff
chrome: webkit-aaa
ie: ie-aaa
等到所有的厂商都支持后,就可以去掉前缀;
使用兼容性插件目的就是生成所有厂商前缀的样式。
1.配置postcss.config.js
2.配置postcss-loader
3.配置package.json中browserslist
1 // postcss.config.js 根目录
module.exports = {
plugins: [
require('autoprefixer')
]
}
2 //配置postcss-loader
{
test: /\.css$/,
// use: ['style-loader','css-loader']
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../' //给css中所有图片添加相对路径
}
}, 'css-loader', 'postcss-loader'] //配置postcss-loader
},
{
test: /\.less$/,
// use: ['style-loader','css-loader','less-loader']
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
'postcss-loader'
] //配置postcss-loader
}
3 //配置package.json中browserslist
对于部分配置参数做一些解释:
" >1%" :代表着全球超过1%人使用的浏览器
“last 2 versions” : 表示所有浏览器兼容到最后两个版本
“not ie <=8” :表示IE浏览器版本大于8(实则用npx browserslist 跑出来不包含IE9 )
“safari >=7”:表示safari浏览器版本大于等于7
"browserslist": [
"> 1%",
"last 100 versions",
"not ie <= 8"
]
webpack.config 2
let path = require('path');
let HtmlWebpackPlugin = require("html-webpack-plugin");
let MiniCssExtractPlugin = require('mini-css-extract-plugin');
let TerserPlugin = require('terser-webpack-plugin')
let OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin')
let CssPlugin = require('css-minimizer-webpack-plugin')
let webpack = require("webpack")
module.exports = {
optimization: {
//压缩
minimizer: [new TerserPlugin(), new CssPlugin()]
},
//入口 出口 loader plugin
entry: "./src/index.js",
mode: 'production', //production
output: {
//__dirname 表示当前目录
path: path.resolve(__dirname, "dist"), //绝对路径
filename: "js/[name].[hash:4].js" //输出的文件名
},
devServer: { //配置webpack-dev-server
port: 8083, //配置web服务端口
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist' //指定web服务器的根目录
},
module: {
rules: [
{
test:/\.html$/,
use: 'html-withimg-loader'
},
{
test: /\.(jpeg|jpg|png)$/,
use: {
loader: 'url-loader',
options: {
esModule: false,
outputPath: 'images',
limit: 20*1024 //小于20kb的图片转base64
}
}
// use: {
// loader: 'file-loader',
// options: {
// esModule: false, //使用commonjs
// outputPath: 'images' //把图片加载到目录下
// }
// }
},
{
test:/\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
"@babel/preset-env"
],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }]
]
}
}
},
{
test: /\.css$/,
// use: ['style-loader','css-loader']
use: [{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../' //给css中所有图片添加相对路径
}
}, 'css-loader', 'postcss-loader']
},
{
test: /\.less$/,
// use: ['style-loader','css-loader','less-loader']
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader', 'postcss-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'index.html' //指定输出dist的文件名
}),
new MiniCssExtractPlugin({ //抽取css为单独的文件
filename: 'css/[name].[hash:4].css'
// filename: 'index.css'
}),
new webpack.ProvidePlugin({ //全局变量
$: 'jquery'
})
],
externals: { //排除三方包
jquery: '$'
}
}
package.json2
{
"name": "01",
"version": "1.0.0",
"description": "- 入口 - 出口 - 装载器loader - 插件plugin",
"main": "index.js",
"scripts": {
"start": "webpack serve",
"dev": "webpack serve",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.13.10",
"@babel/plugin-proposal-decorators": "^7.13.5",
"@babel/preset-env": "^7.13.10",
"autoprefixer": "^10.2.5",
"babel-loader": "^8.2.2",
"css-loader": "^5.1.3",
"css-minimizer-webpack-plugin": "^1.3.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.1",
"html-withimg-loader": "^0.1.16",
"less": "^4.1.1",
"less-loader": "^8.0.0",
"mini-css-extract-plugin": "^1.3.9",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss-loader": "^5.2.0",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^5.1.1",
"url-loader": "^4.1.1",
"webpack": "^5.24.4",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"jquery": "^3.6.0"
},
"browserslist": [
"> 1%",
"last 100 versions",
"not ie <= 8"
]
}
多页面应用打包
- 需要指定多个入口
- 多个出口
- 多个HtmlWebpackPlugin用于生成多个页面
- 需要chunks指定需要引入的js
webpack.config.js
let path = require('path');
let HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
//多页面应用 多个入口 打包要生成多个html
entry: {
index: "./src/index.js",
other: "./src/other.js"
},
mode: 'development', //production
//出口 也需要输出多个文件
output: {
//__dirname 表示当前目录
path: path.resolve(__dirname, "dist"), //绝对路径
filename: "[name].js" //输出的文件名
},
devServer: { //配置webpack-dev-server
port: 8083, //配置web服务端口
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist' //指定web服务器的根目录
},
plugins: [
//主页 里面引入的js也不一样
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'index.html', //指定输出dist的文件名
chunks: ['index'] //指定页面需要的js
}),
//订单页 比如需要2个js
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'other.html', //指定输出dist的文件名
chunks: ['index','other']
})
]
}
多环境打包
# webpack 多环境打包
- 开发环境, 发布测试环境, 发布线上环境
- 开发服务器 http://192.168.1.100:8080
测试服务器 http://192.168.1.200:8080
线上服务器 http://xxxxxxxxxxxx:8080
webpack.base.js
// 父模板 webpack.base.js
let path = require('path');
let HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
//入口 出口 loader plugin
entry: "./src/index.js",
output: {
//__dirname 表示当前目录
path: path.resolve(__dirname, "dist"), //绝对路径
filename: "index.js" //输出的文件名
},
devServer: { //配置webpack-dev-server
port: 8083, //配置web服务端口
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist' //指定web服务器的根目录
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'index.html' //指定输出dist的文件名
})
]
}
webpack.dev.js
//开发模式
let path = require('path');
let webpack = require("webpack");
let {merge} = require('webpack-merge')
let base = require('./webpack.base')
module.exports = merge(base, {
mode: 'development', //production
plugins: [
// 定义webpack变量
new webpack.DefinePlugin({
DEV_ENV: JSON.stringify('dev url')
})
]
})
webpack.prod.js
//生产模式
let path = require('path');
let webpack = require("webpack");
let {merge} = require('webpack-merge')
let base = require('./webpack.base')
module.exports = merge(base, {
mode: 'production', //production
plugins: [
// 定义webpack变量
new webpack.DefinePlugin({
DEV_ENV: JSON.stringify('prod')
})
]
})
webpack.test.js
//生产模式
let path = require('path');
let webpack = require("webpack");
let {merge} = require('webpack-merge')
let base = require('./webpack.base')
module.exports = merge(base, {
mode: 'production', //production
plugins: [
// 定义webpack变量
new webpack.DefinePlugin({
DEV_ENV: JSON.stringify('test')
})
]
})
package.json
{
"name": "01",
"version": "1.0.0",
"description": "- 入口 - 出口 - 装载器loader - 插件plugin",
"main": "index.js",
"scripts": {
"start": "webpack serve",
"dev": "webpack serve",
"build:test": "webpack --config webpack.dev.js",
"build:prod": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.3.1",
"webpack": "^5.24.4",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
}
}
src下的index.js
console.log(DEV_ENV)
if (DEV_ENV === 'dev') {
console.log("这是测试环境, 输出大量的日志,便于定位问题")
} else {
console.log("这是线上环境, 减少日志输出 ")
}
# 模板模式
\1. 先要有一个模板,模板里面会实现大部分通用页面
webpack.base.js
\2. 子文件 继承 模板,并且自己扩展
根据不同的环境使用不同的文件
webpack.dev.js 开发
webpack.prod.js 线上
\3. 最终得到一个 子和父的 合体
打包只需要输入不同的命令
测试: npm run build:test
线上:npm run build:prod
跨域和热加载
# 什么是跨域?
协议 域名 端口 三者只要有不同就是跨域
http://www.baidu.com:80 默认80
https://www.baidu.com:443 默认443
# 搭建服务端
使用express搭建服务端
启动: node server.js
# 多种跨域处理
- cors 在数据交互中讲过 属于后端跨域,推荐后端来做跨域处理
- 代理 nginx 处理跨域 推荐
- webpack处理跨域:前两种可以的情况下,不推荐使用webpack做跨域处理,这种方法打包之后就失效了,只适合开发的时候
\1. 使用proxy代理方式处理跨域
devServer:{
proxy: {
//匹配以/api开头的请求并跳转到target
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'/api': ''} //去掉前缀
},
'/my': {
target: 'http://localhost:3000'
}
},
}
\2. 使用webpack插件把前后端合在一起,这是在后端那边处理,后端启动服务的时候,也一并将前端服务启动
// 将前后端合并
let webpack = require("webpack");
let middle = require("webpack-dev-middleware");
let config = require('./webpack.config');
let compiler = webpack(config)
app.use(middle(compiler))
# 热更新
webpack提供的特性,不用刷新,不用重启,直接将更新的内容加载到页面上了
devServer: { //配置webpack-dev-server
port: 8083, //配置web服务端口
hot: true, //开启热更新
proxy: {
//匹配以/api开头的请求并跳转到target
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'/api': ''} //去掉前缀
},
'/my': {
target: 'http://localhost:3000'
}
},
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist' //指定web服务器的根目录
},
server.js
// node express
let express = require('express')
let app = express();
// 将前后端合并
let webpack = require("webpack");
let middle = require("webpack-dev-middleware");
let config = require('./webpack.config');
let compiler = webpack(config)
app.use(middle(compiler))
app.get('/api/user', (req, res)=> {
res.json({name:'api user'})
})
app.get('/my/user', (req, res)=> {
res.json({name:'my user'})
})
app.get('/my/user2', (req, res)=> {
res.json({name:'my user'})
})
app.get('/user', (req, res)=> {
res.json({name:'no api user'})
})
app.listen(3000, ()=>{
console.log("服务已启动, 端口3000")
})
webpack.config.js
let path = require('path');
let HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
//入口 出口 loader plugin
entry: "./src/index.js",
mode: 'development', //production
output: {
//__dirname 表示当前目录
path: path.resolve(__dirname, "dist"), //绝对路径
filename: "index.js" //输出的文件名
},
devServer: { //配置webpack-dev-server
port: 8083, //配置web服务端口
hot: true, //开启热更新
proxy: {
//匹配以/api开头的请求并跳转到target
'/api': {
target: 'http://localhost:3000',
pathRewrite: {'/api': ''} //去掉前缀
},
'/my': {
target: 'http://localhost:3000'
}
},
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist' //指定web服务器的根目录
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'index.html' //指定输出dist的文件名
}),
new HtmlWebpackPlugin({
template: './src/index.html', //指定输出的文件模板
filename: 'main.html' //指定输出dist的文件名
})
]
}
package.json
{
"name": "01",
"version": "1.0.0",
"description": "- 入口 - 出口 - 装载器loader - 插件plugin",
"main": "index.js",
"scripts": {
"start": "webpack serve",
"dev": "webpack serve",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"express": "^4.17.1",
"html-webpack-plugin": "^5.3.1",
"webpack": "^5.24.4",
"webpack-cli": "^4.5.0",
"webpack-dev-middleware": "^4.1.0",
"webpack-dev-server": "^3.11.2"
}
}
index.js
//ajax
let xhr = new XMLHttpRequest()
// xhr.open('get', 'http://localhost:3000/api/user');
xhr.open('get', '/api/user')
xhr.onload = function () {
console.log(xhr.response)
}
xhr.send()
//ajax
let xhr2 = new XMLHttpRequest()
// xhr.open('get', 'http://localhost:3000/api/user');
xhr2.open('get', '/my/user')
xhr2.onload = function () {
console.log(xhr2.response)
}
xhr2.send()
// 热更新
import test from './test'
console.log(test)
//判断热更新是否开启
if (module.hot) {
module.hot.accept('./test', () => {
console.log('文件更新了')
let s = require('./test')
console.log(s.default)
})
}
test.js
export default "test111"