// serve pure static assets // 提供static文件夹上的静态文件服务 var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) app.use(staticPath, express.static('./static'))
// 访问链接 var uri = 'http://localhost:' + port
// 创建promise,在应用服务启动之后resolve // 便于外部文件require了这个dev-server之后的代码编写 var _resolve var readyPromise = new Promise(resolve => { _resolve = resolve })
console.log('> Starting dev server...') // webpack-dev-middleware等待webpack完成所有编译打包之后输出提示语到控制台,表明服务正式启动 // 服务正式启动才自动打开浏览器进入页面 devMiddleware.waitUntilValid(() => { console.log('> Listening at ' + uri + '\n') // when env is testing, don't need open it if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { opn(uri) } _resolve() })
// 启动express服务器并监听相应的端口 var server = app.listen(port)
var path = require('path') var fs = require('fs') var utils = require('./utils') var config = require('../config') var vueLoaderConfig = require('./vue-loader.conf')
// generate loader string to be used with extract text plugin // 生成各种loader配置,并且配置了extract-text-pulgin function generateLoaders (loader, loaderOptions) { // 默认是css-loader var loaders = [cssLoader] // 如果非css,则增加一个处理预编译语言的loader并设好相关配置属性 // 例如generateLoaders('less'),这里就会push一个less-loader // less-loader先将less编译成css,然后再由css-loader去处理css // 其他sass、scss等语言也是一样的过程 if (loader) { loaders.push({ loader: loader + '-loader', //Object.assign是es6语法的浅复制,后两者合并后复制完成赋值 options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) }
// Extract CSS when that option is specified // (which is the case during production build) if (options.extract) { // 配置extract-text-plugin提取样式 // ExtractTextPlugin可提取出文本,代表首先使用上面处理的loaders,当未能正确引入时使用vue-style-loader return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else { // 无需提取样式则简单使用vue-style-loader配合各种样式loader去处理<style>里面的样式 // 返回vue-style-loader连接loaders的最终值 return ['vue-style-loader'].concat(loaders) } }
// ora,一个可以在终端显示spinner的插件 var ora = require('ora') // rm,用于删除文件或文件夹的插件 var rm = require('rimraf') var path = require('path') // chalk,用于在控制台输出带颜色字体的插件 var chalk = require('chalk') var webpack = require('webpack') // 默认读取下面的index.js文件 var config = require('../config') var webpackConfig = require('./webpack.prod.conf')
var spinner = ora('building for production...') spinner.start() // 开启loading动画
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' )) }) })
var path = require('path') var utils = require('./utils') var webpack = require('webpack') var config = require('../config') var merge = require('webpack-merge') var baseWebpackConfig = require('./webpack.base.conf') // copy-webpack-plugin,用于将static中的静态文件复制到产品文件夹dist var CopyWebpackPlugin = require('copy-webpack-plugin') var HtmlWebpackPlugin = require('html-webpack-plugin') var ExtractTextPlugin = require('extract-text-webpack-plugin') // optimize-css-assets-webpack-plugin,用于优化和最小化css资源 var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
var env = config.build.env
var webpackConfig = merge(baseWebpackConfig, { module: { // 样式文件的处理规则,对css/sass/scss等不同内容使用相应的styleLoaders // 由utils配置出各种类型的预处理语言所需要使用的loader,例如sass需要使用sass-loader rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) }, // 是否使用source-map devtool: config.build.productionSourceMap ? '#source-map' : false, // webpack输出路径和命名规则 output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, // webpack插件 plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html new webpack.DefinePlugin({ 'process.env': env }), // 丑化压缩JS代码 new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, sourceMap: true }), // extract css into its own file // 将css提取到单独的文件 new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css') }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. // 优化、最小化css代码,如果只简单使用extract-text-plugin可能会造成css重复 // 具体原因可以看npm上面optimize-css-assets-webpack-plugin的介绍 new OptimizeCSSPlugin({ cssProcessorOptions: { 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 // 将产品文件的引用注入到index.html new HtmlWebpackPlugin({ filename: config.build.index, template: 'index.html', inject: true, minify: { // 删除index.html中的注释 removeComments: true, // 删除index.html中的空格 collapseWhitespace: true, // 删除各种html标签属性值的双引号 removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference }, // necessary to consistently work with multiple chunks via CommonsChunkPlugin // 注入依赖的时候按照依赖先后顺序进行注入,比如,需要先注入vendor.js,再注入app.js chunksSortMode: 'dependency' }), // keep module.id stable when vender modules does not change new webpack.HashedModuleIdsPlugin(), // split vendor js into its own file // 将所有从node_modules中引入的js提取到vendor.js,即抽取库文件 new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: function (module, count) { // 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 // 从vendor中提取出manifest,原因如上 new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }), // copy custom static assets // 将static文件夹里面的静态资源复制到dist/static new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] } ]) ] })
// 如果开启了产品gzip压缩,则利用插件将构建后的产品文件进行压缩 if (config.build.productionGzip) { // 一个用于压缩的webpack插件 var CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = function () { var warnings = [] // 依次判断版本是否符合要求 for (var i = 0; i < versionRequirements.length; i++) { var mod = versionRequirements[i] if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { //上面这个判断就是如果版本号不符合package.json文件中指定的版本号,就执行下面错误提示的代码 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 (var i = 0; i < warnings.length; i++) { var warning = warnings[i] console.log(' ' + warning) } console.log() process.exit(1) } }
// see http://vuejs-templates.github.io/webpack for documentation. var path = require('path')
module.exports = { // 构建产品时使用的配置 build: { // 环境变量 env: require('./prod.env'), // html入口文件 index: path.resolve(__dirname, '../dist/index.html'), // 产品文件的存放路径 assetsRoot: path.resolve(__dirname, '../dist'), // 二级目录,存放静态资源文件的目录,位于dist文件夹下 assetsSubDirectory: 'static', // 发布路径,如果构建后的产品文件有用于发布CDN或者放到其他域名的服务器,可以在这里进行设置 // 设置之后构建的产品文件在注入到index.html中的时候就会带上这里的发布路径 assetsPublicPath: '/', // 是否使用source-map productionSourceMap: true, // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin // 是否开启gzip压缩 productionGzip: false, // gzip模式下需要压缩的文件的扩展名,设置js、css之后就只会对js和css文件进行压缩 productionGzipExtensions: ['js', 'css'], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off // 是否展示webpack构建打包之后的分析报告 bundleAnalyzerReport: process.env.npm_config_report }, // 开发过程中使用的配置 dev: { // 环境变量 env: require('./dev.env'), // dev-server监听的端口 port: 8080, // 是否自动打开浏览器 autoOpenBrowser: true, // 静态资源文件夹 assetsSubDirectory: 'static', // 发布路径 assetsPublicPath: '/', // 代理配置表,在这里可以配置特定的请求代理到对应的API接口 // 例如将'localhost:8080/api/xxx'代理到'www.example.com/api/xxx' proxyTable: {}, // CSS Sourcemaps off by default because relative paths are "buggy" // with this option, according to the CSS-Loader README // (https://github.com/webpack/css-loader#sourcemaps) // In our experience, they generally work as expected, // just be aware of this issue when enabling this option. // 是否开启 cssSourceMap cssSourceMap: false } }