相信vue使用者对vue-cli都不会陌生,甚至可以说,很熟悉了,但对其webpack的配置可能知之甚少吧。
过完年回来后,我接手了公司的新项目。新项目是一个spa。很自然,我就想到了vue-cli脚手架了,当时研究一下它的webpack配置。于是,就有了其他的内容。
今天这篇文章,是在原来的基础上,增加了一些新版本的内容,但实质上变化不大。
说明
此仓库为vue-cli webpack的配置分析,其实只是在源码中加上注释而已。大家查看详细分析,可以从后面提到的入口文件开始查看。
分析不包括check-versions.js文件,因为check-versions.js是检测npm和node版本,不涉及webpack,所以就没有对check-versions.js进行分析。同时,也不包括测试部分的代码,该分析只是针对开发和生产环境的webpack配置进行分析。
vue-cli 版本
2.8.1
入口
从package.json可以看到开发和生产环境的入口。
"scripts": { "dev": "node build/dev-server.js", "build": "node build/build.js" }
开发环境
开发环境的入口文件是 build/dev-server.js。
dev-server.js
该文件中,使用express作为后端框架,结合一些关于webpack的中间件,搭建了一个开发环境。
// 配置文件var config = require('../config')// 如果 Node 的环境无法判断当前是 dev / product 环境// 使用 config.dev.env.NODE_ENV 作为当前的环境if (!process.env.NODE_ENV) { process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)}// 可以强制打开浏览器并跳转到指定 url 的插件// https://github.com/sindresorhus/opnvar opn = require('opn')// node自带的文件路径工具var path = require('path')// express框架var express = require('express')var webpack = require('webpack')// 测试环境,使用的配置与生产环境的配置一样// 非测试环境,即为开发环境,因为此文件只有测试环境和开发环境使用var proxyMiddleware = require('http-proxy-middleware')var webpackConfig = process.env.NODE_ENV === 'testing'// 生产环境配置文件 ? require('./webpack.prod.conf') // 开发环境配置文件 : require('./webpack.dev.conf')// 端口号为命令行输入的PORT参数或者配置文件中的默认值var port = process.env.PORT || config.dev.port// 配置文件中 是否自动打开浏览器var autoOpenBrowser = !!config.dev.autoOpenBrowser// 配置文件中 http代理配置// https://github.com/chimurai/http-proxy-middlewarevar proxyTable = config.dev.proxyTable// 启动 express 服务var app = express()// 启动 webpack 编译var compiler = webpack(webpackConfig)// 可以将编译后的文件暂存到内存中的插件// https://github.com/webpack/webpack-dev-middlewarevar devMiddleware = require('webpack-dev-middleware')(compiler, { // 公共路径,与webpack的publicPath一样 publicPath: webpackConfig.output.publicPath, // 不打印 quiet: true})// Hot-reload 热重载插件// https://github.com/glenjamin/webpack-hot-middlewarevar hotMiddleware = require('webpack-hot-middleware')(compiler, { log: () => {}})// 当tml-webpack-plugin template更改之后,强制刷新浏览器compiler.plugin('compilation', function (compilation) { compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { hotMiddleware.publish({ action: 'reload' }) cb() })})// 将 proxyTable 中的请求配置挂在到启动的 express 服务上Object.keys(proxyTable).forEach(function (context) { var options = proxyTable[context] // 如果options的数据类型为string,则表示只设置了url, // 所以需要将url设置为对象中的 target的值 if (typeof options === 'string') { options = { target: options } } app.use(proxyMiddleware(options.filter || context, options))})// 使用 connect-history-api-fallback 匹配资源// 如果不匹配就可以重定向到指定地址// https://github.com/bripkens/connect-history-api-fallbackapp.use(require('connect-history-api-fallback')())// 将暂存到内存中的 webpack 编译后的文件挂在到 express 服务上app.use(devMiddleware)// 将 Hot-reload 挂在到 express 服务上app.use(hotMiddleware)// 拼接 static 文件夹的静态资源路径var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)// 静态文件服务app.use(staticPath, express.static('./static'))var uri = 'http://localhost:' + port// 编译成功后打印网址信息devMiddleware.waitUntilValid(function () { console.log('> Listening at ' + uri + '/n')})module.exports = app.listen(port, function (err) { if (err) { console.log(err) return } // 如果配置了自动打开浏览器,且不是测试环境,则自动打开浏览器并跳到我们的开发地址 if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { opn(uri) }})
新闻热点
疑难解答
图片精选