Skip to content

Commit

Permalink
build & serve
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 30, 2017
1 parent d6af38b commit e9e237e
Show file tree
Hide file tree
Showing 19 changed files with 718 additions and 225 deletions.
5 changes: 4 additions & 1 deletion packages/@vue/cli-service/bin/vue-cli-service
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ const service = new Service()
const args = require('minimist')(process.argv.slice(2))
const command = args._[0]

service.run(command, args)
service.run(command, args).catch(err => {
error(err)
process.exit(1)
})
4 changes: 2 additions & 2 deletions packages/@vue/cli-service/generator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ module.exports = (generatorAPI, options) => {
generatorAPI.render('./template')
generatorAPI.extendPackage({
scripts: {
'dev': 'vue-cli-service serve' + (
'dev': 'vue-cli-service dev' + (
// only auto open browser on MacOS where applescript
// can avoid dupilcate window opens
process.platform === 'darwin'
? ' --open'
: ''
),
'build': 'vue-cli-service build',
'start': 'vue-cli-service serve --prod'
'start': 'vue-cli-service serve'
},
dependencies: {
'vue': '^2.5.13'
Expand Down
19 changes: 11 additions & 8 deletions packages/@vue/cli-service/lib/Service.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const Config = require('webpack-chain')
const PluginAPI = require('./PluginAPI')
const { info, warn, error } = require('@vue/cli-shared-utils')

const defaultOptions = require('./defaults')

module.exports = class Service {
constructor () {
this.webpackConfig = new Config()
Expand All @@ -20,7 +22,7 @@ module.exports = class Service {
const pkg = getPkg.sync()
this.pkg = pkg.pkg || {}
this.context = path.dirname(pkg.path)
this.projectOptions = this.loadProjectConfig()
this.projectOptions = Object.assign(defaultOptions, this.loadProjectConfig())
debug('vue:project-config')(this.projectOptions)

// load base .env
Expand Down Expand Up @@ -67,8 +69,9 @@ module.exports = class Service {

resolvePlugins () {
const builtInPlugins = [
'./commands/serve',
'./commands/dev',
'./commands/build',
'./commands/serve',
'./commands/inspect',
'./commands/help',
// config plugins are order sensitive
Expand Down Expand Up @@ -98,7 +101,7 @@ module.exports = class Service {
args._.shift() // remove command itself
}
const { fn } = command
return fn(args)
return Promise.resolve(fn(args))
}

resolveWebpackConfig () {
Expand Down Expand Up @@ -133,27 +136,27 @@ module.exports = class Service {
}
}

// package['vue-cli']
pkgConfig = this.pkg['vue-cli']
// package.vue
pkgConfig = this.pkg.vue
if (pkgConfig && typeof pkgConfig !== 'object') {
error(
`Error loading vue-cli config in ${chalk.bold(`package.json`)}: ` +
`the "vue-cli" field should be an object.`
`the "vue" field should be an object.`
)
pkgConfig = null
}

if (fileConfig) {
if (pkgConfig) {
warn(
`"vue-cli" field in ${chalk.bold(`package.json`)} ignored ` +
`"vue" field in ${chalk.bold(`package.json`)} ignored ` +
`due to presence of ${chalk.bold('vue.config.js')}.`
)
}
info(`Using project config in ${chalk.bold('vue.config.js')}.`)
return fileConfig
} else if (pkgConfig) {
info(`Using project config from "vue-cli" field in ${chalk.bold(`package.json`)}.`)
info(`Using project config from "vue" field in ${chalk.bold(`package.json`)}.`)
return pkgConfig
} else {
return {}
Expand Down
65 changes: 56 additions & 9 deletions packages/@vue/cli-service/lib/commands/build.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,70 @@
// TODO handle alternative build targets

const defaults = {
mode: 'production',
target: 'app',
extractCSS: true,
sourceMap: true,
cssSourceMap: false
target: 'app'
}

module.exports = (api, options) => {
api.registerCommand('build', {
description: 'build for production',
usage: 'vue-cli-service build',
usage: 'vue-cli-service build [options]',
options: {
'--mode': `specify env mode (default: ${defaults.mode})`,
'--target': `app | library | web-component (default: ${defaults.target})`,
'--extractCSS': `extract component CSS into one file. (default: ${defaults.extractCSS})`,
'--sourceMap': `generate source map (default: ${defaults.sourceMap})`,
'--cssSourceMap': `generate source map for CSS (default: ${defaults.cssSourceMap})`
'--target': `app | library | web-component (default: ${defaults.target})`
}
}, args => {
api.setMode(args.mode || defaults.mode)

const chalk = require('chalk')
const rimraf = require('rimraf')
const webpack = require('webpack')
const {
done,
info,
hasYarn,
logWithSpinner,
stopSpinner
} = require('@vue/cli-shared-utils')

console.log()
logWithSpinner(`Building for production...`)

return new Promise((resolve, reject) => {
const targetDir = api.resolve(options.outputDir)
rimraf(targetDir, err => {
if (err) {
return reject(err)
}
const webpackConfig = api.resolveWebpackConfig()
webpack(webpackConfig, (err, stats) => {
stopSpinner(false)
if (err) {
return reject(err)
}
process.stdout.write(stats.toString({
colors: true,
modules: false,
// TODO set this to true if using TS
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')

if (stats.hasErrors()) {
return reject(`Build failed with errors.`)
}

done(`Build complete. The ${chalk.cyan(options.outputDir)} directory is ready to be deployed.\n`)
const previewCommand = chalk.cyan(`${hasYarn ? 'yarn' : 'npm'} start`)
info(`You can preview the production app by running ${previewCommand}.\n`)
if (options.base === '/') {
info(`The app is built assuming that it will be deployed at the root of a domain.`)
info(`If you intend to deploy it under a subpath, update the ${chalk.green('base')} option`)
info(`in your project config (${chalk.cyan(`vue.config.js`)} or ${chalk.green('"vue"')} field in ${chalk.cyan(`package.json`)}).\n`)
}
})
})
})
})
}
151 changes: 151 additions & 0 deletions packages/@vue/cli-service/lib/commands/dev.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
const {
info,
error,
hasYarn,
clearConsole
} = require('@vue/cli-shared-utils')

const defaults = {
mode: 'development',
host: '0.0.0.0',
port: 8080,
https: false
}

module.exports = (api, options) => {
api.registerCommand('dev', {
description: 'start development server',
usage: 'vue-cli-service dev [options]',
options: {
'--open': `open browser on server start`,
'--mode': `specify env mode (default: ${defaults.mode})`,
'--host': `specify host (default: ${defaults.host})`,
'--port': `specify port (default: ${defaults.port})`,
'--https': `use https (default: ${defaults.https})`
}
}, args => {
clearConsole()
info('Starting development server...')

api.setMode(args.mode || defaults.mode)

const chalk = require('chalk')
const webpack = require('webpack')
const WebpackDevServer = require('webpack-dev-server')
const portfinder = require('portfinder')
const openBrowser = require('../util/openBrowser')
const prepareURLs = require('../util/prepareURLs')
const prepareProxy = require('../util/prepareProxy')
const overlayMiddleware = require('@vue/cli-overlay/middleware')

const projectDevServerOptions = options.devServer || {}
const useHttps = args.https || projectDevServerOptions.https || defaults.https
const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host
portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port

portfinder.getPort((err, port) => {
if (err) {
return error(err)
}

const webpackConfig = api.resolveWebpackConfig()

const urls = prepareURLs(
useHttps ? 'https' : 'http',
host,
port
)

// inject dev/hot client
addDevClientToEntry(webpackConfig, [
// dev server client
`webpack-dev-server/client/?${urls.localUrlForBrowser}`,
// hmr client
projectDevServerOptions.hotOnly
? 'webpack/hot/dev-server'
: 'webpack/hot/only-dev-server',
// custom overlay client
`@vue/cli-overlay/dist/client`
])

const compiler = webpack(webpackConfig)

// log instructions & open browser on first compilation complete
let isFirstCompile = true
compiler.plugin('done', stats => {
if (stats.hasErrors()) {
return
}

console.log([
` App running at:`,
` - Local: ${chalk.cyan(urls.localUrlForTerminal)}`,
` - Network: ${chalk.cyan(urls.lanUrlForTerminal)}`
].join('\n'))
console.log()

if (isFirstCompile) {
isFirstCompile = false
const buildCommand = hasYarn ? `yarn build` : `npm run build`
console.log([
` Note that the development build is not optimized.`,
` To create a production build, run ${chalk.cyan(buildCommand)}.`
].join('\n'))
console.log()

if (args.open || projectDevServerOptions.open) {
openBrowser(urls.localUrlForBrowser)
}
}
})

const proxySettings = prepareProxy(
projectDevServerOptions.proxy,
api.resolve('public')
)

const server = new WebpackDevServer(compiler, Object.assign({
clientLogLevel: 'none',
historyApiFallback: {
disableDotRule: true
},
contentBase: api.resolve('public'),
watchContentBase: true,
hot: true,
quiet: true,
compress: true,
publicPath: webpackConfig.output.publicPath
}, projectDevServerOptions, {
https: useHttps,
proxy: proxySettings,
before (app) {
// overlay
app.use(overlayMiddleware())
// allow other plugins to register middlewares, e.g. PWA
api.service.devServerConfigFns.forEach(fn => fn(app))
// apply in project middlewares
projectDevServerOptions.before && projectDevServerOptions.before(app)
}
}))

server.listen(port, host, err => {
if (err) {
return error(err)
}
})
})
})
}

function addDevClientToEntry (config, devClient) {
const { entry } = config
if (typeof entry === 'object' && !Array.isArray(entry)) {
Object.keys(entry).forEach((key) => {
entry[key] = devClient.concat(entry[key])
})
} else if (typeof entry === 'function') {
config.entry = entry(devClient)
} else {
config.entry = devClient.concat(entry)
}
}
4 changes: 4 additions & 0 deletions packages/@vue/cli-service/lib/commands/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ module.exports = (api, options) => {
}`)
}
}
if (opts.details) {
console.log()
console.log(opts.details.split('\n').map(line => ` ${line}`).join('\n'))
}
console.log()
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/@vue/cli-service/lib/commands/inspect.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = (api, options) => {
api.registerCommand('inspect', {
description: 'inspect internal webpack config',
usage: 'vue-cli-service inspect [...keys]',
usage: 'vue-cli-service inspect [options] [...keys]',
options: {
'--env': 'specify NODE_ENV (default: development)'
}
Expand Down
Loading

0 comments on commit e9e237e

Please sign in to comment.