转载地址:
一、文件结构
本文主要分析开发(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.js10 │ ├─webpack.prod.conf.js11 │ └─webpack.test.conf.js12 ├─config13 │ ├─dev.env.js14 │ ├─index.js15 │ ├─prod.env.js16 │ └─test.env.js17 ├─...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文件。该文件主要完成下面几件事情:
- 检查node和npm的版本、引入相关插件和配置
- webpack对源码进行编译打包并返回compiler对象
- 创建express服务器
- 配置开发中间件(webpack-dev-middleware)和热重载中间件(webpack-hot-middleware)
- 挂载代理服务和中间件
- 配置静态资源
- 启动服务器监听特定端口(8080)
- 自动打开浏览器并打开特定网址(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主要完成了下面这些事情:
- 配置webpack编译入口
- 配置webpack输出路径和命名规则
- 配置模块resolve规则
- 配置不同类型模块的处理规则
说明: 这个配置里面只配置了.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.assetsPublicPath26 : config.dev.assetsPublicPath27 },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: false38 },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: vueLoaderConfig55 },56 { // 对src和test文件夹下的.js文件使用babel-loader将es6+的代码转成es557 test: /\.js$/,58 loader: 'babel-loader',59 include: [resolve('src'), resolve('test')]60 },61 { // 对图片资源文件使用url-loader62 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-loader72 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-loader82 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.assetsSubDirectory11 : config.dev.assetsSubDirectory12 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-map25 sourceMap: options.sourceMap26 }27 }28 29 // generate loader string to be used with extract text plugin30 // 生成各种loader配置,并且配置了extract-text-pulgin31 function generateLoaders (loader, loaderOptions) {32 // 默认是css-loader33 var loaders = [cssLoader]34 // 如果非css,则增加一个处理预编译语言的loader并设好相关配置属性35 // 例如generateLoaders('less'),这里就会push一个less-loader36 // less-loader先将less编译成css,然后再由css-loader去处理css37 // 其他sass、scss等语言也是一样的过程38 if (loader) {39 loaders.push({40 loader: loader + '-loader',41 options: Object.assign({}, loaderOptions, {42 sourceMap: options.sourceMap43 })44 })45 }46 47 // Extract CSS when that option is specified48 // (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去处理
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: isProduction10 ? config.build.productionSourceMap11 : config.dev.cssSourceMap,12 // 是否提取样式到单独的文件13 extract: isProduction14 }),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主要完成下面几件事:
- loading动画
- 删除目标文件夹
- 执行webpack构建
- 输出信息
说明: 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 err24 // 执行webpack构建打包,完成之后在终端输出构建完成的相关信息或者输出报错信息并退出程序25 webpack(webpackConfig, function (err, stats) {26 spinner.stop()27 if (err) throw err28 process.stdout.write(stats.toString({29 colors: true,30 modules: false,31 children: false,32 chunks: false,33 chunkModules: false34 }) + '\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基础上的进一步完善。主要完成下面几件事情:
- 合并基础的webpack配置
- 配置样式文件的处理规则,styleLoaders
- 配置webpack的输出
- 配置webpack插件
- gzip模式下的webpack插件配置
- 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 to100 // prevent vendor hash from being updated whenever app bundle is updated101 // 从vendor中提取出manifest,原因如上102 new webpack.optimize.CommonsChunkPlugin({103 name: 'manifest',104 chunks: ['vendor']105 }),106 // copy custom static assets107 // 将static文件夹里面的静态资源复制到dist/static108 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.8135 })136 )137 }138 139 // 如果启动了report,则通过插件给出webpack构建打包后的产品文件分析报告140 if (config.build.bundleAnalyzerReport) {141 var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin142 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.node19 }20 ]21 22 if (shell.which('npm')) {23 versionRequirements.push({24 name: 'npm',25 currentVersion: exec('npm --version'),26 versionRequirement: packageConfig.engines.npm27 })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-map19 productionSourceMap: true,20 // Gzip off by default as many popular static hosts such as21 // 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-plugin24 // 是否开启gzip压缩25 productionGzip: false,26 // gzip模式下需要压缩的文件的扩展名,设置js、css之后就只会对js和css文件进行压缩27 productionGzipExtensions: ['js', 'css'],28 // Run the build command with an extra argument to29 // 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 off32 // 是否展示webpack构建打包之后的分析报告33 bundleAnalyzerReport: process.env.npm_config_report34 },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 README52 // (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 // 是否开启 cssSourceMap56 cssSourceMap: false57 }58 }
config/dev.env.js、config/prod.env.js和config/test.env.js
这三个文件就简单设置了环境变量而已,没什么特别的。