详解vue-cli脚手架build目录中的dev-server.js配置文件


Posted in Javascript onNovember 24, 2017

本文系统讲解vue-cli脚手架build目录中的dev-server.js配置文件

1.这个配置文件是命令npm run dev 和 npm run start 的入口配置文件,主要用于开发环境

2.由于这是一个系统的配置文件,将涉及很多的模块和插件,所以这部分内容我将分多个文章讲解,请关注我博客的其他文章

3.关于注释 •当涉及到较复杂的解释我将通过标识的方式(如(1))将解释写到单独的注释模块,请自行查看

4.上代码

// 导入check-versions.js文件,并且执行导入的函数,用来确定当前环境node和npm版本是否符合要求
// 关于check-versions请查看我博客check-versions的相关文章
require('./check-versions')()
// 导入config目录下的index.js配置文件,此配置文件中定义了生产和开发环境中所要用到的一些参数
// 关于index.js的文件解释请看我博客的index.js的相关文章
var config = require('../config')
// 下面表示如果如果没有定义全局变量NODE_ENV,则将NODE_ENV设置为"development"
if (!process.env.NODE_ENV) {
  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
// opn插件是用来打开特定终端的,此文件用来在默认浏览器中打开链接 opn(url)
var opn = require('opn')
// nodejs路径模块
var path = require('path')
// nodejs开发框架express,用来简化操作,有兴趣可以自行去了解
var express = require('express')
// 引入webpack模块,用来使用webpack内置插件
var webpack = require('webpack')
// 引入http-proxy-middleware插件,此插件是用来代理请求的只能用于开发环境,目的主要是解决跨域请求后台api
var proxyMiddleware = require('http-proxy-middleware')
// 下面的意思是指,如果不是testing环境就引入webpack.dev.conf.js配置文件
// 关于webpack.dev.conf.js配置文件请关注我的相关文章,建议现在就去看,否则后面看着吃力
var webpackConfig = process.env.NODE_ENV === 'testing' ?
  require('./webpack.prod.conf') :
  require('./webpack.dev.conf')

// default port where dev server listens for incoming traffic
// 下面是webpack-dev-server 监听的端口号,因为没有设置process.env.PORT,所以下面监听的就是config.dev.port即8080
var port = process.env.PORT || config.dev.port
  // automatically open browser, if not set will be false
// 下面是true,至于为啥,本来就是true还要加!!两个感叹号,估计是vue作者装了个逼吧
var autoOpenBrowser = !!config.dev.autoOpenBrowser
  // Define HTTP proxies to your custom API backend
  // https://github.com/chimurai/http-proxy-middleware
// 下面是解决开发环境跨域问题的插件,我在config目录index.js文章中有介绍,自行查看
var proxyTable = config.dev.proxyTable
// 下面是创建node.js的express开发框架的实例,别问我为什么这样,自己看node.js去吧
var app = express()
// 把配置参数传递到webpack方法中,返回一个编译对象,这个编译对象上面有很多属性,自己去看吧,主要是用到里面的状态函数 如compilation,compile,after-emit这类的
var compiler = webpack(webpackConfig)
// 下面是webpack-dev-middleware和webpack-hot-middleware两兄弟,这两个是黄金组合
// 而vue作者用这两个插件也是用的最基本的形式,详情看(1) (2)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  publicPath: webpackConfig.output.publicPath,
  quiet: true // 使用friendly-errors-webpack-plugin插件这个必须设置为true,具体看我的wepback-dev-config.js
})

var hotMiddleware = require('webpack-hot-middleware')(compiler, {
    log: () => {} // 使用friendly-errors-webpack-plugin插件这个必须设置为true,具体看我的wepback-dev-config.js
  })
  // force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function(compilation) {
  // webpack任何一个插件都plugin这个方法,里面可以传递钩子函数,用来在插件各个阶段做特殊处理,钩子函数种类很多
  compilation.plugin('html-webpack-plugin-after-emit', function(data, cb) {
    // 当插件html-webpack-plugin产出完成之后,强制刷新浏览器
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})

// proxy api requests
Object.keys(proxyTable).forEach(function(context) {
  // 下面是代理表的处理方法,看看就行了,几乎用不上,除非你是全栈,不用webpack-dev-server,使用后台语言做服务器
  var options = proxyTable[context]
  if (typeof options === 'string') {
    options = { target: options }
  }
  app.use(proxyMiddleware(options.filter || context, options))
})

// handle fallback for HTML5 history API
// 这个插件是用来解决单页面应用,点击刷新按钮和通过其他search值定位页面的404错误
// 详情请看(3)
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
// app.use是在响应请求之前执行的,用来指定静态路径,挂载静态资源
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)

// serve pure static assets
// 下面的staticPath是 static ,path.posix.join其他配置文件中我已经介绍了,这里不再赘述
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// 挂载静态资源,下面的方法是用虚拟目录来访问资源,staticPath就是虚拟目录路径,其实不管设不设置都是static
app.use(staticPath, express.static('./static'))
// 下面结果就是 'http://localhost:8080'
var uri = 'http://localhost:' + port

// 下面是es6的promise规范,用来处理嵌套请求的
var _resolve
var readyPromise = new Promise(resolve => {
  _resolve = resolve // resolve是一个回调函数专门用来传递成功请求的数据
})
// 下面是加载动画
console.log('> Starting dev server...')
// waitUntilValid是webpack-dev-middleware实例的方法,在编译成功之后调用
devMiddleware.waitUntilValid(() => {
  console.log('> Listening at ' + uri + '\n')
    // when env is testing, don't need open it
    // 测试环境不打开浏览器
  if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
    opn(uri)
  }
  _resolve() // 这里没有传递数据,这只是在模拟
})
// node.js监听端口
var server = app.listen(port)
// 这个导出对象是用来对外提供操作服务器和接受数据的接口,vue作者可谓考虑颇深啊
module.exports = {
  ready: readyPromise, // promise实例,可以通过readyPromise.then收到数据
  close: () => {
    server.close() // 关闭服务器
  }
}

解释

(1)webpack-dev-middleware插件

这个插件只能用于开发环境,下面是这个插件的解释

这是一个简洁的webpack包装中间件,这个插件做这个主要为文件做一件事情,就是当文件修改后提交到webpack服务器,然后处理这些修改后的文件

这个插件有一下几个优点

第一,所有的文件都是写在disk上,文件的处理在内存中进行

第二,如果文件在watch模式下被改动,这个中间件将不会为这些老的bundle服务了,如果这些老的bundle上有文件改动, 这个中间件将不会发送请求,而是等到当前编译结束,当前最新的文件有改动,才会发送请求,所以你不需要手动刷新了

第三,我会在以后的版本中优化

总结,这个中间件是webpack-dev-server的核心,实现修改文件,webapack自动刷新的功能

安装 npm install webpack-deb-middleware --save-dev

使用方法如下,下面的使用方法也是webpack-dev-server实现的代码

var webpackMiddleware = require("webpack-deb-middleware");
app.use(webpackMiddleware(webpack({obj1}),{obj2}))

app.use是express的方法,用来设置静态路径

上面的obj1是webpack配置对象,使用webpack方法转换成compiler编译对象,obj2配置的是更新文件打包后的配置,使用

webpackMiddleware处理之后,就返回一个静态路径,方便获取文件关于obj2的配置项,可以自行查阅,必须要添加publicPath

说到这里,我就不卖关子了,简言之我们的静态服务器是node.js,现在文件修改了,webpack-dev-middleware将修改的文件编译后,告诉nodejs服务器哪些文件修改了并且把最新的文件上传到静态服务器,够清楚了吧

(2)webpack-hot-middleware插件

这个插件是用来将webpack-dev-middleware编译更新后的文件通知浏览器,并且告诉浏览器如何更新文件,从而实现 Webpack hot reloading

将这两个插件配合起来使用你就可以不需要webpack-dev-sever,即可以自己实现hot-replacement热替换功能,webpack-hot-middleware插件通知浏览器更新文件大致是通过一个json对象实现的,具体实现机制这里不多说了,下面来看具体用法

安装 npm install webpack-hot-middleware --save-dev

在使用了webpack-dev-middleware之后,在添加如下代码即可

app.use(require("webpack-hot-middleware")(compiler));

(3)connect-history-api-fallback插件

因为在开发单页面应用时,总的来说项目就一个页面,如果通过点击刷新按钮并且此时链接指的不是主页的地址,就会404;或者我通过其他的链接比如 /login.html 但是并没有login.html就会报错,而这个插件的作用就是当有不正当的操作导致404的情况,就把页面定位到默认的index.html使用起来也比较简单,记住这样用就可以了

安装 npm install --save connect-history-api-fallback

使用

var history = require('connect-history-api-fallback');
  var express = require('express');
  var app = express();
  app.use(history());

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript在一段文字中的光标处插入其他文字
Aug 26 Javascript
input 高级限制级用法
Mar 26 Javascript
判断客户端浏览器是否安装了Flash插件的多种方法
Aug 11 Javascript
基于jquery的划词搜索实现(备忘)
Sep 14 Javascript
javascript中动态函数用法实例分析
May 14 Javascript
JavaScript使用DeviceOne开发实战(一) 配置和起步
Dec 01 Javascript
Jquery插件之Fancybox丰富的弹出层效果附源码下载
Dec 02 Javascript
AngularJS 使用$sce控制代码安全检查
Jan 05 Javascript
jQuery实现滚动鼠标放大缩小图片的方法(附demo源码下载)
Mar 05 Javascript
一个用jquery写的判断div滚动条到底部的方法【推荐】
Apr 29 Javascript
JavaScript实现自定义媒体播放器方法介绍
Jan 03 Javascript
关于layui 弹出层一闪而过就消失的解决方法
Sep 09 Javascript
javaScript和jQuery自动加载简单代码实现方法
Nov 24 #jQuery
Bootstrap modal只加载一次数据的解决办法(推荐)
Nov 24 #Javascript
浅谈vue-cli加载不到dev-server.js的解决办法
Nov 24 #Javascript
浅谈Angular文字折叠展开组件的原理分析
Nov 24 #Javascript
vue 文件目录结构详解
Nov 24 #Javascript
获取本机IP地址的实例(JavaScript / Node.js)
Nov 24 #Javascript
js判断数组是否包含某个字符串变量的实例
Nov 24 #Javascript
You might like
PHP session会话的安全性分析
2011/09/08 PHP
PHP中的strtr函数使用介绍(str_replace)
2011/10/20 PHP
PHP mb_convert_encoding文字编码的转换函数介绍
2011/11/10 PHP
PHP程序员基本要求和必备技能
2014/05/09 PHP
PHP的pcntl多进程用法实例
2015/03/19 PHP
php基于dom实现的图书xml格式数据示例
2017/02/03 PHP
解析JavaScript中的不可见数据类型
2013/12/02 Javascript
jQuery验证插件 Validate详解
2014/11/20 Javascript
深入浅析JavaScript中对事件的三种监听方式
2015/09/29 Javascript
原生js实现可爱糖果数字时间特效
2016/12/30 Javascript
react-native组件中NavigatorIOS和ListView结合使用的方法
2017/09/30 Javascript
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
ios设备中angularjs无法改变页面title的解决方法
2018/09/13 Javascript
解决angular2在双向数据绑定时[(ngModel)]无法使用的问题
2018/09/13 Javascript
详解Vue项目在其他电脑npm run dev运行报错的解决方法
2018/10/29 Javascript
JavaScript ES2019中的8个新特性详解
2019/02/20 Javascript
JavaScript中的null和undefined用法解析
2019/09/30 Javascript
[41:13]完美世界DOTA2联赛PWL S2 Forest vs Rebirth 第一场 11.20
2020/11/20 DOTA
python中mechanize库的简单使用示例
2014/01/10 Python
跟老齐学Python之深入变量和引用对象
2014/09/24 Python
Python中文件操作简明介绍
2015/04/13 Python
从Python的源码来解析Python下的freeblock
2015/05/11 Python
Python中列表元素转为数字的方法分析
2016/06/14 Python
python实现单向链表详解
2018/02/08 Python
Python文本处理之按行处理大文件的方法
2018/04/09 Python
python中计算一个列表中连续相同的元素个数方法
2018/06/29 Python
Python格式化输出字符串方法小结【%与format】
2018/10/29 Python
Django-Rest-Framework 权限管理源码浅析(小结)
2018/11/12 Python
python基于C/S模式实现聊天室功能
2019/01/09 Python
python selenium自动化测试框架搭建的方法步骤
2020/06/14 Python
Python多线程thread及模块使用实例
2020/04/28 Python
详解Python设计模式之策略模式
2020/06/15 Python
MIXIT官网:俄罗斯最大的化妆品公司之一
2020/01/25 全球购物
2016年综治宣传月活动宣传标语口号
2016/03/16 职场文书
Elasticsearch 配置详解
2022/04/19 Java/Android
Android开发实现极为简单的QQ登录页面
2022/04/24 Java/Android