转载地址:http://blog.csdn.net/hongchh/article/details/55113751

一、文件结构

本文主要分析开发(dev)和构建(build)两个过程涉及到的文件,故下面文件结构仅列出相应的内容。

 1 ├─build
 2 │   ├─build.js
 3 │   ├─check-versions.js
 4 │   ├─dev-client.js
 5 │   ├─dev-server.js
 6 │   ├─utils.js
 7 │   ├─vue-loader.conf.js
 8 │   ├─webpack.base.conf.js
 9 │   ├─webpack.dev.conf.js
10 │   ├─webpack.prod.conf.js
11 │   └─webpack.test.conf.js
12 ├─config
13 │   ├─dev.env.js
14 │   ├─index.js
15 │   ├─prod.env.js
16 │   └─test.env.js
17 ├─...
18 └─package.json

二、指令分析

首先看package.json里面的scripts字段,

1 "scripts": {
2     "dev": "node build/dev-server.js",
3     "start": "node build/dev-server.js",
4     "build": "node build/build.js",
5     "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
6     "e2e": "node test/e2e/runner.js",
7     "test": "npm run unit && npm run e2e",
8     "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
9   },

运行”npm run dev”的时候执行的是build/dev-server.js文件,运行”npm run build”的时候执行的是build/build.js文件,我们可以从这两个文件开始进行代码阅读分析。

三、build文件夹分析

build/dev-server.js

首先来看执行”npm run dev”时候最先执行的build/dev-server.js文件。该文件主要完成下面几件事情:

  1. 检查node和npm的版本、引入相关插件和配置
  2. webpack对源码进行编译打包并返回compiler对象
  3. 创建express服务器
  4. 配置开发中间件(webpack-dev-middleware)和热重载中间件(webpack-hot-middleware)
  5. 挂载代理服务和中间件
  6. 配置静态资源
  7. 启动服务器监听特定端口(8080)
  8. 自动打开浏览器并打开特定网址(localhost:8080)

说明: express服务器提供静态文件服务,不过它还使用了http-proxy-middleware,一个http请求代理的中间件。前端开发过程中需要使用到后台的API的话,可以通过配置proxyTable来将相应的后台请求代理到专用的API服务器。

详情请看代码注释:

  1 // 检查NodeJS和npm的版本
  2 require('./check-versions')()
  3
  4 // 获取基本配置
  5 var config = require('../config')
  6 // 如果Node的环境变量中没有设置当前的环境(NODE_ENV),则使用config中的dev环境配置作为当前的环境
  7 if (!process.env.NODE_ENV) {
  8   process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
  9 }
 10
 11 // opn是一个可以调用默认软件打开网址、图片、文件等内容的插件
 12 // 这里用它来调用默认浏览器打开dev-server监听的端口,例如:localhost:8080
 13 var opn = require('opn')
 14 var path = require('path')
 15 var express = require('express')
 16 var webpack = require('webpack')
 17 // http-proxy-middleware是一个express中间件,用于将http请求代理到其他服务器
 18 // 例:localhost:8080/api/xxx  -->  localhost:3000/api/xxx
 19 // 这里使用该插件可以将前端开发中涉及到的请求代理到提供服务的后台服务器上,方便与服务器对接
 20 var proxyMiddleware = require('http-proxy-middleware')
 21 // 开发环境下的webpack配置
 22 var webpackConfig = require('./webpack.dev.conf')
 23
 24 // dev-server 监听的端口,如果没有在命令行传入端口号,则使用config.dev.port设置的端口,例如8080
 25 var port = process.env.PORT || config.dev.port
 26 // 用于判断是否要自动打开浏览器的布尔变量,当配置文件中没有设置自动打开浏览器的时候其值为 false
 27 var autoOpenBrowser = !!config.dev.autoOpenBrowser
 28 // HTTP代理表,指定规则,将某些API请求代理到相应的服务器
 29 var proxyTable = config.dev.proxyTable
 30 // 创建express服务器
 31 var app = express()
 32 // webpack根据配置开始编译打包源码并返回compiler对象
 33 var compiler = webpack(webpackConfig)
 34 // webpack-dev-middleware将webpack编译打包后得到的产品文件存放在内存中而没有写进磁盘
 35 // 将这个中间件挂到express上使用之后即可提供这些编译后的产品文件服务
 36 var devMiddleware = require('webpack-dev-middleware')(compiler, {
 37   publicPath: webpackConfig.output.publicPath, // 设置访问路径为webpack配置中的output里面所对应的路径
 38   quiet: true // 设置为true,使其不要在控制台输出日志
 39 })
 40 // webpack-hot-middleware,用于实现热重载功能的中间件
 41 var hotMiddleware = require('webpack-hot-middleware')(compiler, {
 42   log: false, // 关闭控制台的日志输出
 43   heartbeat: 2000 // 发送心跳包的频率
 44 })
 45 // webpack(重新)编译打包完成后并将js、css等文件inject到html文件之后,通过热重载中间件强制页面刷新
 46 compiler.plugin('compilation', function (compilation) {
 47   compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
 48     hotMiddleware.publish({ action: 'reload' })
 49     cb()
 50   })
 51 })
 52
 53 // 根据 proxyTable 中的代理请求配置来设置express服务器的http代理规则
 54 Object.keys(proxyTable).forEach(function (context) {
 55   var options = proxyTable[context]
 56   // 格式化options,例如将'www.example.com'变成{ target: 'www.example.com' }
 57   if (typeof options === 'string') {
 58     options = { target: options }
 59   }
 60   app.use(proxyMiddleware(options.filter || context, options))
 61 })
 62
 63 // handle fallback for HTML5 history API
 64 // 重定向不存在的URL,用于支持SPA(单页应用)
 65 // 例如使用vue-router并开启了history模式
 66 app.use(require('connect-history-api-fallback')())
 67
 68 // serve webpack bundle output
 69 // 挂载webpack-dev-middleware中间件,提供webpack编译打包后的产品文件服务
 70 app.use(devMiddleware)
 71
 72 // enable hot-reload and state-preserving
 73 // compilation error display
 74 // 挂载热重载中间件
 75 app.use(hotMiddleware)
 76
 77 // serve pure static assets
 78 // 提供static文件夹上的静态文件服务
 79 var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
 80 app.use(staticPath, express.static('./static'))
 81
 82 // 访问链接
 83 var uri = 'http://localhost:' + port
 84
 85 // 创建promise,在应用服务启动之后resolve
 86 // 便于外部文件require了这个dev-server之后的代码编写
 87 var _resolve
 88 var readyPromise = new Promise(resolve => {
 89   _resolve = resolve
 90 })
 91
 92 console.log('> Starting dev server...')
 93 // webpack-dev-middleware等待webpack完成所有编译打包之后输出提示语到控制台,表明服务正式启动
 94 // 服务正式启动才自动打开浏览器进入页面
 95 devMiddleware.waitUntilValid(() => {
 96   console.log('> Listening at ' + uri + '\n')
 97   // when env is testing, don't need open it
 98   if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
 99     opn(uri)
100   }
101   _resolve()
102 })
103
104 // 启动express服务器并监听相应的端口
105 var server = app.listen(port)
106
107 // 暴露本模块的功能给外部使用,例如下面这种用法
108 // var devServer = require('./build/dev-server')
109 // devServer.ready.then(() => {...})
110 // if (...) { devServer.close() }
111 module.exports = {
112   ready: readyPromise,
113   close: () => {
114     server.close()
115   }
116 }

build/webpack.base.conf.js

从代码中看到,dev-server使用的webpack配置来自build/webpack.dev.conf.js文件(测试环境下使用的是build/webpack.prod.conf.js,这里暂时不考虑测试环境)。而build/webpack.dev.conf.js中又引用了webpack.base.conf.js,所以这里我先分析webpack.base.conf.js。

webpack.base.conf.js主要完成了下面这些事情:

  1. 配置webpack编译入口
  2. 配置webpack输出路径和命名规则
  3. 配置模块resolve规则
  4. 配置不同类型模块的处理规则

说明: 这个配置里面只配置了.js、.vue、图片、字体等几类文件的处理规则,如果需要处理其他文件可以在module.rules里面另行配置。

具体请看代码注释:

 1 var path = require('path')
 2 var fs = require('fs')
 3 var utils = require('./utils')
 4 var config = require('../config')
 5 var vueLoaderConfig = require('./vue-loader.conf')
 6
 7 // 获取绝对路径
 8 function resolve (dir) {
 9   return path.join(__dirname, '..', dir)
10 }
11
12 module.exports = {
13   // webpack入口文件
14   entry: {
15     app: './src/main.js'
16   },
17   // webpack输出路径和命名规则
18   output: {
19     // webpack输出的目标文件夹路径(例如:/dist)
20     path: config.build.assetsRoot,
21     // webpack输出bundle文件命名格式
22     filename: '[name].js',
23     // webpack编译输出的发布路径(例如'//cdn.xxx.com/app/')
24     publicPath: process.env.NODE_ENV === 'production'
25       ? config.build.assetsPublicPath
26       : config.dev.assetsPublicPath
27   },
28   // 模块resolve的规则
29   resolve: {
30     extensions: ['.js', '.vue', '.json'],
31     // 别名,方便引用模块,例如有了别名之后,
32     // import Vue from 'vue/dist/vue.common.js'可以写成 import Vue from 'vue'
33     alias: {
34       'vue$': 'vue/dist/vue.esm.js',
35       '@': resolve('src'),
36     },
37     symlinks: false
38   },
39   // 不同类型模块的处理规则
40   module: {
41     rules: [
42       {// 对src和test文件夹下的.js和.vue文件使用eslint-loader进行代码规范检查
43         test: /\.(js|vue)$/,
44         loader: 'eslint-loader',
45         enforce: 'pre',
46         include: [resolve('src'), resolve('test')],
47         options: {
48           formatter: require('eslint-friendly-formatter')
49         }
50       },
51       {// 对所有.vue文件使用vue-loader进行编译
52         test: /\.vue$/,
53         loader: 'vue-loader',
54         options: vueLoaderConfig
55       },
56       {// 对src和test文件夹下的.js文件使用babel-loader将es6+的代码转成es5
57         test: /\.js$/,
58         loader: 'babel-loader',
59         include: [resolve('src'), resolve('test')]
60       },
61       {// 对图片资源文件使用url-loader
62         test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
63         loader: 'url-loader',
64         options: {
65           // 小于10K的图片转成base64编码的dataURL字符串写到代码中
66           limit: 10000,
67           // 其他的图片转移到静态资源文件夹
68           name: utils.assetsPath('img/[name].[hash:7].[ext]')
69         }
70       },
71       {// 对多媒体资源文件使用url-loader
72         test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
73         loader: 'url-loader',
74         options: {
75           // 小于10K的资源转成base64编码的dataURL字符串写到代码中
76           limit: 10000,
77           // 其他的资源转移到静态资源文件夹
78           name: utils.assetsPath('media/[name].[hash:7].[ext]')
79         }
80       },
81       {// 对字体资源文件使用url-loader
82         test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
83         loader: 'url-loader',
84         options: {
85           // 小于10K的资源转成base64编码的dataURL字符串写到代码中
86           limit: 10000,
87           // 其他的资源转移到静态资源文件夹
88           name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
89         }
90       }
91     ]
92   }
93 }

build/utils.js

utils提供工具函数,包括生成处理各种样式语言的loader,获取资源文件存放路径的工具函数。 
1. 计算资源文件存放路径 
2. 生成cssLoaders用于加载.vue文件中的样式 
3. 生成styleLoaders用于加载不在.vue文件中的单独存在的样式文件

 1 var path = require('path')
 2 var config = require('../config')
 3 // extract-text-webpack-plugin可以提取bundle中的特定文本,将提取后的文本单独存放到另外的文件
 4 // 这里用来提取css样式
 5 var ExtractTextPlugin = require('extract-text-webpack-plugin')
 6
 7 // 资源文件的存放路径
 8 exports.assetsPath = function (_path) {
 9   var assetsSubDirectory = process.env.NODE_ENV === 'production'
10     ? config.build.assetsSubDirectory
11     : config.dev.assetsSubDirectory
12   return path.posix.join(assetsSubDirectory, _path)
13 }
14
15 // 生成css、sass、scss等各种用来编写样式的语言所对应的loader配置
16 exports.cssLoaders = function (options) {
17   options = options || {}
18   // css-loader配置
19   var cssLoader = {
20     loader: 'css-loader',
21     options: {
22       // 是否最小化
23       minimize: process.env.NODE_ENV === 'production',
24       // 是否使用source-map
25       sourceMap: options.sourceMap
26     }
27   }
28
29   // generate loader string to be used with extract text plugin
30   // 生成各种loader配置,并且配置了extract-text-pulgin
31   function generateLoaders (loader, loaderOptions) {
32     // 默认是css-loader
33     var loaders = [cssLoader]
34     // 如果非css,则增加一个处理预编译语言的loader并设好相关配置属性
35     // 例如generateLoaders('less'),这里就会push一个less-loader
36     // less-loader先将less编译成css,然后再由css-loader去处理css
37     // 其他sass、scss等语言也是一样的过程
38     if (loader) {
39       loaders.push({
40         loader: loader + '-loader',
41         options: Object.assign({}, loaderOptions, {
42           sourceMap: options.sourceMap
43         })
44       })
45     }
46
47     // Extract CSS when that option is specified
48     // (which is the case during production build)
49     if (options.extract) {
50       // 配置extract-text-plugin提取样式
51       return ExtractTextPlugin.extract({
52         use: loaders,
53         fallback: 'vue-style-loader'
54       })
55     } else {
56       // 无需提取样式则简单使用vue-style-loader配合各种样式loader去处理<style>里面的样式
57       return ['vue-style-loader'].concat(loaders)
58     }
59   }
60
61   // https://vue-loader.vuejs.org/en/configurations/extract-css.html
62   // 得到各种不同处理样式的语言所对应的loader
63   return {
64     css: generateLoaders(),
65     postcss: generateLoaders(),
66     less: generateLoaders('less'),
67     sass: generateLoaders('sass', { indentedSyntax: true }),
68     scss: generateLoaders('sass'),
69     stylus: generateLoaders('stylus'),
70     styl: generateLoaders('stylus')
71   }
72 }
73
74 // Generate loaders for standalone style files (outside of .vue)
75 // 生成处理单独的.css、.sass、.scss等样式文件的规则
76 exports.styleLoaders = function (options) {
77   var output = []
78   var loaders = exports.cssLoaders(options)
79   for (var extension in loaders) {
80     var loader = loaders[extension]
81     output.push({
82       test: new RegExp('\\.' + extension + '$'),
83       use: loader
84     })
85   }
86   return output
87 }

build/vue-loader.conf.js

vue-loader.conf的配置比较简单,详情请看代码注释:

 1 var utils = require('./utils')
 2 var config = require('../config')
 3 var isProduction = process.env.NODE_ENV === 'production'
 4
 5 module.exports = {
 6   // 处理.vue文件中的样式
 7   loaders: utils.cssLoaders({
 8     // 是否打开source-map
 9     sourceMap: isProduction
10       ? config.build.productionSourceMap
11       : config.dev.cssSourceMap,
12     // 是否提取样式到单独的文件
13     extract: isProduction
14   }),
15   transformToRequire: {
16     video: 'src',
17     source: 'src',
18     img: 'src',
19     image: 'xlink:href'
20   }
21 }

build/dev-client.js

dev-client.js里面主要写了浏览器端代码,用于实现webpack的热更新。

 1 /* eslint-disable */
 2 // 实现浏览器端的EventSource,用于跟服务器双向通信
 3 // webpack热重载客户端跟dev-server上的热重载插件之间需要进行双向通信
 4 // 服务端webpack重新编译后,会向客户端推送信息,告诉客户端进行更新
 5 require('eventsource-polyfill')
 6 // webpack热重载客户端
 7 var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
 8
 9 // 客户端收到更新动作,执行页面刷新
10 hotClient.subscribe(function (event) {
11   if (event.action === 'reload') {
12     window.location.reload()
13   }
14 })

build/build.js

讲完了开发环境下的配置,下面开始来看构建环境下的配置。执行”npm run build”的时候首先执行的是build/build.js文件,build.js主要完成下面几件事:

  1. loading动画
  2. 删除目标文件夹
  3. 执行webpack构建
  4. 输出信息

说明: webpack编译之后会输出到配置里面指定的目标文件夹;删除目标文件夹之后再创建是为了去除旧的内容,以免产生不可预测的影响。

详情请看代码注释:

 1 // 检查NodeJS和npm的版本
 2 require('./check-versions')()
 3
 4 process.env.NODE_ENV = 'production'
 5
 6 // ora,一个可以在终端显示spinner的插件
 7 var ora = require('ora')
 8 // rm,用于删除文件或文件夹的插件
 9 var rm = require('rimraf')
10 var path = require('path')
11 // chalk,用于在控制台输出带颜色字体的插件
12 var chalk = require('chalk')
13 var webpack = require('webpack')
14 var config = require('../config')
15 var webpackConfig = require('./webpack.prod.conf')
16
17 var spinner = ora('building for production...')
18 spinner.start() // 开启loading动画
19
20 // 首先将整个dist文件夹以及里面的内容删除,以免遗留旧的没用的文件
21 // 删除完成后才开始webpack构建打包
22 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
23   if (err) throw err
24   // 执行webpack构建打包,完成之后在终端输出构建完成的相关信息或者输出报错信息并退出程序
25   webpack(webpackConfig, function (err, stats) {
26     spinner.stop()
27     if (err) throw err
28     process.stdout.write(stats.toString({
29       colors: true,
30       modules: false,
31       children: false,
32       chunks: false,
33       chunkModules: false
34     }) + '\n\n')
35
36     if (stats.hasErrors()) {
37       console.log(chalk.red('  Build failed with errors.\n'))
38       process.exit(1)
39     }
40
41     console.log(chalk.cyan('  Build complete.\n'))
42     console.log(chalk.yellow(
43       '  Tip: built files are meant to be served over an HTTP server.\n' +
44       '  Opening index.html over file:// won\'t work.\n'
45     ))
46   })
47 })

build/webpack.prod.conf.js

构建的时候用到的webpack配置来自webpack.prod.conf.js,该配置同样是在webpack.base.conf基础上的进一步完善。主要完成下面几件事情:

  1. 合并基础的webpack配置
  2. 配置样式文件的处理规则,styleLoaders
  3. 配置webpack的输出
  4. 配置webpack插件
  5. gzip模式下的webpack插件配置
  6. webpack-bundle分析

说明: webpack插件里面多了丑化压缩代码以及抽离css文件等插件。

  1 var path = require('path')
  2 var utils = require('./utils')
  3 var webpack = require('webpack')
  4 var config = require('../config')
  5 var merge = require('webpack-merge')
  6 var baseWebpackConfig = require('./webpack.base.conf')
  7 // copy-webpack-plugin,用于将static中的静态文件复制到产品文件夹dist
  8 var CopyWebpackPlugin = require('copy-webpack-plugin')
  9 var HtmlWebpackPlugin = require('html-webpack-plugin')
 10 var ExtractTextPlugin = require('extract-text-webpack-plugin')
 11 // optimize-css-assets-webpack-plugin,用于优化和最小化css资源
 12 var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
 13
 14 var env = config.build.env
 15
 16 var webpackConfig = merge(baseWebpackConfig, {
 17   module: {
 18     // 样式文件的处理规则,对css/sass/scss等不同内容使用相应的styleLoaders
 19     // 由utils配置出各种类型的预处理语言所需要使用的loader,例如sass需要使用sass-loader
 20     rules: utils.styleLoaders({
 21       sourceMap: config.build.productionSourceMap,
 22       extract: true
 23     })
 24   },
 25   // 是否使用source-map
 26   devtool: config.build.productionSourceMap ? '#source-map' : false,
 27   // webpack输出路径和命名规则
 28   output: {
 29     path: config.build.assetsRoot,
 30     filename: utils.assetsPath('js/[name].[chunkhash].js'),
 31     chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
 32   },
 33   // webpack插件
 34   plugins: [
 35     // http://vuejs.github.io/vue-loader/en/workflow/production.html
 36     new webpack.DefinePlugin({
 37       'process.env': env
 38     }),
 39     // 丑化压缩JS代码
 40     new webpack.optimize.UglifyJsPlugin({
 41       compress: {
 42         warnings: false
 43       },
 44       sourceMap: true
 45     }),
 46     // extract css into its own file
 47     // 将css提取到单独的文件
 48     new ExtractTextPlugin({
 49       filename: utils.assetsPath('css/[name].[contenthash].css')
 50     }),
 51     // Compress extracted CSS. We are using this plugin so that possible
 52     // duplicated CSS from different components can be deduped.
 53     // 优化、最小化css代码,如果只简单使用extract-text-plugin可能会造成css重复
 54     // 具体原因可以看npm上面optimize-css-assets-webpack-plugin的介绍
 55     new OptimizeCSSPlugin({
 56       cssProcessorOptions: {
 57         safe: true
 58       }
 59     }),
 60     // generate dist index.html with correct asset hash for caching.
 61     // you can customize output by editing /index.html
 62     // see https://github.com/ampedandwired/html-webpack-plugin
 63     // 将产品文件的引用注入到index.html
 64     new HtmlWebpackPlugin({
 65       filename: config.build.index,
 66       template: 'index.html',
 67       inject: true,
 68       minify: {
 69         // 删除index.html中的注释
 70         removeComments: true,
 71         // 删除index.html中的空格
 72         collapseWhitespace: true,
 73         // 删除各种html标签属性值的双引号
 74         removeAttributeQuotes: true
 75         // more options:
 76         // https://github.com/kangax/html-minifier#options-quick-reference
 77       },
 78       // necessary to consistently work with multiple chunks via CommonsChunkPlugin
 79       // 注入依赖的时候按照依赖先后顺序进行注入,比如,需要先注入vendor.js,再注入app.js
 80       chunksSortMode: 'dependency'
 81     }),
 82     // keep module.id stable when vender modules does not change
 83     new webpack.HashedModuleIdsPlugin(),
 84     // split vendor js into its own file
 85     // 将所有从node_modules中引入的js提取到vendor.js,即抽取库文件
 86     new webpack.optimize.CommonsChunkPlugin({
 87       name: 'vendor',
 88       minChunks: function (module, count) {
 89         // any required modules inside node_modules are extracted to vendor
 90         return (
 91           module.resource &&
 92           /\.js$/.test(module.resource) &&
 93           module.resource.indexOf(
 94             path.join(__dirname, '../node_modules')
 95           ) === 0
 96         )
 97       }
 98     }),
 99     // extract webpack runtime and module manifest to its own file in order to
100     // prevent vendor hash from being updated whenever app bundle is updated
101     // 从vendor中提取出manifest,原因如上
102     new webpack.optimize.CommonsChunkPlugin({
103       name: 'manifest',
104       chunks: ['vendor']
105     }),
106     // copy custom static assets
107     // 将static文件夹里面的静态资源复制到dist/static
108     new CopyWebpackPlugin([
109       {
110         from: path.resolve(__dirname, '../static'),
111         to: config.build.assetsSubDirectory,
112         ignore: ['.*']
113       }
114     ])
115   ]
116 })
117
118 // 如果开启了产品gzip压缩,则利用插件将构建后的产品文件进行压缩
119 if (config.build.productionGzip) {
120   // 一个用于压缩的webpack插件
121   var CompressionWebpackPlugin = require('compression-webpack-plugin')
122
123   webpackConfig.plugins.push(
124     new CompressionWebpackPlugin({
125       asset: '[path].gz[query]',
126       // 压缩算法
127       algorithm: 'gzip',
128       test: new RegExp(
129         '\\.(' +
130         config.build.productionGzipExtensions.join('|') +
131         ')$'
132       ),
133       threshold: 10240,
134       minRatio: 0.8
135     })
136   )
137 }
138
139 // 如果启动了report,则通过插件给出webpack构建打包后的产品文件分析报告
140 if (config.build.bundleAnalyzerReport) {
141   var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142   webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 }
144
145 module.exports = webpackConfig

build/check-versions.js

最后是build文件夹下的check-version.js,它完成对node和npm的版本检测,下面是其代码注释:

 1 // chalk, 用于在控制台输出带颜色字体的插件
 2 var chalk = require('chalk')
 3 // semver, 语义化版本检查插件(The semantic version parser used by npm)
 4 var semver = require('semver')
 5 var packageConfig = require('../package.json')
 6 // shelljs, 执行Unix命令行的插件
 7 var shell = require('shelljs')
 8 // 开辟子进程执行指令cmd并返回结果
 9 function exec (cmd) {
10   return require('child_process').execSync(cmd).toString().trim()
11 }
12
13 // node和npm版本需求
14 var versionRequirements = [
15   {
16     name: 'node',
17     currentVersion: semver.clean(process.version),
18     versionRequirement: packageConfig.engines.node
19   }
20 ]
21
22 if (shell.which('npm')) {
23   versionRequirements.push({
24     name: 'npm',
25     currentVersion: exec('npm --version'),
26     versionRequirement: packageConfig.engines.npm
27   })
28 }
29
30 module.exports = function () {
31   var warnings = []
32   // 依次判断版本是否符合要求
33   for (var i = 0; i < versionRequirements.length; i++) {
34     var mod = versionRequirements[i]
35     if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
36       warnings.push(mod.name + ': ' +
37         chalk.red(mod.currentVersion) + ' should be ' +
38         chalk.green(mod.versionRequirement)
39       )
40     }
41   }
42   // 如果有警告则将其输出到控制台
43   if (warnings.length) {
44     console.log('')
45     console.log(chalk.yellow('To use this template, you must update following to modules:'))
46     console.log()
47     for (var i = 0; i < warnings.length; i++) {
48       var warning = warnings[i]
49       console.log('  ' + warning)
50     }
51     console.log()
52     process.exit(1)
53   }
54 }

四、config文件夹分析

config/index.js

config文件夹下最主要的文件就是index.js了,在这里面描述了开发和构建两种环境下的配置,前面的build文件夹下也有不少文件引用了index.js里面的配置。下面是代码注释:

 1 // see http://vuejs-templates.github.io/webpack for documentation.
 2 var path = require('path')
 3
 4 module.exports = {
 5   // 构建产品时使用的配置
 6   build: {
 7     // 环境变量
 8     env: require('./prod.env'),
 9     // html入口文件
10     index: path.resolve(__dirname, '../dist/index.html'),
11     // 产品文件的存放路径
12     assetsRoot: path.resolve(__dirname, '../dist'),
13     // 二级目录,存放静态资源文件的目录,位于dist文件夹下
14     assetsSubDirectory: 'static',
15     // 发布路径,如果构建后的产品文件有用于发布CDN或者放到其他域名的服务器,可以在这里进行设置
16     // 设置之后构建的产品文件在注入到index.html中的时候就会带上这里的发布路径
17     assetsPublicPath: '/',
18     // 是否使用source-map
19     productionSourceMap: true,
20     // Gzip off by default as many popular static hosts such as
21     // Surge or Netlify already gzip all static assets for you.
22     // Before setting to `true`, make sure to:
23     // npm install --save-dev compression-webpack-plugin
24     // 是否开启gzip压缩
25     productionGzip: false,
26     // gzip模式下需要压缩的文件的扩展名,设置js、css之后就只会对js和css文件进行压缩
27     productionGzipExtensions: ['js', 'css'],
28     // Run the build command with an extra argument to
29     // View the bundle analyzer report after build finishes:
30     // `npm run build --report`
31     // Set to `true` or `false` to always turn it on or off
32     // 是否展示webpack构建打包之后的分析报告
33     bundleAnalyzerReport: process.env.npm_config_report
34   },
35   // 开发过程中使用的配置
36   dev: {
37     // 环境变量
38     env: require('./dev.env'),
39     // dev-server监听的端口
40     port: 8080,
41     // 是否自动打开浏览器
42     autoOpenBrowser: true,
43     // 静态资源文件夹
44     assetsSubDirectory: 'static',
45     // 发布路径
46     assetsPublicPath: '/',
47     // 代理配置表,在这里可以配置特定的请求代理到对应的API接口
48     // 例如将'localhost:8080/api/xxx'代理到'www.example.com/api/xxx'
49     proxyTable: {},
50     // CSS Sourcemaps off by default because relative paths are "buggy"
51     // with this option, according to the CSS-Loader README
52     // (https://github.com/webpack/css-loader#sourcemaps)
53     // In our experience, they generally work as expected,
54     // just be aware of this issue when enabling this option.
55     // 是否开启 cssSourceMap
56     cssSourceMap: false
57   }
58 }

config/dev.env.js、config/prod.env.js和config/test.env.js

这三个文件就简单设置了环境变量而已,没什么特别的。

转载于:https://www.cnblogs.com/zhaobao1830/p/7600223.html

转:vue-cli的webpack模板项目配置文件分析相关推荐

  1. vue-cli的webpack模板项目配置文件分析[转]

    vue-cli的webpack模板项目配置文件分析[转] 原文出处:http://blog.csdn.net/hongchh/article/details/55113751 由于最近在vue-cli ...

  2. vue-cli的webpack模板项目配置文件分析

    由于最近在vue-cli生成的webpack模板项目的基础上写一个小东西,开发过程中需要改动到build和config里面一些相关的配置,所以刚好趁此机会将所有配置文件看一遍,理一理思路,也便于以后修 ...

  3. vue-cli的webpack模板项目配置文件分析(转)

    由于最近在vue-cli生成的webpack模板项目的基础上写一个小东西,开发过程中需要改动到build和config里面一些相关的配置,所以刚好趁此机会将所有配置文件看一遍,理一理思路,也便于以后修 ...

  4. vue-cli的webpack模板项目配置文件说明

    如果没有vue-cli,那么进行vue项目的开发环境配置将是很费力的一件事情,现在脚手架可以快速构建一个开发环境,是很不错的.不过对于脚手架构建的配置,还是要大概了解一下,方便自己调试配置. 初始化一 ...

  5. 《转》vue-cli的webpack模板项目配置文件注释

    一.文件结构 本文主要分析开发(dev)和构建(build)两个过程涉及到的文件,故下面文件结构仅列出相应的内容. ├─build │ ├─build.js │ ├─check-versions.js ...

  6. vue-cli项目配置文件分析

    最近在vue-cli生成的webpack模板项目的基础上开发了一些项目,开发过程中遇到很多坑,并且需要改动build和config里面一些相关的配置,查阅,学习,总结,分享. 一.配置文件结构 本文主 ...

  7. vuecli启动的服务器位置,webpack – 在vue cli 3生成的项目中启动dev服务器

    我使用npm i -g @ vue / cli在我的 Windows系统上全局安装了vue cli 3. 然后我使用vue create vue-project生成了一个项目 我通过提示选择了所需的插 ...

  8. 猿创征文|【Vue五分钟】 Vue Cli脚手架创建一个项目

    目录 前言 一.创建项目的操作步骤 选择路由模式 选择CSS预编译器 选择如何存放配置 自动下载项目所需的包文件 二.启动vue项目 1.项目目录 2.启动项目 3.浏览器打开项目首页界面 三.项目的 ...

  9. egg html模板,egg+vue服务端渲染模板项目介绍

    egg-vue-webpack-boilerplate 基于 Egg + Vue + Webpack SSR 服务端渲染和 CSR 前端渲染工程骨架项目,包括前台系统(SSR MPA)和后台管理系统( ...

最新文章

  1. pidstat 命令详解(转载)
  2. 基于qml创建最简单的图像处理程序(1)-基于qml创建界面
  3. Java 成员变量和局部变量
  4. 批量生成数组_JavaScript【重温基础】13.迭代器和生成器
  5. java读取gpx文件,从Leaflet导出GPX文件
  6. python中的单例模式_Python单例模式
  7. MySQL学习(五、数据操作语言DML和事务处理语言TCL)
  8. MP3转换器下载 - 通用mp3转换器
  9. 无线领夹式麦克风方案,专门为USB-C接口手机打造的直播方案
  10. WPE封包外挂教程(下)
  11. 大华海康NVR录像JAVA下载及WEB播放
  12. 国产低代码开发平台,这5个值得一试
  13. 基于arm板linux的语音合成,基于ARM7和μCLinux的中文电子语音阅读系统的研究与应用...
  14. 王文京:纵横30年,阵阵桂花香
  15. 不同PyTorch版本训练同一个代码结果差异巨大
  16. 一次HTTP(S)请求究竟需要多少流量?Wireshark抓包分析
  17. 赶紧拿走!这4个实用的软件关键时刻能帮上你大忙!
  18. python无法调用urlopen_python urlopen 不了一个url 而用curl 是可以的
  19. 有了这几个webp转换工具,快速完成图片转换工作
  20. 计算机显示器桌面变小,电脑显示器显示变小怎么办

热门文章

  1. linux做视频 加字幕,ubuntu16.04给视频添加字幕方法 ubuntu16.04如何给视频添加字幕...
  2. 2.使用Gateway实现token校验
  3. 微信工具(Python)实现备注管理和群发消息
  4. 名家专栏 况杰 主动下架比被动下架要好
  5. OpenCV打开相机,调整窗口大小位置
  6. 打造百万级访问网站的技术准备
  7. Android开发OMA(Open Mobile Api)
  8. 工简教育:消防工程师证书的用途
  9. matlab与c/c++混合...,matlab与c/c++ 混合编程之 MCR | 学步园
  10. 计算机应用领域中CAL代表,计算机应用领域.doc