devServer常用配置
一、本地开发服务
1.1 proxy 代理
1.1.1 启动一个服务,mock一个接口
npm i express -D
新建server.js
const express = require("express");
const app = express();
app.get("/api/info",(req,res)=>{
res.json({
hello:"express",
})
});
app.listen("9092");
node server.js
http://localhost:9092/api/info
1.1.2 项目中安装axios工具
npm i axios -D
index.js
import axios from "axios";
axios.get("http://localhost:9092/api/info").then(res=>{
console.log("res",res);
});
会有跨域问题
1.1.3 修改webpack.config.js 设置服务器器代理理
devServer: {
......
//代理
proxy:{
"/api":{
target:"http://localhost:9092"
}
}
},
1.2 mock server
devServer: {
......
// 代理
// 配置联调环境
- proxy:{
- "/api":{
- target:"http://localhost:9092"
- }
- },
// mock server
// 配置mock环境
+ before: function (app, server, compiler) {
+ app.get('/api/mock.json', function (req, res) {
+ res.json({
+ hello: 'express'
+ });
+ });
+ },
},
1.不需要新建server.js
2.不需要启动 node server.js
3.proxy 适合开发环境
mock server适合开发环境
二、Hot Module Replacement (HMR:热模块替换)
当我们使用webpack-dev-server的自动刷新功能时,浏览器会整页刷新。
而热替换的区别就在于,当前端代码变动时,无需刷新整个页面,只把变化的部分替换掉。
HMR(Hot Module Replacement)能够实现在页面不刷新的情况下,代码也可以及时的更新到浏览器的页面中,重新执行,避免页面状态丢失。
启动HMR
webpack4:
此时Webpack4
可以实现css的热替换
;
但不能实现js、图片等的热替换
,此二者需要自己手动通过代码来处理
css热模块
webpack.config.js
webpack4
+ const webpack = require("webpack");
devServer: {
......
+ hot:true,
//hotOnly:true 即使HMR没有生效,浏览器也不要自动刷新
+ hotOnly:true,
},
module: {
rules: [
......
{
test: /\.less$/i,
use: [
+ "style-loader", 放开
- MiniCssExtractPlugin.loader, // 注释
{
loader: "css-loader",
options: {
modules: true,
},
},
{
loader: "postcss-loader",
},
"less-loader"],
},
......
]
},
plugins: [
- new MiniCssExtractPlugin({
- filename: "[name][chunkhash:8].css"
- filename: "css/[name].css"
- }),
+ new webpack.HotModuleReplacementPlugin()
],
index.js index.less
//index.js
import "./css/index.less";
var btn = document.createElement("button");
btn.innerHTML = "新增";
document.body.appendChild(btn);
btn.onclick = function() {
var div = document.createElement("div");
div.innerHTML = "item";
document.body.appendChild(div);
};
//index.less
div:nth-of-type(odd) {
background: yellow;
}
js热模块
webpack.config.js
在这里插入代码片
number.js counter.js index.js
number.js
function number() {
var div = document.createElement("div");
div.setAttribute("id", "number");
div.innerHTML = 6666;
document.body.appendChild(div);
}
export default number;
counter.js
function counter() {
var div = document.createElement("div");
div.setAttribute("id", "counter");
div.innerHTML = 1;
div.onclick = function () {
div.innerHTML = parseInt(div.innerHTML, 10) + 1;
};
document.body.appendChild(div);
}
export default counter;
index.js
//-----------------js热模块替换------------------------------
import "./css/index.less";
import counter from './counter'
import number from './number'
counter();
number();
if(module.hot){
//要让 哪些模块 实现js HMR
//当检测到number.js 模块 发生变化的时候
module.hot.accept("./number.js",function(){
//手动移除
document.body.removeChild(document.getElementById("number"));
//重新执行 number()
number();
});
}
webpack5:
可以实现css热模块,js热模块
- const webpack = require("webpack");
devServer: {
......
+ hot:true,
- hotOnly:true,
},
module: {
rules: [
......
{
test: /\.less$/i,
use: [
+ "style-loader",
|| + MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
},
},
{
loader: "postcss-loader",
},
"less-loader"],
},
......
]
},
plugins: [
- new MiniCssExtractPlugin({
- filename: "[name][chunkhash:8].css"
- filename: "css/[name].css"
- }),
- new webpack.HotModuleReplacementPlugin()
],
devServer: {
......
+ hot:true,
......
},
vue使用HMR:
Babel处理ES6
npm i babel-loader @babel/core @babel/preset-env -D
- 1.babel-loader 是 webpack 与 babel的通信桥梁,不会把es6转成es5的工作,这部分工作需要用到 @babel/preset-env
- 2.@babel/preset-env⾥包含了了es,6,7,8转es5的转换规
webpack.config.js
module: {
rules: [
......
{
test: /\.m?js$/,
//exclude 排除
exclude: /(node_modules|bower_components)/,
use: {
/**
* npm i babel-loader -D
* 1.babel-loader 是 webpack 与 babel的通信桥梁,不会把es6转成es5的工作,这部分工作需要用到 @babel/preset-env
* 安装 npm i @babel/core @babel/preset-env -D
*
*
* 执行顺序,实现步骤
* 1.检测到 js 模块 , 使用babel使 webpack 和 babel babel/core 有一个通信
* 2.使用 preset-env 进行转换
*/
loader: 'babel-loader',
options: {
//语法转换插件 preset-env
presets: ['@babel/preset-env'],
}
}
}
]
},
通过上⾯的⼏步 还不够
,默认的Babel只⽀持let等⼀些基础的特性转换,Promise
等⼀些还没有转换过 来,这时候需要借助@babel/polyfill
,把es的新特性都装进来,来弥补低版本浏览器中缺失的特性。
npm install --save @babel/polyfill
index.js
//index.js 顶部
import "@babel/polyfill";
会发现打包的体积⼤了很多,这是因为polyfill默认会把所有特性注⼊入进来,假如我想我⽤用到的es6+,才 会注入,没⽤到的不注入,从而减少打包的体积,可不可以呢
按需加载,减少冗余
npm install --save @babel/polyfill
babel7
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
- presets: ['@babel/preset-env'],
+ presets: [
+ ['@babel/preset-env',
+ {
// 指定兼容性做到那个版本的浏览器
+ targets: {
+ edge: "17",
+ firefox: "60",
+ chrome: "67",
+ safari: "11.1"
+ ie: "8"
+ },
// 指定 core-js 版本
+ corejs: 2,//新版本需要指定核⼼心库版本
// 按需注⼊入
+ useBuiltIns: "usage"
+ }
+ ]
+ ],
}
}
}
useBuiltIns
"usage" | "entry" | false,默认值是 false
-
false:需要在 js 代码第一行主动 import ‘@babel/polyfill’,会将@babel/polyfill 整个包全部导入。
不推荐
,能覆盖到所有 API 的转译,但体积最大 -
entry:需要在 js 代码第一行主动 import ‘@babel/polyfill’,会将 browserslist 环境不支持的所有垫片都导入。
-
usage:项目里不用主动 import,会自动将代码里已使用到的、且 browserslist 环境不支持的垫片导入。
polyfill
- 如果是自己的应用: @babel/preset-env + @babel/polyfill
- 如果是开发第三方类库: @babel/preset-env + @babel/plugin-transform-runtime + @babel/runtime-corejs2
针对做开源、UI库、组件库、工具库的时候,选择 polyfill 会有 全局污染问题
babel插件分两部分
- 语法转换 @babel/preset-env
- 语法解析
扩展:
babelrc文件: 新建.babelrc⽂文件,把options部分移⼊入到该文件中,就可以了
配置React打包环境
安装
npm install react react-dom --save
编写react代码:
//index.js
import React, { Component } from "react";
import ReactDom from "react-dom";
class App extends Component {
render() {
return <div>hello world</div>;
}
}
ReactDom.render(<App />, document.getElementById("app"));
npm install --save-dev @babel/preset-react
在babelrc文件里添加:
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"corejs": 2,
"useBuiltIns": "usage"
}
],
+ "@babel/preset-react"
]
}
hash
所有chunk文件使用相同的hash
项目中任一文件内容发生变化都会影响所有chunk文件hash
chunkhash (不利于js和css分离)
基于 webpack 的 entry point
任意文件改变只会影响其所属的chunk,不会影响其它chunk。
contenthash
基于文件内容产生的hash
影响范围只限于本文件