对比新文件 |
| | |
| | | 'use strict'; |
| | | require('./check-versions')(); |
| | | |
| | | process.env.NODE_ENV = 'production'; |
| | | |
| | | const ora = require('ora'); |
| | | const rm = require('rimraf'); |
| | | const path = require('path'); |
| | | const chalk = require('chalk'); |
| | | const webpack = require('webpack'); |
| | | const config = require('../config'); |
| | | const webpackConfig = require('./webpack.prod.conf'); |
| | | |
| | | const spinner = ora('building for production...'); |
| | | spinner.start(); |
| | | |
| | | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { |
| | | if (err) throw err; |
| | | webpack(webpackConfig, function (err, stats) { |
| | | spinner.stop(); |
| | | if (err) throw err; |
| | | process.stdout.write(stats.toString({ |
| | | colors: true, |
| | | modules: false, |
| | | children: false, |
| | | chunks: false, |
| | | chunkModules: false |
| | | }) + '\n\n'); |
| | | |
| | | if (stats.hasErrors()) { |
| | | console.log(chalk.red(' Build failed with errors.\n')); |
| | | process.exit(1) |
| | | } |
| | | |
| | | console.log(chalk.cyan(' Build complete.\n')) |
| | | console.log(chalk.yellow( |
| | | ' Tip: built files are meant to be served over an HTTP server.\n' + |
| | | ' Opening index.html over file:// won\'t work.\n' |
| | | )) |
| | | }) |
| | | }); |
对比新文件 |
| | |
| | | 'use strict'; |
| | | const chalk = require('chalk'); |
| | | const semver = require('semver'); |
| | | const packageConfig = require('../package.json'); |
| | | const shell = require('shelljs'); |
| | | function exec (cmd) { |
| | | return require('child_process').execSync(cmd).toString().trim() |
| | | } |
| | | |
| | | const versionRequirements = [ |
| | | { |
| | | name: 'node', |
| | | currentVersion: semver.clean(process.version), |
| | | versionRequirement: packageConfig.engines.node |
| | | } |
| | | ]; |
| | | |
| | | if (shell.which('npm')) { |
| | | versionRequirements.push({ |
| | | name: 'npm', |
| | | currentVersion: exec('npm --version'), |
| | | versionRequirement: packageConfig.engines.npm |
| | | }) |
| | | } |
| | | |
| | | module.exports = function () { |
| | | const warnings = []; |
| | | for (let i = 0; i < versionRequirements.length; i++) { |
| | | const mod = versionRequirements[i] |
| | | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { |
| | | warnings.push(mod.name + ': ' + |
| | | chalk.red(mod.currentVersion) + ' should be ' + |
| | | chalk.green(mod.versionRequirement) |
| | | ) |
| | | } |
| | | } |
| | | |
| | | if (warnings.length) { |
| | | console.log(''); |
| | | console.log(chalk.yellow('To use this template, you must update following to modules:')); |
| | | console.log(); |
| | | for (let i = 0; i < warnings.length; i++) { |
| | | const warning = warnings[i] |
| | | console.log(' ' + warning) |
| | | } |
| | | console.log(); |
| | | process.exit(1) |
| | | } |
| | | }; |
对比新文件 |
| | |
| | | 'use strict'; |
| | | const path = require('path'); |
| | | const config = require('../config'); |
| | | const ExtractTextPlugin = require('extract-text-webpack-plugin'); |
| | | const pkg = require('../package.json'); |
| | | |
| | | exports.assetsPath = function (_path) { |
| | | const assetsSubDirectory = process.env.NODE_ENV === 'production' |
| | | ? config.build.assetsSubDirectory |
| | | : config.dev.assetsSubDirectory |
| | | return path.posix.join(assetsSubDirectory, _path) |
| | | }; |
| | | |
| | | exports.cssLoaders = function (options) { |
| | | options = options || {}; |
| | | |
| | | const cssLoader = { |
| | | loader: 'css-loader', |
| | | options: { |
| | | sourceMap: options.sourceMap |
| | | } |
| | | }; |
| | | |
| | | var postcssLoader = { |
| | | loader: 'postcss-loader', |
| | | options: { |
| | | sourceMap: options.sourceMap |
| | | } |
| | | }; |
| | | |
| | | // generate loader string to be used with extract text plugin |
| | | function generateLoaders (loader, loaderOptions) { |
| | | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]; |
| | | if (loader) { |
| | | loaders.push({ |
| | | loader: loader + '-loader', |
| | | options: Object.assign({}, loaderOptions, { |
| | | sourceMap: options.sourceMap |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // Extract CSS when that option is specified |
| | | // (which is the case during production build) |
| | | if (options.extract) { |
| | | return ExtractTextPlugin.extract({ |
| | | use: loaders, |
| | | fallback: 'vue-style-loader' |
| | | }) |
| | | } else { |
| | | return ['vue-style-loader'].concat(loaders) |
| | | } |
| | | } |
| | | |
| | | // https://vue-loader.vuejs.org/en/configurations/extract-css.html |
| | | return { |
| | | css: generateLoaders(), |
| | | postcss: generateLoaders(), |
| | | less: generateLoaders('less'), |
| | | sass: generateLoaders('sass', { indentedSyntax: true }), |
| | | scss: generateLoaders('sass'), |
| | | stylus: generateLoaders('stylus'), |
| | | styl: generateLoaders('stylus') |
| | | } |
| | | }; |
| | | |
| | | // Generate loaders for standalone style files (outside of .vue) |
| | | exports.styleLoaders = function (options) { |
| | | const output = []; |
| | | const loaders = exports.cssLoaders(options); |
| | | for (const extension in loaders) { |
| | | const loader = loaders[extension]; |
| | | output.push({ |
| | | test: new RegExp('\\.' + extension + '$'), |
| | | use: loader |
| | | }) |
| | | } |
| | | return output |
| | | }; |
| | | |
| | | exports.createNotifierCallback = function () { |
| | | const notifier = require('node-notifier'); |
| | | |
| | | return (severity, errors) => { |
| | | if (severity !== 'error') { |
| | | return |
| | | } |
| | | const error = errors[0]; |
| | | |
| | | const filename = error.file && error.file.split('!').pop(); |
| | | notifier.notify({ |
| | | title: pkg.name, |
| | | message: severity + ': ' + error.name, |
| | | subtitle: filename || '', |
| | | icon: path.join(__dirname, 'logo.png') |
| | | }) |
| | | } |
| | | }; |
对比新文件 |
| | |
| | | 'use strict'; |
| | | const utils = require('./utils'); |
| | | const config = require('../config'); |
| | | const isProduction = process.env.NODE_ENV === 'production'; |
| | | const sourceMapEnabled = isProduction |
| | | ? config.build.productionSourceMap |
| | | : config.dev.cssSourceMap; |
| | | |
| | | |
| | | module.exports = { |
| | | loaders: utils.cssLoaders({ |
| | | sourceMap: sourceMapEnabled, |
| | | extract: isProduction |
| | | }), |
| | | cssSourceMap: sourceMapEnabled, |
| | | cacheBusting: config.dev.cacheBusting, |
| | | transformToRequire: { |
| | | video: 'src', |
| | | source: 'src', |
| | | img: 'src', |
| | | image: 'xlink:href' |
| | | } |
| | | }; |
对比新文件 |
| | |
| | | 'use strict'; |
| | | const path = require('path'); |
| | | const utils = require('./utils'); |
| | | const config = require('../config'); |
| | | const vueLoaderConfig = require('./vue-loader.conf'); |
| | | |
| | | function resolve (dir) { |
| | | return path.join(__dirname, '..', dir) |
| | | } |
| | | |
| | | module.exports = { |
| | | context: path.resolve(__dirname, '../'), |
| | | entry: { |
| | | app: './src/main.js' |
| | | }, |
| | | output: { |
| | | path: config.build.assetsRoot, |
| | | filename: '[name].js', |
| | | publicPath: process.env.NODE_ENV === 'production' |
| | | ? config.build.assetsPublicPath |
| | | : config.dev.assetsPublicPath |
| | | }, |
| | | resolve: { |
| | | extensions: ['.js', '.vue', '.json'], |
| | | alias: { |
| | | 'vue$': 'vue/dist/vue.esm.js', |
| | | '@': resolve('src'), |
| | | 'scss_vars': '@/statics/css/vars.scss' |
| | | } |
| | | }, |
| | | module: { |
| | | rules: [ |
| | | // ...(config.dev.useEslint? [{ |
| | | // test: /\.(js|vue)$/, |
| | | // loader: 'eslint-loader', |
| | | // enforce: 'pre', |
| | | // include: [resolve('src'), resolve('test')], |
| | | // options: { |
| | | // formatter: require('eslint-friendly-formatter'), |
| | | // emitWarning: !config.dev.showEslintErrorsInOverlay |
| | | // } |
| | | // }] : []), |
| | | { |
| | | test: /\.vue$/, |
| | | loader: 'vue-loader', |
| | | options: vueLoaderConfig |
| | | }, |
| | | { |
| | | test: /\.js$/, |
| | | loader: 'babel-loader', |
| | | include: [resolve('src'), resolve('test')] |
| | | }, |
| | | { |
| | | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, |
| | | loader: 'url-loader', |
| | | options: { |
| | | limit: 10000, |
| | | name: utils.assetsPath('img/[name].[hash:7].[ext]') |
| | | } |
| | | }, |
| | | { |
| | | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, |
| | | loader: 'url-loader', |
| | | options: { |
| | | limit: 10000, |
| | | name: utils.assetsPath('media/[name].[hash:7].[ext]') |
| | | } |
| | | }, |
| | | { |
| | | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, |
| | | loader: 'url-loader', |
| | | options: { |
| | | limit: 10000, |
| | | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') |
| | | } |
| | | } |
| | | ] |
| | | } |
| | | }; |
对比新文件 |
| | |
| | | 'use strict'; |
| | | const utils = require('./utils'); |
| | | const webpack = require('webpack'); |
| | | const config = require('../config'); |
| | | const merge = require('webpack-merge'); |
| | | const baseWebpackConfig = require('./webpack.base.conf'); |
| | | const HtmlWebpackPlugin = require('html-webpack-plugin'); |
| | | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin'); |
| | | const portfinder = require('portfinder'); |
| | | |
| | | const devWebpackConfig = merge(baseWebpackConfig, { |
| | | module: { |
| | | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) |
| | | }, |
| | | // cheap-module-eval-source-map is faster for development |
| | | devtool: config.dev.devtool, |
| | | |
| | | // these devServer options should be customized in /config/index.js |
| | | devServer: { |
| | | disableHostCheck:true, |
| | | clientLogLevel: 'warning', |
| | | historyApiFallback: true, |
| | | hot: true, |
| | | compress: true, |
| | | host: process.env.HOST ||聽config.dev.host, |
| | | port: process.env.PORT ||聽config.dev.port, |
| | | open: config.dev.autoOpenBrowser, |
| | | overlay: config.dev.errorOverlay ? { |
| | | warnings: false, |
| | | errors: true, |
| | | } : false, |
| | | publicPath: config.dev.assetsPublicPath, |
| | | proxy: config.dev.proxyTable, |
| | | quiet: true, // necessary for FriendlyErrorsPlugin |
| | | watchOptions: { |
| | | poll: config.dev.poll, |
| | | } |
| | | }, |
| | | plugins: [ |
| | | new webpack.DefinePlugin({ |
| | | 'process.env': require('../config/dev.env') |
| | | }), |
| | | new webpack.HotModuleReplacementPlugin(), |
| | | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. |
| | | new webpack.NoEmitOnErrorsPlugin(), |
| | | // https://github.com/ampedandwired/html-webpack-plugin |
| | | new HtmlWebpackPlugin({ |
| | | filename: 'index.html', |
| | | template: 'index.html', |
| | | inject: true |
| | | }), |
| | | ] |
| | | }); |
| | | |
| | | module.exports = new Promise((resolve, reject) => { |
| | | portfinder.basePort = process.env.PORT || config.dev.port; |
| | | portfinder.getPort((err, port) => { |
| | | if (err) { |
| | | reject(err); |
| | | } else { |
| | | // publish the new Port, necessary for e2e tests |
| | | process.env.PORT = port; |
| | | // add port to devServer config |
| | | devWebpackConfig.devServer.port = port; |
| | | |
| | | // Add FriendlyErrorsPlugin |
| | | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({ |
| | | compilationSuccessInfo: { |
| | | messages: [`Your application is running here: http://${config.dev.host}:${port}`], |
| | | }, |
| | | onErrors: config.dev.notifyOnErrors |
| | | ? utils.createNotifierCallback() |
| | | : undefined |
| | | })); |
| | | |
| | | resolve(devWebpackConfig); |
| | | } |
| | | }) |
| | | }); |
对比新文件 |
| | |
| | | 'use strict'; |
| | | const path = require('path'); |
| | | const utils = require('./utils'); |
| | | const webpack = require('webpack'); |
| | | const config = require('../config'); |
| | | const merge = require('webpack-merge'); |
| | | const baseWebpackConfig = require('./webpack.base.conf'); |
| | | const CopyWebpackPlugin = require('copy-webpack-plugin'); |
| | | const HtmlWebpackPlugin = require('html-webpack-plugin'); |
| | | const ExtractTextPlugin = require('extract-text-webpack-plugin'); |
| | | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin'); |
| | | |
| | | const env = process.env.NODE_ENV === 'testing' |
| | | ? require('../config/test.env') |
| | | : require('../config/prod.env'); |
| | | |
| | | const webpackConfig = merge(baseWebpackConfig, { |
| | | module: { |
| | | rules: utils.styleLoaders({ |
| | | sourceMap: config.build.productionSourceMap, |
| | | extract: true, |
| | | usePostCSS: true |
| | | }) |
| | | }, |
| | | devtool: config.build.productionSourceMap ? config.build.devtool : false, |
| | | output: { |
| | | path: config.build.assetsRoot, |
| | | filename: utils.assetsPath('js/[name].[chunkhash].js'), |
| | | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') |
| | | }, |
| | | plugins: [ |
| | | // http://vuejs.github.io/vue-loader/en/workflow/production.html |
| | | new webpack.DefinePlugin({ |
| | | 'process.env': env |
| | | }), |
| | | // UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify |
| | | new webpack.optimize.UglifyJsPlugin({ |
| | | compress: { |
| | | warnings: false |
| | | }, |
| | | sourceMap: config.build.productionSourceMap, |
| | | parallel: true |
| | | }), |
| | | // extract css into its own file |
| | | new ExtractTextPlugin({ |
| | | filename: utils.assetsPath('css/[name].[contenthash].css'), |
| | | // set the following option to `true` if you want to extract CSS from |
| | | // codesplit chunks into this main css file as well. |
| | | // This will result in *all* of your app's CSS being loaded upfront. |
| | | allChunks: false, |
| | | }), |
| | | // Compress extracted CSS. We are using this plugin so that possible |
| | | // duplicated CSS from different components can be deduped. |
| | | new OptimizeCSSPlugin({ |
| | | cssProcessorOptions: config.build.productionSourceMap |
| | | ? { safe: true, map: { inline: false } } |
| | | : { safe: true } |
| | | }), |
| | | // generate dist index.html with correct asset hash for caching. |
| | | // you can customize output by editing /index.html |
| | | // see https://github.com/ampedandwired/html-webpack-plugin |
| | | new HtmlWebpackPlugin({ |
| | | filename: process.env.NODE_ENV === 'testing' |
| | | ? 'index.html' |
| | | : config.build.index, |
| | | template: 'index.html', |
| | | inject: true, |
| | | minify: { |
| | | removeComments: true, |
| | | collapseWhitespace: true, |
| | | removeAttributeQuotes: true |
| | | // more options: |
| | | // https://github.com/kangax/html-minifier#options-quick-reference |
| | | }, |
| | | // necessary to consistently work with multiple chunks via CommonsChunkPlugin |
| | | chunksSortMode: 'dependency' |
| | | }), |
| | | // keep module.id stable when vender modules does not change |
| | | new webpack.HashedModuleIdsPlugin(), |
| | | // enable scope hoisting |
| | | new webpack.optimize.ModuleConcatenationPlugin(), |
| | | // split vendor js into its own file |
| | | new webpack.optimize.CommonsChunkPlugin({ |
| | | name: 'vendor', |
| | | minChunks: function (module) { |
| | | // any required modules inside node_modules are extracted to vendor |
| | | return ( |
| | | module.resource && |
| | | /\.js$/.test(module.resource) && |
| | | module.resource.indexOf( |
| | | path.join(__dirname, '../node_modules') |
| | | ) === 0 |
| | | ) |
| | | } |
| | | }), |
| | | // extract webpack runtime and module manifest to its own file in order to |
| | | // prevent vendor hash from being updated whenever app bundle is updated |
| | | new webpack.optimize.CommonsChunkPlugin({ |
| | | name: 'manifest', |
| | | minChunks: Infinity |
| | | }), |
| | | // This instance extracts shared chunks from code splitted chunks and bundles them |
| | | // in a separate chunk, similar to the vendor chunk |
| | | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk |
| | | new webpack.optimize.CommonsChunkPlugin({ |
| | | name: 'app', |
| | | async: 'vendor-async', |
| | | children: true, |
| | | minChunks: 3 |
| | | }), |
| | | |
| | | // copy custom static assets |
| | | new CopyWebpackPlugin([ |
| | | { |
| | | from: path.resolve(__dirname, '../static'), |
| | | to: config.build.assetsSubDirectory, |
| | | ignore: ['.*'] |
| | | } |
| | | ]) |
| | | ] |
| | | }); |
| | | |
| | | if (config.build.productionGzip) { |
| | | const CompressionWebpackPlugin = require('compression-webpack-plugin') |
| | | |
| | | webpackConfig.plugins.push( |
| | | new CompressionWebpackPlugin({ |
| | | asset: '[path].gz[query]', |
| | | algorithm: 'gzip', |
| | | test: new RegExp( |
| | | '\\.(' + |
| | | config.build.productionGzipExtensions.join('|') + |
| | | ')$' |
| | | ), |
| | | threshold: 10240, |
| | | minRatio: 0.8 |
| | | }) |
| | | ) |
| | | } |
| | | |
| | | if (config.build.bundleAnalyzerReport) { |
| | | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin |
| | | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) |
| | | } |
| | | |
| | | module.exports = webpackConfig; |
对比新文件 |
| | |
| | | 'use strict'; |
| | | // This is the webpack config used for unit tests. |
| | | |
| | | const utils = require('./utils'); |
| | | const webpack = require('webpack'); |
| | | const merge = require('webpack-merge'); |
| | | const baseWebpackConfig = require('./webpack.base.conf'); |
| | | |
| | | const webpackConfig = merge(baseWebpackConfig, { |
| | | // use inline sourcemap for karma-sourcemap-loader |
| | | module: { |
| | | rules: utils.styleLoaders() |
| | | }, |
| | | devtool: '#inline-source-map', |
| | | resolveLoader: { |
| | | alias: { |
| | | // necessary to to make lang="scss" work in test when using vue-loader's ?inject option |
| | | // see discussion at https://github.com/vuejs/vue-loader/issues/724 |
| | | 'scss-loader': 'sass-loader' |
| | | } |
| | | }, |
| | | plugins: [ |
| | | new webpack.DefinePlugin({ |
| | | 'process.env': require('../config/test.env') |
| | | }) |
| | | ] |
| | | }); |
| | | |
| | | // no need for app entry during tests |
| | | delete webpackConfig.entry; |
| | | |
| | | module.exports = webpackConfig; |