前面几篇文章,详细介绍过webpack的核心配置项,入口起点、出口文件、加载器loader和插件plugin,感兴趣的可以前往查看
项目开发,一般都是在本地起一个服务,进行代码的运行和调试。前面几篇文章介绍到了,webpack
对项目进行编译打包,方便在浏览器上运行。
那么问题来了,怎么样让打包好的项目文件,在浏览器上运行起来呢?
webpack中提供的开发环境工具 devServer,让打包的项目在浏览器上运行,通过配置devServer的属性,使开发过程更加高效地进行调试和测试
webpack-dev-server
(简写: dev-server
),用于快速开发应用程序。
devServer
的主要作用包括:
- 提供本地服务器:
devServer
启动一个本地服务器,使得你可以在本地环境中访问和测试你的 Webpack 项目。 - 实时重新加载:
devServer
能够实时监测你的代码更改,并在保存文件时自动重新加载页面,以便你能够立即看到更改的效果。 - 热模块替换(HMR):
devServer
支持热模块替换功能,使得在不刷新整个页面的情况下,更新已加载的模块。 - 自动打开浏览器:
devServer
可以自动打开浏览器并显示你的项目页面,方便你直接进行开发和调试。 - 提供开发工具:
devServer
提供了一些开发工具,如控制台输出、错误提示、模块热替换等,帮助你在开发过程中更好地调试和监控项目的状态。
如何启动服务 webpack-dev-server
1、安装webpack-dev-server命令
js
npm install -D webpack-dev-server
yarn add webpack-dev-server -D
2、package.json文件下scripts配置如下代码
js
// 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"
}
}
3、使用命令(npm start or npm run dev)启动你的项目服务
js
devServer: {
// 配置webpack-dev-server 开发使用
port: 8081, // 配置web服务器端口,端口不能相同
open: true, // 启动成功之后自动打开浏览器
progress: true, // 进度
contentBase: "./dist", // 指定web服务的根目录,服务一打开就直接去dist文件夹下找index.html文件,有就直接打开
},
devServer 中的配置项很多,下面介绍一下常用的,想知道完整的配置,前往官网查看
devServer
devServer.https (使用 HTTPS 提供服务)
默认情况下,开发服务器将通过 HTTP 提供服务,也可以选择使用 HTTPS 提供服务
js
module.exports = {
//...
devServer: {
https: true,
},
};
devServer.port(指定监听请求的端口号)
js
module.exports = {
//...
devServer: {
port: 8080,
},
};
port
配置项不能设置为 null
或者空字符串,要想自动使用一个可用端口请使用 port: 'auto'
js
module.exports = {
//...
devServer: {
port: 'auto',
},
};
devServer.open (打开你的默认浏览器)
告诉 dev-server 在服务器已经启动后打开浏览器。设置其为 true
以打开你的默认浏览器。
js
module.exports = {
//...
devServer: {
open: true,
},
};
在浏览器中打开指定页面
js
module.exports = {
//...
devServer: {
open: ['/my-page'],
},
};
在浏览器中打开多个指定页面
js
module.exports = {
//...
devServer: {
open: ['/my-page', '/another-page'],
},
};
devServer.proxy(设置代理服务器的配置)
代理服务器是一种中间服务器,它接收客户端的请求,并将请求转发到实际的目标服务器。在开发环境中,使用代理服务器可以解决跨域问题和模拟不同环境
。
js
module.exports = {
//...
devServer: {
proxy: {
'/api': {
target: 'https://other-server.example.com',
// 指定目标服务器的地址,即请求应该被转发到的实际服务器
ws: false,
// 指定是否启用 WebSocket 支持
changeOrigin: true
//是否启用 CORS(跨域资源共享)支持,如果设置为 `true`,则在转发请求时会添加 `Origin` 请求头,以解决跨域问题。
},
},
},
};
也可以将配置文件写在.env文件中,便于管理、复用
js
module.exports = {
//...
devServer: {
proxy: {
[process.env.VUE_APP_AIFORCE_PATH]: {
target: process.env.VUE_APP_BASIC_DATA_SERVICE_API_URL, // 代理的目标地址
changOrigin: true // 支持跨域
},
[process.env.VUE_APP_WS_TEXT_PATH]: {
target: process.env.VUE_APP_BASIC_WS_SERVICE_API_URL,
ws: true, // 是否启用websockets
changOrigin: true
},
},
},
};
devServer.overlay(当出现编译器错误或警告时,在浏览器中显示)
js
module.exports = {
//...
devServer: {
// 当出现编译器错误或警告时,在浏览器中显示
overlay: {
warnings: true, // 显示警告
errors: true // 显示错误
},
},
};
devServer.headers (为所有响应添加 headers)
js
module.exports = {
devServer: {
// 对象写法
headers: {
'X-Custom': 'foo',
'Y-Custom': 'bar'
},
// 数组写法
headers: [
{
key: 'X-Custom',
value: 'foo',
},
{
key: 'Y-Custom',
value: 'bar',
},
],
// 函数写法
headers: () => {
return { 'X-Bar': ['key1=value1', 'key2=value2'] };
},
},
};
devServer.client(指定开发服务器与浏览器之间的通信方式)
js
module.exports = {
//...
devServer: {
client: {
logging: 'info', // 指定开发服务器的日志级别。可以是 `silent`、`error`、`warn`、`info` 或 `verbose`。默认为 `info`
progress:true, // 是否显示进度条
overlay: { // 显示错误信息
errors: true,
warnings: false,
},
publicPath: '/', //指定静态资源的公共路径
socketPath: 'auto', // 指定使用 WebSocket 协议时的 socket 路径。默认为 `auto`,表示自动选择合适的路径。
host:'localhost', // 指定开发服务器的主机名。默认为 `localhost`。
},
},
};
devServer.hot(是否开启热更新)
js
module.exports = {
//...
devServer: {
hot: true, // 开启热更新
},
};
在项目中运用
js
// vue.config.js
const path = require('path');
const webpack = require('webpack');
let HtmlWebpackPlugin = require("html-webpack-plugin");
const styleLoader = { loader: 'style-loader' };
function resolve(dir) {
return path.join(__dirname, dir);
}
const isBuildProduction = process.env.NODE_ENV === 'production';
module.exports = {
// 是否将包,进行映射
productionSourceMap: false,
// 资源在浏览器中的访问路径
publicPath: '/', // 指定构建后的资源的根路径,默认为"/"
outputDir: 'dist', // 指定构建后的资源的输出目录,默认为"dist"
mode: 'development', // 开发模式和生产环境,都有不同的内置优化
configureWebpack: {
publicPath: isBuildProduction ? "/" : "./",
// 控制是否生成 映射文件
devtool: isBuildProduction
? 'nosources-source-map'
: 'eval-cheap-module-source-map',
// 插件,对打包文件做处理
plugins: [
new HtmlWebpackPlugin(),
new webpack.ContextReplacementPlugin( //内置插件
/moment[\\/]locale$/,
/^\.\/(zh-cn)$/
)
],
// 排除第三方依赖
externals: /^(jquery|$)$/i,
// 优化
optimization: {
splitChunks: { // 控制代码分割
// 有效值为 `all`,`async` 和 `initial`
chunks: 'all', // 对所有的块进行分割
name: true, // 表示为每个块生成一个唯一的名称
minSize: 1, // 表示最小分割块的大小为 1 字节
minChunks: 1, // 表示如果一个块被多个模块引用,它将被分割
cacheGroups: { // 定义了多个缓存组,用于根据不同的规则对代码进行分割
default: false, // 禁用任何默认缓存组
defaultVendors: { // 缓存组适用于 node_modules 目录下的所有模块
name: 'common', // 缓存组的名称,用于在缓存中标识
chunks: 'initial', // initial 表示应用程序的入口模块
minChunks: 1, // 最小的 chunk 数量,只有在满足最小 chunk 数量时才会创建缓存
enforce: true, // 是否强制使用缓存。如果为 `true`,则在满足条件时必须使用缓存,否则将抛出错误。
test: /node_modules/, // 一个正则表达式,用于匹配要缓存的模块
reuseExistingChunk: true // - - 是否重用现有的 chunk。如果为 `true`,则如果已经存在匹配的缓存,则直接使用,而不是创建新的缓存。
},
vuePhotoPreviewVenodr: {
test: /(vue-photo-preview)/, // 表示匹配 `vue-photo-preview` 模块
priority: 103, // 缓存的优先级。优先级越高,越先被使用。
name: 'vuePhotoPreviewVenodr',
chunks: 'async' // `async`表示适用于异步加载的 chunks
},
'async-commons': { // 这个缓存组适用于其他异步加载的包
// 其余异步加载包
chunks: 'async',
minChunks: 2,
name: 'async-commons',
priority: 90
},
commons: { // 这个缓存组适用于其他同步加载的包
// 其余同步加载包
chunks: 'all',
minChunks: 2,
name: 'commons',
priority: 80
},
styles: { // 这个缓存组适用于所有的样式文件
name: 'common',
chunks: 'initial',
minChunks: 1,
test: /\.(css|less|scss|stylus)$/,
enforce: true,
priority: 50
}
}
}
}
},
chainWebpack: (config) => {
// 别名,使用@web,就是在使用'./src'地址
config.resolve.alias.set('@web', path.resolve('./src')),
// 删除 prefetch 插件
config.plugins.delete('prefetch')
// 清空名为 `app` 的入口点
config.entry('app').clear();
// 向名为 `app` 的入口点添加一个新的入口文件
config.entry('app').add('./packages/index.js');
// 使用 babel-loader 加载器,转换 ts 代码
config.module.rule('ts').test(/\.ts$/).use('babel-loader').loader('babel-loader').end();
},
// 配置webpack-dev-server
devServer: {
port: 8083, //配置web服务端口
open: true, //自动打开浏览器
progress: true, //进度
contentBase: './dist', //指定web服务器的根目录
overlay: { // 当出现编译器错误或警告时,在浏览器中显示
warnings: true, // 显示警告
errors: true // 显示错误
},
// 设置代理服务器的配置
proxy: {
[process.env.VUE_APP_AIFORCE_PATH]: {
// 指定目标服务器的地址,即请求应该被转发到的实际服务器
target: process.env.VUE_APP_BASIC_DATA_SERVICE_API_URL,
changOrigin: true // 是否支持跨域
},
[process.env.VUE_APP_WS_TEXT_PATH]: {
target: process.env.VUE_APP_BASIC_WS_SERVICE_API_URL, // 测试服
ws: true, // 是否启用websockets
changOrigin: true
},
},
// 请求头
headers: {
'X-Custom-Bar': 'bar',
'X-Custom-Foo': 'foo',
}
},
css: {
loaderOptions: {
sass: {
// 覆盖原来的 loader user 配置
// 全局引入 scss,便于引用函数和变量
data: '@import "~@main/styles/variable.scss"; @import "~@main/styles/cloud-variable.scss";',
// 生产环境不需要 styleLoader
use: (isBuildProduction ? [] : [styleLoader]).concat([
'css-loader',
'postcss-loader', // `postcss-loader` 用于处理 PostCSS 转换
{
loader: 'sass-loader',
options: {
implementation: require('sass') // 用于指定要使用的 Sass 实现库
}
}
]),
postcss: false // 默认添加的 postcss 位置不对, 应当按上面列出的顺序
}
},
sourceMap: false // 控制是否生成 CSS 文件的源映射
},
}
多环境配置
js
const env = process.env.NODE_ENV;//当前环境
if (env === 'production') {
// 生产环境
module.exports = {} // 可以在这里写入生产环境的配置,也可以写在其他文件,在这里引入
}else if (env === 'test') {
// 测试环境
console.log("----------测试环境----------");
} else {
// 开发环境
console.log("----------开发环境----------");
}
配置项多而乱,根据要实现的需求,使用对应的配置项,完成配置,实现效果。