vue-element-admin源码解读——项目启动过程
async function serve (args) {
info('Starting development server...')
// although this is primarily a dev server, it is possible that we
// are running it in a mode with a production env, . in E2E tests.
const isInContainer = checkInContainer()
const isProduction = process.env.NODE_ENV === 'production'
const url = require('url')
const chalk = require('chalk')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const portfinder = require('portfinder')
const prepareURLs = require('../util/prepareURLs')
const prepareProxy = require('../util/prepareProxy')
const launchEditorMiddleware = require('launch-editor-middleware')
const validateWebpackConfig = require('../util/validateWebpackConfig')
const isAbsoluteUrl = require('../util/isAbsoluteUrl')
// 获取webpack的配置,在Service初始化时就获取了
const webpackConfig = api.resolveWebpackConfig()
//检查配置信息是否有问题
validateWebpackConfig(webpackConfig, api, options)
//配置webpack的devServer配置选项,这个选项是从获取的
const projectDevServerOptions = Object.assign(
webpackConfig.devServer || {},
options.devServer
)
......
// 配置服务器的选项
const useHttps = args.https || projectDevServerOptions.https || defaults.https
const protocol = useHttps ? 'https' : 'http'
const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port
const port = await portfinder.getPortPromise()
const rawPublicUrl = args.public || projectDevServerOptions.public
const publicUrl = rawPublicUrl
? /^[a-zA-Z]+:\/\//.test(rawPublicUrl)
? rawPublicUrl
: `${protocol}://${rawPublicUrl}`
: null
const urls = prepareURLs(
protocol,
host,
port,
isAbsoluteUrl(options.publicPath) ? '/' : options.publicPath
)
const proxySettings = prepareProxy(
projectDevServerOptions.proxy,
api.resolve('public')
)
// 配置webpack-dev-server选项
if (!isProduction) {
const sockjsUrl = publicUrl
? `?${publicUrl}/sockjs-node`
: isInContainer
? ``
: `?` + url.format({
protocol,
port,
hostname: urls.lanUrlForConfig || 'localhost',
pathname: '/sockjs-node'
})
const devClients = [
// dev server client
require.resolve(`webpack-dev-server/client`) + sockjsUrl,
// hmr client
require.resolve(projectDevServerOptions.hotOnly
? 'webpack/hot/only-dev-server'
: 'webpack/hot/dev-server')
// TODO custom overlay client
// `@vue/cli-overlay/dist/client`
]
if (process.env.APPVEYOR) {
devClients.push(`webpack/hot/poll?500`)
}
// inject dev/hot client
addDevClientToEntry(webpackConfig, devClients)
}
// create compiler
const compiler = webpack(webpackConfig)
// 创建服务器,并注入配置信息
const server = new WebpackDevServer(compiler, Object.assign({
clientLogLevel: 'none',
historyApiFallback: {
disableDotRule: true,
rewrites: genHistoryApiFallbackRewrites(options.publicPath, options.pages)
},
//指定根目录路径
contentBase: api.resolve('public'),
//启动是否监视根目录文件变化
watchContentBase: !isProduction,
//开发环境下启动热更新
hot: !isProduction,
quiet: true,
compress: isProduction,
publicPath: options.publicPath,
overlay: isProduction // TODO disable this
? false
: { warnings: false, errors: true }
}, projectDevServerOptions, {
https: useHttps,
proxy: proxySettings,
before (app, server) {
// launch editor support.
// this works with vue-devtools & @vue/cli-overlay
app.use('/__open-in-editor', launchEditorMiddleware(() => console.log(
`To specify an editor, sepcify the EDITOR env variable or ` +
`add "editor" field to your Vue project config.\n`
)))
//指定中配置的插件
api.service.devServerConfigFns.forEach(fn => fn(app, server))
//应用项目中配置的中间件,中的中指定的mock服务器就是在这被执行的
projectDevServerOptions.before && projectDevServerOptions.before(app, server)
}
}))
// 监听系统信号
;['SIGINT', 'SIGTERM'].forEach(signal => {
process.on(signal, () => {
server.close(() => {
process.exit(0)
})
})
})
//监听关闭信号
if (process.env.VUE_CLI_TEST) {
process.stdin.on('data', data => {
if (data.toString() === 'close') {
console.log('got close signal!')
server.close(() => {
process.exit(0)
})
}
})
}