You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					239 lines
				
				7.3 KiB
			
		
		
			
		
	
	
					239 lines
				
				7.3 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								const defaults = {
							 | 
						||
| 
								 | 
							
								  clean: true,
							 | 
						||
| 
								 | 
							
								  target: 'app',
							 | 
						||
| 
								 | 
							
								  formats: 'commonjs,umd,umd-min',
							 | 
						||
| 
								 | 
							
								  'unsafe-inline': true
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const buildModes = {
							 | 
						||
| 
								 | 
							
								  lib: 'library',
							 | 
						||
| 
								 | 
							
								  wc: 'web component',
							 | 
						||
| 
								 | 
							
								  'wc-async': 'web component (async)'
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const modifyConfig = (config, fn) => {
							 | 
						||
| 
								 | 
							
								  if (Array.isArray(config)) {
							 | 
						||
| 
								 | 
							
								    config.forEach(c => fn(c))
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    fn(config)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = (api, options) => {
							 | 
						||
| 
								 | 
							
								  api.registerCommand('build', {
							 | 
						||
| 
								 | 
							
								    description: 'build for production',
							 | 
						||
| 
								 | 
							
								    usage: 'vue-cli-service build [options] [entry|pattern]',
							 | 
						||
| 
								 | 
							
								    options: {
							 | 
						||
| 
								 | 
							
								      '--mode': `specify env mode (default: production)`,
							 | 
						||
| 
								 | 
							
								      '--dest': `specify output directory (default: ${options.outputDir})`,
							 | 
						||
| 
								 | 
							
								      '--modern': `build app targeting modern browsers with auto fallback`,
							 | 
						||
| 
								 | 
							
								      '--no-unsafe-inline': `build app without introducing inline scripts`,
							 | 
						||
| 
								 | 
							
								      '--target': `app | lib | wc | wc-async (default: ${defaults.target})`,
							 | 
						||
| 
								 | 
							
								      '--inline-vue': 'include the Vue module in the final bundle of library or web component target',
							 | 
						||
| 
								 | 
							
								      '--formats': `list of output formats for library builds (default: ${defaults.formats})`,
							 | 
						||
| 
								 | 
							
								      '--name': `name for lib or web-component mode (default: "name" in package.json or entry filename)`,
							 | 
						||
| 
								 | 
							
								      '--filename': `file name for output, only usable for 'lib' target (default: value of --name)`,
							 | 
						||
| 
								 | 
							
								      '--no-clean': `do not remove the dist directory before building the project`,
							 | 
						||
| 
								 | 
							
								      '--report': `generate report.html to help analyze bundle content`,
							 | 
						||
| 
								 | 
							
								      '--report-json': 'generate report.json to help analyze bundle content',
							 | 
						||
| 
								 | 
							
								      '--skip-plugins': `comma-separated list of plugin names to skip for this run`,
							 | 
						||
| 
								 | 
							
								      '--watch': `watch for changes`,
							 | 
						||
| 
								 | 
							
								      '--stdin': `close when stdin ends`
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }, async (args, rawArgs) => {
							 | 
						||
| 
								 | 
							
								    for (const key in defaults) {
							 | 
						||
| 
								 | 
							
								      if (args[key] == null) {
							 | 
						||
| 
								 | 
							
								        args[key] = defaults[key]
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    args.entry = args.entry || args._[0]
							 | 
						||
| 
								 | 
							
								    if (args.target !== 'app') {
							 | 
						||
| 
								 | 
							
								      args.entry = args.entry || 'src/App.vue'
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    process.env.VUE_CLI_BUILD_TARGET = args.target
							 | 
						||
| 
								 | 
							
								    if (args.modern && args.target === 'app') {
							 | 
						||
| 
								 | 
							
								      process.env.VUE_CLI_MODERN_MODE = true
							 | 
						||
| 
								 | 
							
								      if (!process.env.VUE_CLI_MODERN_BUILD) {
							 | 
						||
| 
								 | 
							
								        // main-process for legacy build
							 | 
						||
| 
								 | 
							
								        await build(Object.assign({}, args, {
							 | 
						||
| 
								 | 
							
								          modernBuild: false,
							 | 
						||
| 
								 | 
							
								          keepAlive: true
							 | 
						||
| 
								 | 
							
								        }), api, options)
							 | 
						||
| 
								 | 
							
								        // spawn sub-process of self for modern build
							 | 
						||
| 
								 | 
							
								        const { execa } = require('@vue/cli-shared-utils')
							 | 
						||
| 
								 | 
							
								        const cliBin = require('path').resolve(__dirname, '../../../bin/vue-cli-service.js')
							 | 
						||
| 
								 | 
							
								        await execa('node', [cliBin, 'build', ...rawArgs], {
							 | 
						||
| 
								 | 
							
								          stdio: 'inherit',
							 | 
						||
| 
								 | 
							
								          env: {
							 | 
						||
| 
								 | 
							
								            VUE_CLI_MODERN_BUILD: true
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        // sub-process for modern build
							 | 
						||
| 
								 | 
							
								        await build(Object.assign({}, args, {
							 | 
						||
| 
								 | 
							
								          modernBuild: true,
							 | 
						||
| 
								 | 
							
								          clean: false
							 | 
						||
| 
								 | 
							
								        }), api, options)
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      delete process.env.VUE_CLI_MODERN_MODE
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (args.modern) {
							 | 
						||
| 
								 | 
							
								        const { warn } = require('@vue/cli-shared-utils')
							 | 
						||
| 
								 | 
							
								        warn(
							 | 
						||
| 
								 | 
							
								          `Modern mode only works with default target (app). ` +
							 | 
						||
| 
								 | 
							
								          `For libraries or web components, use the browserslist ` +
							 | 
						||
| 
								 | 
							
								          `config to specify target browsers.`
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      await build(args, api, options)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    delete process.env.VUE_CLI_BUILD_TARGET
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								async function build (args, api, options) {
							 | 
						||
| 
								 | 
							
								  const fs = require('fs-extra')
							 | 
						||
| 
								 | 
							
								  const path = require('path')
							 | 
						||
| 
								 | 
							
								  const webpack = require('webpack')
							 | 
						||
| 
								 | 
							
								  const { chalk } = require('@vue/cli-shared-utils')
							 | 
						||
| 
								 | 
							
								  const formatStats = require('./formatStats')
							 | 
						||
| 
								 | 
							
								  const validateWebpackConfig = require('../../util/validateWebpackConfig')
							 | 
						||
| 
								 | 
							
								  const {
							 | 
						||
| 
								 | 
							
								    log,
							 | 
						||
| 
								 | 
							
								    done,
							 | 
						||
| 
								 | 
							
								    info,
							 | 
						||
| 
								 | 
							
								    logWithSpinner,
							 | 
						||
| 
								 | 
							
								    stopSpinner
							 | 
						||
| 
								 | 
							
								  } = require('@vue/cli-shared-utils')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  log()
							 | 
						||
| 
								 | 
							
								  const mode = api.service.mode
							 | 
						||
| 
								 | 
							
								  if (args.target === 'app') {
							 | 
						||
| 
								 | 
							
								    const bundleTag = args.modern
							 | 
						||
| 
								 | 
							
								      ? args.modernBuild
							 | 
						||
| 
								 | 
							
								        ? `modern bundle `
							 | 
						||
| 
								 | 
							
								        : `legacy bundle `
							 | 
						||
| 
								 | 
							
								      : ``
							 | 
						||
| 
								 | 
							
								    logWithSpinner(`Building ${bundleTag}for ${mode}...`)
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    const buildMode = buildModes[args.target]
							 | 
						||
| 
								 | 
							
								    if (buildMode) {
							 | 
						||
| 
								 | 
							
								      const additionalParams = buildMode === 'library' ? ` (${args.formats})` : ``
							 | 
						||
| 
								 | 
							
								      logWithSpinner(`Building for ${mode} as ${buildMode}${additionalParams}...`)
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      throw new Error(`Unknown build target: ${args.target}`)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (args.dest) {
							 | 
						||
| 
								 | 
							
								    // Override outputDir before resolving webpack config as config relies on it (#2327)
							 | 
						||
| 
								 | 
							
								    options.outputDir = args.dest
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const targetDir = api.resolve(options.outputDir)
							 | 
						||
| 
								 | 
							
								  const isLegacyBuild = args.target === 'app' && args.modern && !args.modernBuild
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // resolve raw webpack config
							 | 
						||
| 
								 | 
							
								  let webpackConfig
							 | 
						||
| 
								 | 
							
								  if (args.target === 'lib') {
							 | 
						||
| 
								 | 
							
								    webpackConfig = require('./resolveLibConfig')(api, args, options)
							 | 
						||
| 
								 | 
							
								  } else if (
							 | 
						||
| 
								 | 
							
								    args.target === 'wc' ||
							 | 
						||
| 
								 | 
							
								    args.target === 'wc-async'
							 | 
						||
| 
								 | 
							
								  ) {
							 | 
						||
| 
								 | 
							
								    webpackConfig = require('./resolveWcConfig')(api, args, options)
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    webpackConfig = require('./resolveAppConfig')(api, args, options)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // check for common config errors
							 | 
						||
| 
								 | 
							
								  validateWebpackConfig(webpackConfig, api, options, args.target)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (args.watch) {
							 | 
						||
| 
								 | 
							
								    modifyConfig(webpackConfig, config => {
							 | 
						||
| 
								 | 
							
								      config.watch = true
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (args.stdin) {
							 | 
						||
| 
								 | 
							
								    process.stdin.on('end', () => {
							 | 
						||
| 
								 | 
							
								      process.exit(0)
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								    process.stdin.resume()
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Expose advanced stats
							 | 
						||
| 
								 | 
							
								  if (args.dashboard) {
							 | 
						||
| 
								 | 
							
								    const DashboardPlugin = require('../../webpack/DashboardPlugin')
							 | 
						||
| 
								 | 
							
								    modifyConfig(webpackConfig, config => {
							 | 
						||
| 
								 | 
							
								      config.plugins.push(new DashboardPlugin({
							 | 
						||
| 
								 | 
							
								        type: 'build',
							 | 
						||
| 
								 | 
							
								        modernBuild: args.modernBuild,
							 | 
						||
| 
								 | 
							
								        keepAlive: args.keepAlive
							 | 
						||
| 
								 | 
							
								      }))
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (args.report || args['report-json']) {
							 | 
						||
| 
								 | 
							
								    const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
							 | 
						||
| 
								 | 
							
								    modifyConfig(webpackConfig, config => {
							 | 
						||
| 
								 | 
							
								      const bundleName = args.target !== 'app'
							 | 
						||
| 
								 | 
							
								        ? config.output.filename.replace(/\.js$/, '-')
							 | 
						||
| 
								 | 
							
								        : isLegacyBuild ? 'legacy-' : ''
							 | 
						||
| 
								 | 
							
								      config.plugins.push(new BundleAnalyzerPlugin({
							 | 
						||
| 
								 | 
							
								        logLevel: 'warn',
							 | 
						||
| 
								 | 
							
								        openAnalyzer: false,
							 | 
						||
| 
								 | 
							
								        analyzerMode: args.report ? 'static' : 'disabled',
							 | 
						||
| 
								 | 
							
								        reportFilename: `${bundleName}report.html`,
							 | 
						||
| 
								 | 
							
								        statsFilename: `${bundleName}report.json`,
							 | 
						||
| 
								 | 
							
								        generateStatsFile: !!args['report-json']
							 | 
						||
| 
								 | 
							
								      }))
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (args.clean) {
							 | 
						||
| 
								 | 
							
								    await fs.remove(targetDir)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return new Promise((resolve, reject) => {
							 | 
						||
| 
								 | 
							
								    webpack(webpackConfig, (err, stats) => {
							 | 
						||
| 
								 | 
							
								      stopSpinner(false)
							 | 
						||
| 
								 | 
							
								      if (err) {
							 | 
						||
| 
								 | 
							
								        return reject(err)
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (stats.hasErrors()) {
							 | 
						||
| 
								 | 
							
								        return reject(`Build failed with errors.`)
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!args.silent) {
							 | 
						||
| 
								 | 
							
								        const targetDirShort = path.relative(
							 | 
						||
| 
								 | 
							
								          api.service.context,
							 | 
						||
| 
								 | 
							
								          targetDir
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								        log(formatStats(stats, targetDirShort, api))
							 | 
						||
| 
								 | 
							
								        if (args.target === 'app' && !isLegacyBuild) {
							 | 
						||
| 
								 | 
							
								          if (!args.watch) {
							 | 
						||
| 
								 | 
							
								            done(`Build complete. The ${chalk.cyan(targetDirShort)} directory is ready to be deployed.`)
							 | 
						||
| 
								 | 
							
								            info(`Check out deployment instructions at ${chalk.cyan(`https://cli.vuejs.org/guide/deployment.html`)}\n`)
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            done(`Build complete. Watching for changes...`)
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // test-only signal
							 | 
						||
| 
								 | 
							
								      if (process.env.VUE_CLI_TEST) {
							 | 
						||
| 
								 | 
							
								        console.log('Build complete.')
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      resolve()
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.defaultModes = {
							 | 
						||
| 
								 | 
							
								  build: 'production'
							 | 
						||
| 
								 | 
							
								}
							 |