由于最近在vue-cli生成的webpack模板项目的基础上写一个小东西,开发过程中需要改动到build和config里面一些相关的配置,所以刚好趁此机会将所有配置文件看一遍,理一理思路,也便于以后修改配置的时候不会“太折腾”。
本文主要分析开发(dev)和构建(build)两个过程涉及到的文件,故下面文件结构仅列出相应的内容。
1 ├─build 2 │ ├─build.js 3 │ ├─check-versions.js 4 │ ├─dev-client.js 5 │ ├─dev-server.js 6 │ ├─utils.js 7 │ ├─vue-loader.conf.js 8 │ ├─webpack.base.conf.js 9 │ ├─webpack.dev.conf.js 10 │ ├─webpack.prod.conf.js 11 │ └─webpack.test.conf.js 12 ├─config 13 │ ├─dev.env.js 14 │ ├─index.js 15 │ ├─prod.env.js 16 │ └─test.env.js 17 ├─... 18 └─package.json
二、指令分析
首先看package.json里面的scripts字段,
1 "scripts": { 2 "dev": "node build/dev-server.js", 3 "build": "node build/build.js", 4 "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", 5 "e2e": "node test/e2e/runner.js", 6 "test": "npm run unit && npm run e2e", 7 "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" 8 }
测试的东西先不看,直接看”dev”和”build”。运行”npm run dev”的时候执行的是build/dev-server.js文件,运行”npm run build”的时候执行的是build/build.js文件,我们可以从这两个文件开始进行代码阅读分析。
三、build文件夹分析
build/dev-server.js
首先来看执行”npm run dev”时候最先执行的build/dev-server.js文件。该文件主要完成下面几件事情:
- 检查node和npm的版本
- 引入相关插件和配置
- 创建express服务器和webpack编译器
- 配置开发中间件(webpack-dev-middleware)和热重载中间件(webpack-hot-middleware)
- 挂载代理服务和中间件
- 配置静态资源
- 启动服务器监听特定端口(8080)
- 自动打开浏览器并打开特定网址(localhost:8080)
说明: express服务器提供静态文件服务,不过它还使用了http-proxy-middleware,一个http请求代理的中间件。前端开发过程中需要使用到后台的API的话,可以通过配置proxyTable来将相应的后台请求代理到专用的API服务器。
详情请看代码注释:
1 // 检查NodeJS和npm的版本 2 require('./check-versions')() 3 4 // 获取配置 5 var config = require('../config') 6 // 如果Node的环境变量中没有设置当前的环境(NODE_ENV),则使用config中的配置作为当前的环境 7 if (!process.env.NODE_ENV) { 8 process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 9 } 10 11 // 一个可以调用默认软件打开网址、图片、文件等内容的插件 12 // 这里用它来调用默认浏览器打开dev-server监听的端口,例如:localhost:8080 13 var opn = require('opn') 14 var path = require('path') 15 var express = require('express') 16 var webpack = require('webpack') 17 18 // 一个express中间件,用于将http请求代理到其他服务器 19 // 例:localhost:8080/api/xxx --> localhost:3000/api/xxx 20 // 这里使用该插件可以将前端开发中涉及到的请求代理到API服务器上,方便与服务器对接 21 var proxyMiddleware = require('http-proxy-middleware') 22 23 // 根据 Node 环境来引入相应的 webpack 配置 24 var webpackConfig = process.env.NODE_ENV === 'testing' 25 ? require('./webpack.prod.conf') 26 : require('./webpack.dev.conf') 27 28 // dev-server 监听的端口,默认为config.dev.port设置的端口,即8080 29 var port = process.env.PORT || config.dev.port 30 31 // 用于判断是否要自动打开浏览器的布尔变量,当配置文件中没有设置自动打开浏览器的时候其值为 false 32 var autoOpenBrowser = !!config.dev.autoOpenBrowser 33 34 // 定义 HTTP 代理表,代理到 API 服务器 35 var proxyTable = config.dev.proxyTable 36 37 // 创建1个 express 实例 38 var app = express() 39 40 // 根据webpack配置文件创建Compiler对象 41 var compiler = webpack(webpackConfig) 42 43 // webpack-dev-middleware使用compiler对象来对相应的文件进行编译和绑定 44 // 编译绑定后将得到的产物存放在内存中而没有写进磁盘 45 // 将这个中间件交给express使用之后即可访问这些编译后的产品文件 46 var devMiddleware = require('webpack-dev-middleware')(compiler, { 47 publicPath: webpackConfig.output.publicPath, 48 quiet: true 49 }) 50 51 // webpack-hot-middleware,用于实现热重载功能的中间件 52 var hotMiddleware = require('webpack-hot-middleware')(compiler, { 53 log: () => {} 54 }) 55 56 // 当html-webpack-plugin提交之后通过热重载中间件发布重载动作使得页面重载 57 compiler.plugin('compilation', function (compilation) { 58 compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 59 hotMiddleware.publish({ action: 'reload' }) 60 cb() 61 }) 62 }) 63 64 // 将 proxyTable 中的代理请求配置挂在到express服务器上 65 Object.keys(proxyTable).forEach(function (context) { 66 var options = proxyTable[context] 67 // 格式化options,例如将'www.example.com'变成{ target: 'www.example.com' } 68 if (typeof options === 'string') { 69 options = { target: options } 70 } 71 app.use(proxyMiddleware(options.filter || context, options)) 72 }) 73 74 // handle fallback for HTML5 history API 75 // 重定向不存在的URL,常用于SPA 76 app.use(require('connect-history-api-fallback')()) 77 78 // serve webpack bundle output 79 // 使用webpack开发中间件 80 // 即将webpack编译后输出到内存中的文件资源挂到express服务器上 81 app.use(devMiddleware) 82 83 // enable hot-reload and state-preserving 84 // compilation error display 85 // 将热重载中间件挂在到express服务器上 86 app.use(hotMiddleware) 87 88 // serve pure static assets 89 // 静态资源的路径 90 var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 91 92 // 将静态资源挂到express服务器上 93 app.use(staticPath, express.static('./static')) 94 95 // 应用的地址信息,例如:http://localhost:8080 96 var uri = 'http://localhost:' + port 97 98 // webpack开发中间件合法(valid)之后输出提示语到控制台,表明服务器已启动 99 devMiddleware.waitUntilValid(function () { 100 console.log('> Listening at ' + uri + '\n') 101 }) 102 103 // 启动express服务器并监听相应的端口(8080) 104 module.exports = app.listen(port, function (err) { 105 if (err) { 106 console.log(err) 107 return 108 } 109 110 // when env is testing, don't need open it 111 // 如果符合自动打开浏览器的条件,则通过opn插件调用系统默认浏览器打开对应的地址uri 112 if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 113 opn(uri) 114 } 115 })