webpack中是如何让项目开发调试,变得更加高效的?

前面几篇文章,详细介绍过webpack的核心配置项,入口起点、出口文件加载器loader插件plugin,感兴趣的可以前往查看

项目开发,一般都是在本地起一个服务,进行代码的运行和调试。前面几篇文章介绍到了,webpack 对项目进行编译打包,方便在浏览器上运行。

那么问题来了,怎么样让打包好的项目文件,在浏览器上运行起来呢?

webpack中提供的开发环境工具 devServer,让打包的项目在浏览器上运行,通过配置devServer的属性,使开发过程更加高效地进行调试和测试

webpack-dev-server (简写: dev-server),用于快速开发应用程序。

devServer 的主要作用包括:

  1. 提供本地服务器:devServer 启动一个本地服务器,使得你可以在本地环境中访问和测试你的 Webpack 项目。
  2. 实时重新加载:devServer 能够实时监测你的代码更改,并在保存文件时自动重新加载页面,以便你能够立即看到更改的效果。
  3. 热模块替换(HMR):devServer 支持热模块替换功能,使得在不刷新整个页面的情况下,更新已加载的模块。
  4. 自动打开浏览器:devServer 可以自动打开浏览器并显示你的项目页面,方便你直接进行开发和调试。
  5. 提供开发工具: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("----------开发环境----------");
}

配置项多而乱,根据要实现的需求,使用对应的配置项,完成配置,实现效果。

相关推荐
mldong10 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60611 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角2 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi4 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒6 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端