文章目录

  • webpack专辑
  • webpack Dev Server
    • 配置选项
      • 1.静态资源访问
      • 2.Proxy 代理
    • 小结

webpack专辑

  • 如何使用webpack实现模块化打包?
  • 如何通过Loader实现特殊资源加载?实例加载css文件
  • 开发一个Loader
  • 插件机制横向扩展webpack的构建能力 三个插件的使用实例
  • 开发一个清除文件注释的插件 (学习插件原理)

webpack Dev Server

webpack-dev-server 是 Webpack 官方推出的一款开发工具,根据它的名字我们就应该知道,它提供了一个开发服务器,并且将自动编译和自动刷新浏览器等一系列对开发友好的功能全部集成在了一起。

Webpack 官方推出 webpack-dev-server 这款工具的初衷,就是为了提高开发者日常的开发效率,而且它是一个高度集成的工具,使用起来十分的方便

webpack-dev-server 同样也是一个独立的 npm 模块,所以我们需要通过 npm 将 webpack-dev-server 作为项目的开发依赖安装。安装完成过后,这个模块为我们提供了一个叫作 webpack-dev-server 的 CLI 程序,我们同样可以直接通过 npx 直接去运行这个 CLI,或者把它定义到 npm scripts 中,具体操作如下:

# 安装 webpack-dev-server
$ npm install webpack-dev-server --save-dev
# 运行 webpack-dev-server
$ npx webpack-dev-server

安装webpack-dev-server:

运行 webpack-dev-server 这个命令时,它内部会启动一个 HTTP Server,为打包的结果提供静态文件服务,并且自动使用 Webpack 打包我们的应用,然后监听源代码的变化,一旦文件发生变化,它会立即重新打包,大致流程如下:


不过这里需要注意的是,webpack-dev-server 为了提高工作速率,它并没有将打包结果写入到磁盘中,而是暂时存放在内存中,内部的 HTTP Server 也是从内存中读取这些文件的。这样一来,就会减少很多不必要的磁盘读写操作,大大提高了整体的构建效率。


我们还可以为 webpack-dev-server 命令传入一个 --open 的参数,用于自动唤起浏览器打开我们的应用。打开浏览器过后,此时如果你有两块屏幕,就可以把浏览器放到另外一块屏幕上,然后体验一边编码,一边即时预览的开发环境了。

配置选项

Webpack 配置对象中可以有一个叫作 devServer 的属性,专门用来为 webpack-dev-server 提供配置,具体如下:

// ./webpack.config.js
const path = require('path')module.exports = {// ...devServer: {contentBase: path.join(__dirname, 'dist'),compress: true,port: 9000// ...// 详细配置文档:https://webpack.js.org/configuration/dev-server/}
}

具体有哪些配置我们就不在这里一一介绍了,你可以在它的官网中找到相对应的说明文档。

####接下来我们来看几个 webpack-dev-server 的常用功能。

1.静态资源访问

webpack-dev-server 默认会将构建结果和输出文件全部作为开发服务器的资源文件,也就是说,只要通过 Webpack 打包能够输出的文件都可以直接被访问到。但是如果你还有一些没有参与打包的静态文件也需要作为开发服务器的资源被访问,那你就需要额外通过配置“告诉” webpack-dev-server。

具体的方法就是在 webpack-dev-server 的配置对象中添加一个对应的配置。我们回到配置文件中,找到 devServer 属性,它的类型是一个对象,我们可以通过这个 devServer 对象的 contentBase 属性指定额外的静态资源路径。这个 contentBase 属性可以是一个字符串或者数组,也就是说你可以配置一个或者多个路径。具体配置如下:

// ./webpack.config.js
module.exports = {// ...devServer: {contentBase: 'public'}
}

我们这里将这个路径设置为项目中的 public 目录。可能有人会有疑问,之前我们在使用插件的时候已经将这个目录通过 copy-webpack-plugin 输出到了输出目录,按照刚刚的说法,所有输出的文件都可以直接被 serve,也就是能直接访问到,按道理应该不需要再作为开发服务器的静态资源路径了。

确实是这样的,而且如果你能想到这一点,也就证明你真正理解了webpack-dev-server 的文件加载规则。

但是在实际使用 Webpack 时,我们一般都会把 copy-webpack-plugin 这种插件留在上线前的那一次打包中使用,而开发过程中一般不会用它。因为在开发过程中,我们会频繁重复执行打包任务,假设这个目录下需要拷贝的文件比较多,如果每次都需要执行这个插件,那打包过程开销就会比较大,每次构建的速度也就自然会降低。

至于如何实现某些插件只在生产模式打包时使用,是额外的话题,所以具体的操作方式会在 10 课时中详细介绍。这里我们先移除 CopyWebpackPlugin,确保这里的打包不会输出 public 目录中的静态资源文件,然后回到命令行再次执行 webpack-dev-server。

启动过后,我们打开浏览器,这里我们访问的页面文件和 bundle.js 文件均来自于打包结果。我们再尝试访问 favicon.ico,因为这个文件已经没有参与打包了,所以这个文件必然来源于 contentBase 中配置的目录了。

2.Proxy 代理

由于 webpack-dev-server 是一个本地开发服务器,所以我们的应用在开发阶段是独立运行在 localhost 的一个端口上,而后端服务又是运行在另外一个地址上。但是最终上线过后,我们的应用一般又会和后端服务部署到同源地址下。

那这样就会出现一个非常常见的问题:在实际生产环境中能够直接访问的 API,回到我们的开发环境后,再次访问这些 API 就会产生跨域请求问题。

可能有人会说,我们可以用跨域资源共享(CORS)解决这个问题。确实如此,如果我们请求的后端 API 支持 CORS,那这个问题就不成立了。但是并不是每种情况下服务端的 API 都支持 CORS。如果前后端应用是同源部署,也就是协议 / 域名 / 端口一致,那这种情况下,根本没必要开启 CORS,所以跨域请求的问题仍然是不可避免的。

那解决这种开发阶段跨域请求问题最好的办法,就是在开发服务器中配置一个后端 API 的代理服务,也就是把后端接口服务代理到本地的开发服务地址。

webpack-dev-server 就支持直接通过配置的方式,添加代理服务。接下来,我们来看一下它的具体用法。

这里我们假定 GitHub 的 API 就是我们应用的后端服务,那我们的目标就是将 GitHub API 代理到本地开发服务器中。

我们可以先在浏览器中尝试访问其中的一个接口,具体结果如下图:

GitHub API 的 Endpoint 都是在根目录下,也就是说不同的 Endpoint 只是 URL 中的路径部分不同,例如 https://api.github.com/users 和 https://api.github.com/events。

知道 API 地址的规则过后,我们回到配置文件中,在 devServer 配置属性中添加一个 proxy 属性,这个属性值需要是一个对象,对象中的每个属性就是一个代理规则配置。

属性的名称是需要被代理的请求路径前缀,一般为了辨别,我都会设置为 /api。值是所对应的代理规则配置,我们将代理目标地址设置为 https://api.github.com,具体代码如下:

// ./webpack.config.js
module.exports = {// ...devServer: {proxy: {'/api': {target: 'https://api.github.com'}}}
}

那此时我们请求 http://localhost:8080/api/users ,就相当于请求了 https://api.github.com/api/users。

而我们真正希望请求的地址是 https://api.github.com/users,所以对于代理路径开头的 /api 我们要重写掉。我们可以添加一个 pathRewrite 属性来实现代理路径重写,重写规则就是把路径中开头的 /api 替换为空,pathRewrite 最终会以正则的方式来替换请求路径。

// ./webpack.config.js
module.exports = {// ...devServer: {proxy: {'/api': {target: 'https://api.github.com',pathRewrite: {'^/api': '' // 替换掉代理地址中的 /api}}}}
}

这样我们代理的地址就正常了。


除此之外,我们还需设置一个 changeOrigin 属性为 true。这是因为默认代理服务器会以我们实际在浏览器中请求的主机名,也就是 localhost:8080 作为代理请求中的主机名。而一般服务器需要根据请求的主机名判断是哪个网站的请求,那 localhost:8080 这个主机名,对于 GitHub 的服务器来说,肯定无法正常请求,所以需要修改。

将代理规则配置的 changeOrigin 属性设置为 true,就会以实际代理请求地址中的主机名去请求,也就是我们正常请求这个地址的主机名是什么,实际请求 GitHub 时就会设置成什么。

// ./webpack.config.js
module.exports = {// ...devServer: {proxy: {'/api': {target: 'https://api.github.com',pathRewrite: {'^/api': '' // 替换掉代理地址中的 /api},changeOrigin: true // 确保请求 GitHub 的主机名就是:api.github.com}}}
}

完成以后,打开命令行终端,运行 webpack-dev-server。然后打开浏览器,这里我们直接尝试请求 http://localhost:8080/api/users,得到的就是 GitHub 的用户数据。 因为这个地址已经被代理到了 GitHub 的用户数据接口。


此时,我们就可以回到代码中使用代理后的本地同源地址去请求后端接口,而不必担心出现跨域问题了。

小结

今天跟你分享了一个叫作 webpack-dev-server 的工具,它是 Webpack 周边工具中最重要的一个,作用就是提升开发者的开发体验,帮助开发者更快更高效的完成开发工作。

webpack-dev-server实现静态资源加载和proxy代理相关推荐

  1. 【Bug档案01】Spring Boot的控制器+thymeleaf模板 -使用中出现静态资源加载路径不当的问题 -解决时间:3h

    [Bug档案01]Spring Boot的控制器+thymeleaf模板 -使用中出现静态资源加载路径不当的问题 -解决时间:3h 参考文章: (1)[Bug档案01]Spring Boot的控制器+ ...

  2. SpringMVC配置静态资源加载, 中文乱码处理,注解驱动

    常规配置(Controller加载控制) SpringMVC的处理器对应的bean必须按照规范格式开发,未避免加入无效的bean可通过bean加载过滤器进行包含设定或排除设定,表现层bean标注通常设 ...

  3. Spring MVC中静态资源加载

    问题:MVC 静态资源加载,包括 js.css.image加载不出来 由于web.xml中dispatcherServlet中 url-pattern 使用 / 拦截所有访问,而导致静态资源也交给了D ...

  4. 美团金融扫码付静态资源加载优化实践

    原文链接:https://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651747208&idx=1&sn=b9fc54300 ...

  5. Flask-模板-静态资源加载-jsonify

    文章目录 1.模板 1.1 render_template 1.2 模板标签 1.3 模板继承 1.4 模板包含 1.5 模板过滤器 1.6 宏 2. 静态资源加载 3. jsonify() 1.模板 ...

  6. html src加载外部静态资源,前端性能优化2:静态资源加载与优化

    css和js的装载与执行-HTML 页面加载渲染的过程 一个网站在浏览器端是如何进行渲染的呢? 流程示意图.png HTML渲染过程的一些特点 顺序执行.并发加载(单个域名的并发数量是有限的,所以多个 ...

  7. Vue踩坑之二级路由下静态资源加载失败

    在使用vue开发过程中意外发现 , 当我的路由加到二级时我的页面背景突然没了? 这是怎么回事呢? 让我们先来复现一下问题吧 起初我的登陆页面的路由是这样子的 我的背景图片是在外部的一个css中写着的 ...

  8. 前端静态资源加载顺序

    一.js放在head中会立即执行,阻塞后续的资源下载与执行.因为js有可能会修改dom,如果不阻塞后续的资源下载,dom的操作顺序不可控. 正常的网页加载流程是这样的. 浏览器一边下载HTML网页,一 ...

  9. SpringBoot项目中静态资源加载失败,那可能是自定义配置类继承了WebMvcConfigurationSupport这个类

    1.跟着视频课学SpringBoot,自己的一个html登录页面就是在浏览器中渲染不出来效果,很郁闷.我的项目结构如下: 2.想要打开login.html页面,该页面用到了静态资源中的css文件及sv ...

最新文章

  1. Dalvik虚拟机与java虚拟机的区别
  2. 第十二周-学习进度条
  3. Marine Life Science Technology(海洋生命科学与技术)被SCIE收录
  4. java读avro的流_0016-Avro序列化反序列化和Spark读取Avro数据
  5. 初识vue 2.0(2):路由与组件
  6. phpstorm 2017.1激活
  7. Java并发编程的艺术,解读并发编程的优缺点
  8. C++ 高级篇(五)—— 预处理指令
  9. streamset 数据合并_StreamSet之数据流从JDBC到Hbase
  10. php.ini icuuc54.dll,icuuc54.dll下载|
  11. Windows Serer2003域升级到Windows Server2008R2域
  12. 9 月,有远见的程序员,都关注了这个人!
  13. lnmp编译安装mysql_LNMP一键包不安装mysql | 厘米天空
  14. Educational Codeforces Round 51 (Rated for Div. 2) The Shortest Statement
  15. 快速下载【百度文库】文档
  16. 【亲测有效】无法定位链接器!请检查 tools\link.ini 中的配置是否正确的解决方案...
  17. 使用函数式编程优化代码
  18. 目标跟踪VOT2016的配置
  19. C6能比C8快多少(Altera的FPGA速度等级)
  20. 在树莓派(Linux)上使用FTDI的usb转串口芯片ft232两种驱动方式(VCP和D2xx)

热门文章

  1. win7备份工具_Win7/10系统如何一键还原系统?一键备份还原系统方法图文教程
  2. Eclipse使用Maven
  3. 单片机c语言字符型数据类型,单片机C语言数据类型
  4. 虚拟机ubuntu连不上网
  5. VM下的ubuntu连不上网的解决办法
  6. 上海交大软件学院课件 NPM、PYPI、DockerHub 备份
  7. Ganymed SSH-2
  8. 软件评测师--第13小时 标准符合性测试
  9. 软件项目管理-第五章软件项目任务分解
  10. 自己创建百度百科老是不通过的原因,怎么才能创建词条成功