您好,登錄后才能下訂單哦!
這篇文章主要講解了“vue-cli目錄結構詳細講解”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“vue-cli目錄結構詳細講解”吧!
一個vue-cli的項目結構如下:
目錄
結構預覽
├─build // 保存一些webpack的初始化配置,項目構建 │ ├─build.js // 生產環境構建 │ ├─check-version.js // 檢查npm、node版本 │ ├─vue-loader.conf.js // webpack loader配置 │ ├─webpack.base.conf.js// webpack基礎配置 │ ├─webpack.dev.conf.js // 開發環境配置,構建本地開發服務器 │ ├─webpack.prod.conf.js// 生產環境的配置 │ ├─config // config文件夾保存一些項目初始化的配置 │ ├─dev.env.js // 開發環境的配置 │ ├─index.js // 項目一些配置變量 │ ├─prod.env.js // 生產環境的配置 │ ├─dist // 打包后的項目 ├─node_modules // 依賴包 │ ├─src // 源碼目錄 │ ├─assets // 靜態文件目錄 │ ├─components // 組件文件 │ ├─router // 路由 │ ├─App.vue // 是項目入口文件 │ ├─main.js // 是項目的核心文件,入口 ├─static // 靜態資源目錄 ├─.babelrc // Babel的配置文件 ├─.editorconfig // 代碼規范配置文件 ├─.gitignore // git忽略配置文件 ├─.postcssrc.js // postcss插件配置文件 ├─index.html // 頁面入口文件 ├─package-lock.json // 項目包管控文件 ├─package.json // 項目配置 └─README.md // 項目說明書
結構解析
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服務器。
// 檢查NodeJS和npm的版本 require('./check-versions')() // 獲取基本配置 var config = require('../config') // 如果Node的環境變量中沒有設置當前的環境(NODE_ENV),則使用config中的dev環境配置作為當前的環境 if (!process.env.NODE_ENV) { process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) } // opn是一個可以調用默認軟件打開網址、圖片、文件等內容的插件 // 這里用它來調用默認瀏覽器打開dev-server監聽的端口,例如:localhost:8080 var opn = require('opn') var path = require('path') var express = require('express') var webpack = require('webpack') // http-proxy-middleware是一個express中間件,用于將http請求代理到其他服務器 // 例:localhost:8080/api/xxx --> localhost:3000/api/xxx // 這里使用該插件可以將前端開發中涉及到的請求代理到提供服務的后臺服務器上,方便與服務器對接 var proxyMiddleware = require('http-proxy-middleware') // 開發環境下的webpack配置 var webpackConfig = require('./webpack.dev.conf') // dev-server 監聽的端口,如果沒有在命令行傳入端口號,則使用config.dev.port設置的端口,例如8080 var port = process.env.PORT || config.dev.port // 用于判斷是否要自動打開瀏覽器的布爾變量,當配置文件中沒有設置自動打開瀏覽器的時候其值為 false var autoOpenBrowser = !!config.dev.autoOpenBrowser // HTTP代理表,指定規則,將某些API請求代理到相應的服務器 var proxyTable = config.dev.proxyTable // 創建express服務器 var app = express() // webpack根據配置開始編譯打包源碼并返回compiler對象 var compiler = webpack(webpackConfig) // webpack-dev-middleware將webpack編譯打包后得到的產品文件存放在內存中而沒有寫進磁盤 // 將這個中間件掛到express上使用之后即可提供這些編譯后的產品文件服務 var devMiddleware = require('webpack-dev-middleware')(compiler, { publicPath: webpackConfig.output.publicPath, // 設置訪問路徑為webpack配置中的output里面所對應的路徑 quiet: true // 設置為true,使其不要在控制臺輸出日志 }) // webpack-hot-middleware,用于實現熱重載功能的中間件 var hotMiddleware = require('webpack-hot-middleware')(compiler, { log: false, // 關閉控制臺的日志輸出 heartbeat: 2000 // 發送心跳包的頻率 }) // webpack(重新)編譯打包完成后并將js、css等文件inject到html文件之后,通過熱重載中間件強制頁面刷新 compiler.plugin('compilation', function (compilation) { compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { hotMiddleware.publish({ action: 'reload' }) cb() }) }) // 根據 proxyTable 中的代理請求配置來設置express服務器的http代理規則 Object.keys(proxyTable).forEach(function (context) { var options = proxyTable[context] // 格式化options,例如將'www.example.com'變成{ target: 'www.example.com' } if (typeof options === 'string') { options = { target: options } } app.use(proxyMiddleware(options.filter || context, options)) }) // handle fallback for HTML5 history API // 重定向不存在的URL,用于支持SPA(單頁應用) // 例如使用vue-router并開啟了history模式 app.use(require('connect-history-api-fallback')()) // serve webpack bundle output // 掛載webpack-dev-middleware中間件,提供webpack編譯打包后的產品文件服務 app.use(devMiddleware) // enable hot-reload and state-preserving // compilation error display // 掛載熱重載中間件 app.use(hotMiddleware) // 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 devServer = require('./build/dev-server') // devServer.ready.then(() => {...}) // if (...) { devServer.close() } module.exports = { ready: readyPromise, close: () => { server.close() } }
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里面另行配置。
var path = require('path') var fs = require('fs') var utils = require('./utils') var config = require('../config') var vueLoaderConfig = require('./vue-loader.conf') // 獲取絕對路徑 function resolve (dir) { return path.join(__dirname, '..', dir) } module.exports = { // webpack入口文件 entry: { app: './src/main.js' }, // webpack輸出路徑和命名規則 output: { // webpack輸出的目標文件夾路徑(例如:/dist) path: config.build.assetsRoot, // webpack輸出bundle文件命名格式 filename: '[name].js', // webpack編譯輸出的發布路徑(例如'//cdn.xxx.com/app/') publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, // 模塊resolve的規則 resolve: { extensions: ['.js', '.vue', '.json'], // 別名,方便引用模塊,例如有了別名之后, // import Vue from 'vue/dist/vue.common.js'可以寫成 import Vue from 'vue' alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), }, symlinks: false }, // 不同類型模塊的處理規則 module: { rules: [ {// 對src和test文件夾下的.js和.vue文件使用eslint-loader進行代碼規范檢查 test: /\.(js|vue)$/, loader: 'eslint-loader', enforce: 'pre', include: [resolve('src'), resolve('test')], options: { formatter: require('eslint-friendly-formatter') } }, {// 對所有.vue文件使用vue-loader進行編譯 test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, {// 對src和test文件夾下的.js文件使用babel-loader將es6+的代碼轉成es5 test: /\.js$/, loader: 'babel-loader', include: [resolve('src'), resolve('test')] }, {// 對圖片資源文件使用url-loader test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { // 小于10K的圖片轉成base64編碼的dataURL字符串寫到代碼中 limit: 10000, // 其他的圖片轉移到靜態資源文件夾 name: utils.assetsPath('img/[name].[hash:7].[ext]') } }, {// 對多媒體資源文件使用url-loader test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { // 小于10K的資源轉成base64編碼的dataURL字符串寫到代碼中 limit: 10000, // 其他的資源轉移到靜態資源文件夾 name: utils.assetsPath('media/[name].[hash:7].[ext]') } }, {// 對字體資源文件使用url-loader test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { // 小于10K的資源轉成base64編碼的dataURL字符串寫到代碼中 limit: 10000, // 其他的資源轉移到靜態資源文件夾 name: utils.assetsPath('fonts/[name].[hash:7].[ext]') } } ] } }
webpack.dev.conf.js
接下來看webpack.dev.conf.js,這里面在webpack.base.conf的基礎上增加完善了開發環境下面的配置,主要包括下面幾件事情:
將webpack的熱重載客戶端代碼添加到每個entry對應的應用
合并基礎的webpack配置
配置樣式文件的處理規則,styleLoaders
配置Source Maps
配置webpack插件
var utils = require('./utils') var webpack = require('webpack') var config = require('../config') // webpack-merge是一個可以合并數組和對象的插件 var merge = require('webpack-merge') var baseWebpackConfig = require('./webpack.base.conf') // html-webpack-plugin用于將webpack編譯打包后的產品文件注入到html模板中 // 即自動在index.html里面加上<link>和<script>標簽引用webpack打包后的文件 var HtmlWebpackPlugin = require('html-webpack-plugin') // friendly-errors-webpack-plugin用于更友好地輸出webpack的警告、錯誤等信息 var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') // add hot-reload related code to entry chunks // 給每個入口頁面(應用)加上dev-client,用于跟dev-server的熱重載插件通信,實現熱更新 Object.keys(baseWebpackConfig.entry).forEach(function (name) { baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) }) module.exports = merge(baseWebpackConfig, { module: { // 樣式文件的處理規則,對css/sass/scss等不同內容使用相應的styleLoaders // 由utils配置出各種類型的預處理語言所需要使用的loader,例如sass需要使用sass-loader rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) }, // cheap-module-eval-source-map is faster for development // 使用這種source-map更快 devtool: '#cheap-module-eval-source-map', // webpack插件 plugins: [ new webpack.DefinePlugin({ 'process.env': config.dev.env }), // 開啟webpack熱更新功能 new webpack.HotModuleReplacementPlugin(), // webpack編譯過程中出錯的時候跳過報錯階段,不會阻塞編譯,在編譯結束后報錯 new webpack.NoEmitOnErrorsPlugin(), // 自動將依賴注入html模板,并輸出最終的html文件到目標文件夾 new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), new FriendlyErrorsPlugin() ] })
utils
此配置文件是vue開發環境的wepack相關配置文件,主要用來處理css-loader和vue-style-loader
// 引入nodejs路徑模塊 var path = require('path') // 引入config目錄下的index.js配置文件 var config = require('../config') // 引入extract-text-webpack-plugin插件,用來將css提取到單獨的css文件中 // 詳情請看(1) var ExtractTextPlugin = require('extract-text-webpack-plugin') // exports其實就是一個對象,用來導出方法的最終還是使用module.exports,此處導出assetsPath exports.assetsPath = function (_path) { // 如果是生產環境assetsSubDirectory就是'static',否則還是'static',哈哈哈 var assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory // path.join和path.posix.join的區別就是,前者返回的是完整的路徑,后者返回的是完整路徑的相對根路徑 // 也就是說path.join的路徑是C:a/a/b/xiangmu/b,那么path.posix.join就是b return path.posix.join(assetsSubDirectory, _path) // 所以這個方法的作用就是返回一個干凈的相對根路徑 } // 下面是導出cssLoaders的相關配置 exports.cssLoaders = function (options) { // options如果沒值就是空對象 options = options || {} // cssLoader的基本配置 var cssLoader = { loader: 'css-loader', options: { // options是用來傳遞參數給loader的 // minimize表示壓縮,如果是生產環境就壓縮css代碼 minimize: process.env.NODE_ENV === 'production', // 是否開啟cssmap,默認是false sourceMap: options.sourceMap } } // generate loader string to be used with extract text plugin function generateLoaders (loader, loaderOptions) { // 將上面的基礎cssLoader配置放在一個數組里面 var loaders = [cssLoader] // 如果該函數傳遞了單獨的loader就加到這個loaders數組里面,這個loader可能是less,sass之類的 if (loader) { loaders.push({ // 加載對應的loader 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) // 注意這個extract是自定義的屬性,可以定義在options里面,主要作用就是當配置為true就把文件單獨提取,false表示不單獨提取,這個可以在使用的時候單獨配置,瞬間覺得vue作者好牛逼 if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader' }) } else { return ['vue-style-loader'].concat(loaders) } // 上面這段代碼就是用來返回最終讀取和導入loader,來處理對應類型的文件 } // https://vue-loader.vuejs.org/en/configurations/extract-css.html return { css: generateLoaders(), // css對應 vue-style-loader 和 css-loader postcss: generateLoaders(), // postcss對應 vue-style-loader 和 css-loader less: generateLoaders('less'), // less對應 vue-style-loader 和 less-loader sass: generateLoaders('sass', { indentedSyntax: true }), // sass對應 vue-style-loader 和 sass-loader scss: generateLoaders('sass'), // scss對應 vue-style-loader 和 sass-loader stylus: generateLoaders('stylus'), // stylus對應 vue-style-loader 和 stylus-loader styl: generateLoaders('stylus') // styl對應 vue-style-loader 和 styl-loader } } // Generate loaders for standalone style files (outside of .vue) // 下面這個主要處理import這種方式導入的文件類型的打包,上面的exports.cssLoaders是為這一步服務的 exports.styleLoaders = function (options) { var output = [] // 下面就是生成的各種css文件的loader對象 var loaders = exports.cssLoaders(options) for (var extension in loaders) { // 把每一種文件的laoder都提取出來 var loader = loaders[extension] output.push({ // 把最終的結果都push到output數組中,大事搞定 test: new RegExp('\\.' + extension + '$'), use: loader }) } return output }
extract-text-webpack-plugin插件是用來將文本從bundle中提取到一個單獨的文件中
const ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { module: { rules: [ { test: /\.css$/, //主要用來處理css文件 use: ExtractTextPlugin.extract({ fallback: "style-loader", // fallback表示如果css文件沒有成功導入就使用style-loader導入 use: "css-loader" // 表示使用css-loader從js讀取css文件 }) } ], plugins: [ new ExtractTextPlugin("styles.css") //表示生成styles.css文件 ] } }
vue-loader.conf.js
var utils = require('./utils') var config = require('../config') var isProduction = process.env.NODE_ENV === 'production' module.exports = { // 處理.vue文件中的樣式 loaders: utils.cssLoaders({ // 是否打開source-map sourceMap: isProduction ? config.build.productionSourceMap : config.dev.cssSourceMap, // 是否提取樣式到單獨的文件 extract: isProduction }), transformToRequire: { video: 'src', source: 'src', img: 'src', image: 'xlink:href' } }
dev-client.js
dev-client.js里面主要寫了瀏覽器端代碼,用于實現webpack的熱更新。
/* eslint-disable */ // 實現瀏覽器端的EventSource,用于跟服務器雙向通信 // webpack熱重載客戶端跟dev-server上的熱重載插件之間需要進行雙向通信 // 服務端webpack重新編譯后,會向客戶端推送信息,告訴客戶端進行更新 require('eventsource-polyfill') // webpack熱重載客戶端 var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') // 客戶端收到更新動作,執行頁面刷新 hotClient.subscribe(function (event) { if (event.action === 'reload') { window.location.reload() } })
build.js
執行”npm run build”的時候首先執行的是build/build.js文件,build.js主要完成下面幾件事:
loading動畫
刪除目標文件夾
執行webpack構建
輸出信息
說明: webpack編譯之后會輸出到配置里面指定的目標文件夾;刪除目標文件夾之后再創建是為了去除舊的內容,以免產生不可預測的影響。
// 檢查NodeJS和npm的版本 require('./check-versions')() process.env.NODE_ENV = 'production' // ora,一個可以在終端顯示spinner的插件 var ora = require('ora') // rm,用于刪除文件或文件夾的插件 var rm = require('rimraf') var path = require('path') // chalk,用于在控制臺輸出帶顏色字體的插件 var chalk = require('chalk') var webpack = require('webpack') var config = require('../config') var webpackConfig = require('./webpack.prod.conf') var spinner = ora('building for production...') spinner.start() // 開啟loading動畫 // 首先將整個dist文件夾以及里面的內容刪除,以免遺留舊的沒用的文件 // 刪除完成后才開始webpack構建打包 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { if (err) throw err // 執行webpack構建打包,完成之后在終端輸出構建完成的相關信息或者輸出報錯信息并退出程序 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' )) }) })
webpack.prod.conf.js
構建的時候用到的webpack配置來自webpack.prod.conf.js,該配置同樣是在webpack.base.conf基礎上的進一步完善。主要完成下面幾件事情:
合并基礎的webpack配置
配置樣式文件的處理規則,styleLoaders
配置webpack的輸出
配置webpack插件
gzip模式下的webpack插件配置
webpack-bundle分析
說明: webpack插件里面多了丑化壓縮代碼以及抽離css文件等插件。
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') webpackConfig.plugins.push( new CompressionWebpackPlugin({ asset: '[path].gz[query]', // 壓縮算法 algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 }) ) } // 如果啟動了report,則通過插件給出webpack構建打包后的產品文件分析報告 if (config.build.bundleAnalyzerReport) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports = webpackConfig
check-versions.js
// chalk, 用于在控制臺輸出帶顏色字體的插件 var chalk = require('chalk') // semver, 語義化版本檢查插件(The semantic version parser used by npm) var semver = require('semver') var packageConfig = require('../package.json') // shelljs, 執行Unix命令行的插件 var shell = require('shelljs') // 開辟子進程執行指令cmd并返回結果 function exec (cmd) { return require('child_process').execSync(cmd).toString().trim() } // node和npm版本需求 var 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 () { var warnings = [] // 依次判斷版本是否符合要求 for (var i = 0; i < versionRequirements.length; i++) { var 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 (var i = 0; i < warnings.length; i++) { var warning = warnings[i] console.log(' ' + warning) } console.log() process.exit(1) } }
config
index.js
config文件夾下最主要的文件就是index.js了,在這里面描述了開發和構建兩種環境下的配置,前面的build文件夾下也有不少文件引用了index.js里面的配置
// 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 } } 'use strict' const path = require('path') module.exports = { dev: { // 開發環境下面的配置 assetsSubDirectory: 'static',//子目錄,一般存放css,js,image等文件 assetsPublicPath: '/',//根目錄 proxyTable: {},//可利用該屬性解決跨域的問題 host: 'localhost', // 地址 port: 8080, //端口號設置,端口號占用出現問題可在此處修改 autoOpenBrowser: false,//是否在編譯(輸入命令行npm run dev)后打開http://localhost:8080/頁面,以前配置為true,近些版本改為false,個人偏向習慣自動打開頁面 errorOverlay: true,//瀏覽器錯誤提示 notifyOnErrors: true,//跨平臺錯誤提示 poll: false, //使用文件系統(file system)獲取文件改動的通知devServer.watchOptions devtool: 'cheap-module-eval-source-map',//增加調試,該屬性為原始源代碼(僅限行)不可在生產環境中使用 cacheBusting: true,//使緩存失效 cssSourceMap: true//代碼壓縮后進行調bug定位將非常困難,于是引入sourcemap記錄壓縮前后的位置信息記錄,當產生錯誤時直接定位到未壓縮前的位置,將大大的方便我們調試 }, build: { // 生產環境下面的配置 index: path.resolve(__dirname, '../dist/index.html'),//index編譯后生成的位置和名字,根據需要改變后綴,比如index.php assetsRoot: path.resolve(__dirname, '../dist'),//編譯后存放生成環境代碼的位置 assetsSubDirectory: 'static',//js,css,images存放文件夾名 assetsPublicPath: '/',//發布的根目錄,通常本地打包dist后打開文件會報錯,此處修改為./。如果是上線的文件,可根據文件存放位置進行更改路徑 productionSourceMap: true, devtool: '#source-map',//① //unit的gzip命令用來壓縮文件,gzip模式下需要壓縮的文件的擴展名有js和css productionGzip: false, productionGzipExtensions: ['js', 'css'], bundleAnalyzerReport: process.env.npm_config_report } }
prod.env.js
當開發是調取dev.env.js的開發環境配置,發布時調用prod.env.js的生產環境配置
'use strict' module.exports = { NODE_ENV: '"production"' }
dev.env.js
config內的文件其實是服務于build的,大部分是定義一個變量export出去。
'use strict'//采用嚴格模式 const merge = require('webpack-merge')//① const prodEnv = require('./prod.env') //webpack-merge提供了一個合并函數,它將數組和合并對象創建一個新對象。 //如果遇到函數,它將執行它們,通過算法運行結果,然后再次將返回的值封裝在函數中.這邊將dev和prod進行合并 module.exports = merge(prodEnv, { NODE_ENV: '"development"' })
src
①、assets文件:腳手架自動會放入一個圖片在里面作為初始頁面的logo。平常我們使用的時候會在里面建立js,css,img,fonts等文件夾,作為靜態資源調用
②、components文件夾:用來存放組件,合理地使用組件可以高效地實現復用等功能,從而更好地開發項目。一般情況下比如創建頭部組件的時候,我們會新建一個header的文件夾,然后再新建一個header.vue的文件
③、router文件夾:該文件夾下有一個叫index.js文件,用于實現頁面的路由跳轉,具體使用請點擊→vue-router傳送門
④、App.vue:作為我們的主組件,可通過使用<router-view/>開放入口讓其他的頁面組件得以顯示。
⑤、main.js:作為我們的入口文件,主要作用是初始化vue實例并使用需要的插件,小型項目省略router時可放在該處
.babelrc
{ //制定轉碼的規則 "presets": [ //env是使用babel-preset-env插件將js進行轉碼成es5,并且設置不轉碼的AMD,COMMONJS的模塊文件,制定瀏覽器的兼容 ["env", { "modules": false, "targets": { "browsers": ["> 1%", "last 2 versions", "not ie <= 8"] } }], "stage-2" ], "plugins": ["transform-vue-jsx", "transform-runtime"]//① }
.postcessrc.js
.postcssrc.js文件其實是postcss-loader包的一個配置,在webpack的舊版本可以直接在webpack.config.js中配置,現版本中postcss的文檔示例獨立出.postcssrc.js,里面寫進去需要使用到的插件
module.exports = { "plugins": { "postcss-import": {},//① "postcss-url": {},//② "autoprefixer": {}//③ } }
package.json
package.json來制定名單,需要哪些npm包來參與到項目中來,npm install命令根據這個配置文件增減來管理本地的安裝包
{ //從name到private都是package的配置信息,也就是我們在腳手架搭建中輸入的項目描述 "name": "shop",//項目名稱:不能以.(點)或者_(下劃線)開頭,不能包含大寫字母,具有明確的的含義與現有項目名字不重復 "version": "1.0.0",//項目版本號:遵循“大版本.次要版本.小版本” "description": "A Vue.js project",//項目描述 "author": "qietuniu",//作者名字 "private": true,//是否私有 //scripts中的子項即是我們在控制臺運行的腳本的縮寫 "scripts": { //①webpack-dev-server:啟動了http服務器,實現實時編譯; //inline模式會在webpack.config.js入口配置中新增webpack-dev-server/client?http://localhost:8080/的入口,使得我們訪問路徑為localhost:8080/index.html(相應的還有另外一種模式Iframe); //progress:顯示打包的進度 "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev",//與npm run dev相同,直接運行開發環境 "build": "node build/build.js"//使用node運行build文件 }, //②dependencies(項目依賴庫):在安裝時使用--save則寫入到dependencies "dependencies": { "vue": "^2.5.2",//vue.js "vue-router": "^3.0.1"//vue的路由插件 }, //和devDependencies(開發依賴庫):在安裝時使用--save-dev將寫入到devDependencies "devDependencies": { "autoprefixer": "^7.1.2",//autoprefixer作為postcss插件用來解析CSS補充前綴,例如 display: flex會補充為display:-webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex。 //babel:以下幾個babel開頭的都是針對es6解析的插件。用最新標準編寫的 JavaScript 代碼向下編譯成可以在今天隨處可用的版本 "babel-core": "^6.22.1",//babel的核心,把 js 代碼分析成 ast ,方便各個插件分析語法進行相應的處理。 "babel-helper-vue-jsx-merge-props": "^2.0.3",//預制babel-template函數,提供給vue,jsx等使用 "babel-loader": "^7.1.1",//使項目運行使用Babel和webpack來傳輸js文件,使用babel-core提供的api進行轉譯 "babel-plugin-syntax-jsx": "^6.18.0",//支持jsx "babel-plugin-transform-runtime": "^6.22.0",//避免編譯輸出中的重復,直接編譯到build環境中 "babel-plugin-transform-vue-jsx": "^3.5.0",//babel轉譯過程中使用到的插件,避免重復 "babel-preset-env": "^1.3.2",//轉為es5,transform階段使用到的插件之一 "babel-preset-stage-2": "^6.22.0",//ECMAScript第二階段的規范 "chalk": "^2.0.1",//用來在命令行輸出不同顏色文字 "copy-webpack-plugin": "^4.0.1",//拷貝資源和文件 "css-loader": "^0.28.0",//webpack先用css-loader加載器去解析后綴為css的文件,再使用style-loader生成一個內容為最終解析完的css代碼的style標簽,放到head標簽里 "extract-text-webpack-plugin": "^3.0.0",//將一個以上的包里面的文本提取到單獨文件中 "file-loader": "^1.1.4",//③打包壓縮文件,與url-loader用法類似 "friendly-errors-webpack-plugin": "^1.6.1",//識別某些類別的WebPACK錯誤和清理,聚合和優先排序,以提供更好的開發經驗 "html-webpack-plugin": "^2.30.1",//簡化了HTML文件的創建,引入了外部資源,創建html的入口文件,可通過此項進行多頁面的配置 "node-notifier": "^5.1.2",//支持使用node發送跨平臺的本地通知 "optimize-css-assets-webpack-plugin": "^3.2.0",//壓縮提取出的css,并解決ExtractTextPlugin分離出的js重復問題(多個文件引入同一css文件) "ora": "^1.2.0",//加載(loading)的插件 "portfinder": "^1.0.13",//查看進程端口 "postcss-import": "^11.0.0",//可以消耗本地文件、節點模塊或web_modules "postcss-loader": "^2.0.8",//用來兼容css的插件 "postcss-url": "^7.2.1",//URL上重新定位、內聯或復制 "rimraf": "^2.6.0",//節點的UNIX命令RM—RF,強制刪除文件或者目錄的命令 "semver": "^5.3.0",//用來對特定的版本號做判斷的 "shelljs": "^0.7.6",//使用它來消除shell腳本在UNIX上的依賴性,同時仍然保留其熟悉和強大的命令,即可執行Unix系統命令 "uglifyjs-webpack-plugin": "^1.1.1",//壓縮js文件 "url-loader": "^0.5.8",//壓縮文件,可將圖片轉化為base64 "vue-loader": "^13.3.0",//VUE單文件組件的WebPACK加載器 "vue-style-loader": "^3.0.1",//類似于樣式加載程序,您可以在CSS加載器之后將其鏈接,以將CSS動態地注入到文檔中作為樣式標簽 "vue-template-compiler": "^2.5.2",//這個包可以用來預編譯VUE模板到渲染函數,以避免運行時編譯開銷和CSP限制 "webpack": "^3.6.0",//打包工具 "webpack-bundle-analyzer": "^2.9.0",//可視化webpack輸出文件的大小 "webpack-dev-server": "^2.9.1",//提供一個提供實時重載的開發服務器 "webpack-merge": "^4.1.0"//它將數組和合并對象創建一個新對象。如果遇到函數,它將執行它們,通過算法運行結果,然后再次將返回的值封裝在函數中 }, //engines是引擎,指定node和npm版本 "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, //限制了瀏覽器或者客戶端需要什么版本才可運行 "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }
注釋:
①、webpack運行時的配置文檔
②、devDependencies和dependencies的區別: devDependencies里面的插件只用于開發環境,不用于生產環境,即輔助作用,打包的時候需要,打包完成就不需要了。而dependencies是需要發布到生產環境的,自始至終都在。比如wepack等只是在開發中使用的包就寫入到devDependencies,而像vue這種項目全程依賴的包要寫入到dependencies
點這里→更多安裝包文檔搜索頁傳送門
③、file-loader和url-loader的區別:以圖片為例,file-loader可對圖片進行壓縮,但是還是通過文件路徑進行引入,當http請求增多時會降低頁面性能,而url-loader通過設定limit參數,小于limit字節的圖片會被轉成base64的文件,大于limit字節的將進行圖片壓縮的操作。總而言之,url-loader是file-loader的上層封裝。
其他文件
①、.editorconfig:編輯器的配置文件
②、.gitignore:忽略git提交的一個文件,配置之后提交時將不會加載忽略的文件
③、index.html:頁面入口,經過編譯之后的代碼將插入到這來。
④、package.lock.json:鎖定安裝時的包的版本號,并且需要上傳到git,以保證其他人在npm install時大家的依賴能保證一致
⑤、README.md:可此填寫項目介紹
⑥、node_modules:根據package.json安裝時候生成的的依賴(安裝包)
感謝各位的閱讀,以上就是“vue-cli目錄結構詳細講解”的內容了,經過本文的學習后,相信大家對vue-cli目錄結構詳細講解這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。