轉載地址:http://blog.csdn.net/hongchh/article/details/55113751css
本文主要分析開發(dev)和構建(build)兩個過程涉及到的文件,故下面文件結構僅列出相應的內容。html
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文件,咱們能夠從這兩個文件開始進行代碼閱讀分析。vue
首先來看執行」npm run dev」時候最早執行的build/dev-server.js文件。該文件主要完成下面幾件事情:node
說明: express服務器提供靜態文件服務,不過它還使用了http-proxy-middleware,一個http請求代理的中間件。前端開發過程當中須要使用到後臺的API的話,能夠經過配置proxyTable來將相應的後臺請求代理到專用的API服務器。webpack
詳情請看代碼註釋:git
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 }
從代碼中看到,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。es6
webpack.base.conf.js主要完成了下面這些事情:github
說明: 這個配置裏面只配置了.js、.vue、圖片、字體等幾類文件的處理規則,若是須要處理其餘文件能夠在module.rules裏面另行配置。web
具體請看代碼註釋:
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 }
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 }
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 }
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 })
講完了開發環境下的配置,下面開始來看構建環境下的配置。執行」npm run build」的時候首先執行的是build/build.js文件,build.js主要完成下面幾件事:
說明: 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 })
構建的時候用到的webpack配置來自webpack.prod.conf.js,該配置一樣是在webpack.base.conf基礎上的進一步完善。主要完成下面幾件事情:
說明: 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-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文件夾下最主要的文件就是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 }
這三個文件就簡單設置了環境變量而已,沒什麼特別的。