日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

【vue系列之二】详解vue-cli 2.0配置文件

發布時間:2023/12/10 vue 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【vue系列之二】详解vue-cli 2.0配置文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上次給大家分享的是用vue-cli快速搭建vue項目,雖然很省時間和精力,但想要真正搞明白,我們還需要對其原理一探究竟。

大家拿到一個項目,要快速上手,正確的思路是這樣的:

首先,如果在項目有readme.md的情況下,大家要先讀readme,項目的一些基本介紹,包括項目信息、運行的腳本、采用何種框架,以及項目維護者等信息通常都會有。一般在git上維護的項目都會有readme.md,不熟悉markdown語法的同學可以先了解下markdown入門。

第二步,要看package.json。現代的前端項目中通常都會有package.json文件。在package.json里,會介紹項目名稱、版本、描述、作者、腳本、依賴包,對環境的要求,以及對瀏覽器要求。

1 { 2 "name": "uccn", 3 "version": "1.0.0", 4 "description": "uccn3.0", 5 "author": "v_yangtianjiao <v_yangtianjiao@baidu.com>", 6 "private": true,
   // 這里的腳本是分析項目的主要入口
7 "scripts": { 8 "dev": "node build/dev-server.js", 9 "start": "node build/dev-server.js", 10 "build": "node build/build.js", 11 "jsonp": "node build/jsonp-server.js" 12 },
   // 項目依賴
13 "dependencies": { 14 "fetch-jsonp": "^1.1.3", 15 "less": "^2.7.2", 16 "less-loader": "^4.0.4", 17 "stylus": "^0.54.5", 18 "stylus-loader": "^3.0.1", 19 "vue": "^2.4.2" 20 }, 21 "devDependencies": { 22 "autoprefixer": "^7.1.2", 23 "babel-core": "^6.22.1", 24 "babel-loader": "^7.1.1", 25 "babel-plugin-component": "^0.10.1", 26 "babel-plugin-transform-runtime": "^6.22.0", 27 "babel-preset-env": "^1.3.2", 28 "babel-preset-es2015": "^6.24.1", 29 "babel-preset-stage-2": "^6.22.0", 30 "babel-register": "^6.22.0", 31 "chalk": "^2.0.1", 32 "connect-history-api-fallback": "^1.3.0", 33 "copy-webpack-plugin": "^4.0.1", 34 "css-loader": "^0.28.0", 35 "cssnano": "^3.10.0", 36 "eventsource-polyfill": "^0.9.6", 37 "express": "^4.14.1", 38 "extract-text-webpack-plugin": "^2.0.0", 39 "file-loader": "^0.11.1", 40 "friendly-errors-webpack-plugin": "^1.1.3", 41 "html-webpack-plugin": "^2.28.0", 42 "http-proxy-middleware": "^0.17.3", 43 "opn": "^5.1.0", 44 "optimize-css-assets-webpack-plugin": "^2.0.0", 45 "ora": "^1.2.0", 46 "rimraf": "^2.6.0", 47 "semver": "^5.3.0", 48 "shelljs": "^0.7.6", 49 "url-loader": "^0.5.8", 50 "vue-loader": "^13.0.4", 51 "vue-style-loader": "^3.0.1", 52 "vue-template-compiler": "^2.4.2", 53 "webpack": "^2.6.1", 54 "webpack-bundle-analyzer": "^2.2.1", 55 "webpack-dev-middleware": "^1.10.0", 56 "webpack-hot-middleware": "^2.18.0", 57 "webpack-merge": "^4.1.0" 58 },
// 對node版本的以及npm版本的要求
59 "engines": { 60 "node": ">= 4.0.0", 61 "npm": ">= 3.0.0" 62 },
   // 瀏覽器要求,vue項目不支持ie8,因為ie8是es3,尚沒有Object.defineProperty屬性
63 "browserslist": [ 64 "> 1%", 65 "last 2 versions", 66 "not ie <= 8" 67 ] 68 }

上面的package.json是從實際vue項目中摘出來的,大家從package.json中就會對項目有一個大概的了解,最主要的是腳本部分。通過npm的自動化任務,可以很方便的執行配置文件中的腳本。通過配置? "jsonp": "node build/jsonp-server.js",可以方便的使用npm run jsonp命令,代替node build/jsonp-server.js或者更復雜的一系列命令。詳細的npm自動化命令可以移步npm 自動化。

?

?現在的項目目錄結構如上,我們從剛才的腳本入手。首先是啟服務的腳本npm run dev,實際上是執行node build/dev-server.js,我們在build文件夾中找到dev-server.js,一步步分析。

/* eslint-disable */

// 首先檢查node和npm的版本 require('./check-versions')()
// 獲取配置文件中默認的配置
var config = require('../config')
// 如果node無法判斷當前是開發環境還是生產環境,則使用config.dev.env.NODE_ENV作為當前的環境
if (!process.env.NODE_ENV) {process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) }var opn = require('opn')// 用來在起來服務之后,打開瀏覽器并跳轉指定URL var path = require('path')// node自帶文件路徑工具 var express = require('express')// node框架express(本地開發的核心,起服務) var webpack = require('webpack')// webpack,壓縮打包 var proxyMiddleware = require('http-proxy-middleware')// 中間件 var webpackConfig = require('./webpack.dev.conf')// 開發環境的webpack配置 var mockMiddleware = require('../config/dev.mock')// 開發環境本地mock數據中間件 var port = process.env.PORT || config.dev.port var autoOpenBrowser = !!config.dev.autoOpenBrowser var proxyTable = config.dev.proxyTablevar app = express()// 起服務 var compiler = webpack(webpackConfig)// webpack進行編譯
// webpack-dev-middleware將編譯的文件放在內存中,后續注入
var devMiddleware = require('webpack-dev-middleware')(compiler, {publicPath: webpackConfig.output.publicPath,quiet: true }) // 熱加載 var hotMiddleware = require('webpack-hot-middleware')(compiler, {log: false,heartbeat: 2000 }) compiler.plugin('compilation', function (compilation) {compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {hotMiddleware.publish({ action: 'reload' })cb()}) })// proxy api requests
// proxyTable中的配置掛載到express中
Object.keys(proxyTable).forEach(function (context) {var options = proxyTable[context]if (typeof options === 'string') {options = { target: options }}app.use(proxyMiddleware(options.filter || context, options)) })// 處理后退的時候匹配資源 app.use(require('connect-history-api-fallback')())// 暫存在內存的webpack編譯后的文件掛載到express上 app.use(devMiddleware)
// 將本地mock中間件掛載到express上 app.use(mockMiddleware);
// 熱加載掛載到express上 app.use(hotMiddleware)// 拼static靜態資源文件路徑 var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// express為靜態資源提供服務 app.use(staticPath, express.static(
'./static'))var uri = 'http://localhost:' + portvar _resolve var readyPromise = new Promise(resolve => {_resolve = resolve })console.log('> Starting dev server...') devMiddleware.waitUntilValid(() => {console.log('> Listening at ' + uri + '\n')if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {opn(uri)}_resolve() }) // 通過配置的端口,自動打開瀏覽器,并跳轉拼好的URL,至此,發開環境已經跑起來了 var server = app.listen(port)module.exports = {ready: readyPromise,close: () => {server.close()} }

在上面的dev-server中,有很多變量來自于./config/index.js和webpack.dev.conf.js,我們一個個看上述配置文件。

首先看./config/index.js,這里是整個項目主要的配置入口,我們在代碼中一步步分析:

// node自帶路徑工具. var path = require('path') // 分為兩種環境,dev和production module.exports = {build: {env: require('./prod.env'),// 使用config/prod.env.js中定義的編譯環境index: path.resolve(__dirname, '../dist/index.html'),// 編譯輸入的index.html文件。node.js中,在任何模塊文件內部,可以使用__filename變量獲取當前模塊文件的帶有完整絕對路徑的文件名,assetsRoot: path.resolve(__dirname, '../dist'),// 編譯輸出的靜態資源路徑assetsSubDirectory: 'static',// 編譯輸出的二級目錄assetsPublicPath: './', // 編譯發布的根目錄,可配置為資源服務器或者cdn域名productionSourceMap: false,//是否開啟cssSourceMapproductionGzip: false,// 是否開啟gzipproductionGzipExtensions: ['js', 'css'],// 需要用gzip壓縮的文件擴展名 bundleAnalyzerReport: process.env.npm_config_report},dev: {env: require('./dev.env'),port: 8989,// 起服務的端口autoOpenBrowser: true,assetsSubDirectory: 'static',assetsPublicPath: '/',proxyTable: {},// 需要代理的接口,可以跨域cssSourceMap: false} }

接著我們分析webpack.dev.conf.js:

var utils = require('./utils')// 工具類 var webpack = require('webpack') var config = require('../config') var merge = require('webpack-merge')// 使用webpack配置合并插件 var baseWebpackConfig = require('./webpack.base.conf') var HtmlWebpackPlugin = require('html-webpack-plugin')// 這個插件自動生成HTML,并注入到.html文件中 var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')// 將hot-reload相對路徑添加到webpack.base.conf的對應的entry前面 Object.keys(baseWebpackConfig.entry).forEach(function (name) {baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) })
// webpack.dev.conf.js與webpack.base.conf.js中的配置合并 module.exports
= merge(baseWebpackConfig, {module: {rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })},// webpack-devtool有7種模式,cheap-module-eval-source-map模式是比較快的開發模式
 
devtool: '#cheap-module-eval-source-map',plugins: [
  // 你可以理解為,通過配置了DefinePlugin,那么這里面的標識就相當于全局變量,你的業務代碼可以直接使用配置的標識。
new webpack.DefinePlugin({'process.env': config.dev.env}),// hotModule插件讓頁面變動時,只重繪對應的模塊,不會重繪整個HTML文件new webpack.HotModuleReplacementPlugin(),
  // 在編譯出現錯誤時,使用?NoEmitOnErrorsPlugin?來跳過輸出階段。這樣可以確保輸出資源不會包含錯誤
new webpack.NoEmitOnErrorsPlugin(),// 將生成的HTML代碼注入index.html文件new HtmlWebpackPlugin({filename: 'index.html',template: 'index.html',inject: true}),
  // friendly-errors-webpack-plugin用于更友好地輸出webpack的警告、錯誤等信息
new FriendlyErrorsPlugin()] })

?剛才的webpack.dev.conf.js中有引到webpack.base.conf.js,我們就把他們一網打盡,繼續看webpack.base.conf.js!

/* eslint-disable */ var path = require('path')// node自帶的文件路徑插件 var utils = require('./utils')// 工具類 var config = require('../config')// 上面說過的config/index var vueLoaderConfig = require('./vue-loader.conf')// vue-loader.conf配置文件是用來解決各種css文件的,定義了諸如css,less,sass之類的和樣式有關的loader // 此函數是用來返回當前目錄的平行目錄的路徑, function resolve (dir) {return path.join(__dirname, '..', dir) }module.exports = {entry: {uccn: './src/main.js'// 入口},output: {
  // 路徑是config目錄下的index.js中的build配置中的assetsRoot,也就是dist目錄path: config.build.assetsRoot,filename:
'[name].js',
  // 上線地址,也就是真正的文件引用路徑,如果是production生產環境,其實這里都是 '/'publicPath: process.env.NODE_ENV
=== 'production'? config.build.assetsPublicPath: config.dev.assetsPublicPath},
 // resolve是webpack的內置選項,顧名思義,決定要做的事情,也就是說當使用 import "jquery",該如何去執行這件事情,就是resolve配置項要做的,import jQuery from "./additional/dist/js/jquery" 這樣會很麻煩,可以起個別名簡化操作 resolve: {
  // 省略擴展名,比方說import index form '../js/index', 會默認去找index文件,然后找index.js,.vue,.josn.extensions: [
'.js', '.vue', '.json'],alias: {'vue$': 'vue/dist/vue.esm.js',
    // 使用上面的resolve函數,意思是用@代替src的絕對路徑
'@': resolve('src'),}},
 // 不同的模塊使用不同的loadermodule: {rules: [{
     // 對vue文件,使用vue-loader解析test:
/\.vue$/,loader: 'vue-loader',options: vueLoaderConfig},{
     // babel-loader把es6解析成es5test:
/\.js$/,loader: 'babel-loader',include: [resolve('src'), resolve('test')]},{
     // url-loader將文件大小低于下面option中limit的圖片,轉化為一個64位的DataURL,這樣會省去很多請求,大于limit的,按[name].[hash:7].[ext]的命名方式放到了static/img下面,方便做cachetest:
/\.(png|jpe?g|gif|svg)(\?.*)?$/,loader: 'url-loader',options: {limit: 20000,name: utils.assetsPath('img/[name].[hash:7].[ext]')}},{
     // 音頻和視頻文件處理,同上test:
/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('media/[name].[hash:7].[ext]')}},{
     // 字體處理,同上 test:
/\.(woff2?|eot|ttf|otf)(\?.*)?$/,loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('fonts/[name].[hash:7].[ext]')}}]} }

?至此,npm run dev起本地開發環境相關的配置文件基本說完了,接著說一下上面都用到的util工具類:

var path = require('path') var config = require('../config')
// extract-text-webpack-plugin該插件的主要是為了抽離css樣式,防止將樣式打包在js中引起頁面樣式加載錯亂的現象
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// 返回資源文件路徑,path.posix以posix兼容的方式交互,是跨平臺的,如果是path.win32的話,只能在win上 exports.assetsPath
= function (_path) {var assetsSubDirectory = process.env.NODE_ENV === 'production'? config.build.assetsSubDirectory: config.dev.assetsSubDirectoryreturn path.posix.join(assetsSubDirectory, _path) }
// 通過判斷是否是生產環境,配置不同的樣式語言的loader配置 exports.cssLoaders
= function (options) {options = options || {}var cssLoader = {loader: 'css-loader',options: {minimize: process.env.NODE_ENV === 'production',sourceMap: options.sourceMap}}// 生成各種loader配置,通過傳入不同的loader和option,將不同樣式文件語言的loader拼好,push到loader配置中。function generateLoaders (loader, loaderOptions) {var loaders = [cssLoader]if (loader) {loaders.push({loader: loader + '-loader',options: Object.assign({}, loaderOptions, {sourceMap: options.sourceMap})})}// extract-text-webpack-plugin有三個參數,use指需要用什么loader去編譯文件;fallback指編譯后用什么loader去提取文件;還有一個publicfile用來覆蓋項目路徑if (options.extract) {return ExtractTextPlugin.extract({use: loaders,fallback: 'vue-style-loader'})} else {return ['vue-style-loader'].concat(loaders)}}// 對不同的樣式語言,返回相應的loaderreturn {css: generateLoaders(),postcss: generateLoaders(),less: generateLoaders('less'),sass: generateLoaders('sass', { indentedSyntax: true }),scss: generateLoaders('sass'),stylus: generateLoaders('stylus'),styl: generateLoaders('stylus')} }// 生成處理不同的樣式文件處理規則 exports.styleLoaders = function (options) {var output = []var loaders = exports.cssLoaders(options)for (var extension in loaders) {var loader = loaders[extension]output.push({test: new RegExp('\\.' + extension + '$'),use: loader})}return output }

———————————————— 華麗的分隔符 —————————————————

下面我們繼續說npm run build,打包編譯的一系列操作~

從package.json 中可以看出,npm run build,其實是執行了 node build/build.js,我們在build文件夾中找到build.js,build主要的工作是:檢測node和npm版本,刪除dist包,webpack構建打包,在終端輸出構建信息并結束,如果報錯,則輸出報錯信息。

require('./check-versions')()process.env.NODE_ENV = 'production'
// 在終端顯示的旋轉器插件 var ora = require('ora')
// 用于刪除文件夾
var rm = require('rimraf') var path = require('path')
// 終端文字顏色插件
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()
// 刪除dist文件夾,之后webpack打包 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err
=> {if (err) throw errwebpack(webpackConfig, function (err, stats) {spinner.stop()if (err) throw errprocess.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'))}) })

build.js用到了webpack.prod.conf.js,他與webpack.base.conf.js merge之后,作為webpack配置文件,我們再看看webpack.prod.conf.js,主要做的工作是:
1.提取webpack生成的bundle中的文本,到特定的文件,使得css,js文件與webpack輸出的bundle分離。

2.合并基本的webpack配置

3.配置webpack的輸出,包括輸出路徑,文件名格式。

4.配置webpack插件,包括丑化代碼。

5.gzip下引入compression插件進行壓縮。

/* eslint-disable */ 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') var CopyWebpackPlugin = require('copy-webpack-plugin') var HtmlWebpackPlugin = require('html-webpack-plugin')
// 用于從webpack生成的bundle中提取文本到特定文件中的插件
// 可以抽取出css,js文件將其與webpack輸出的bundle分離
var ExtractTextPlugin = require('extract-text-webpack-plugin') var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')var env = config.build.env // 合并基礎的webpack配置 var webpackConfig = merge(baseWebpackConfig, {module: {rules: utils.styleLoaders({sourceMap: config.build.productionSourceMap,extract: true})},
 // 7中sourceMap上面有講過devtool: config.build.productionSourceMap
? '#source-map' : false,
 // 配置webpack輸出的目錄,及文件命名規則output: {path: config.build.assetsRoot,filename: utils.assetsPath(
'js/[name].min.js'),chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')},
 // webpack插件配置plugins: [
// 同webpack.dev.conf.jsnew webpack.DefinePlugin({'process.env': env}),
  // 丑化代碼
new webpack.optimize.UglifyJsPlugin({compress: {warnings: false},sourceMap: true}),// 抽離css文件到單獨的文件new ExtractTextPlugin({filename: utils.assetsPath('css/[name].min.css')}),new OptimizeCSSPlugin({cssProcessorOptions: {safe: true}}),// 生成并注入index.htmlnew HtmlWebpackPlugin({filename: config.build.index,template: 'index.html',inject: true,minify: {removeComments: true,collapseWhitespace: false,removeAttributeQuotes: true },chunksSortMode: 'dependency'}),// keep module.id stable when vender modules does not changenew webpack.HashedModuleIdsPlugin(),split vendor js into its own filenew webpack.optimize.CommonsChunkPlugin({name: 'vendor',minChunks: function (module, count) {// any required modules inside node_modules are extracted to vendorreturn (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 toprevent vendor hash from being updated whenever app bundle is updatednew webpack.optimize.CommonsChunkPlugin({name: 'manifest',chunks: ['vendor']}),copy custom static assetsnew CopyWebpackPlugin([{from: path.resolve(__dirname, '../static'),to: config.build.assetsSubDirectory,ignore: ['.*']}])] }) // gzip模式下需要引入compression插件進行壓縮 if (config.build.productionGzip) {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})) }if (config.build.bundleAnalyzerReport) {var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPluginwebpackConfig.plugins.push(new BundleAnalyzerPlugin()) }module.exports = webpackConfig

到此為止,vue官方腳手架工具vue-cli 2.0的所有配置文件都已介紹完畢,從頭到尾再梳理一遍:

執行npm run dev或者npm run start,實際是在node環境執行build/dev-server.js, dev-server.js會去拿到config中的端口等配置,通過express起一個服務,通過插件自動打開瀏覽器,加載webpack編譯后放在內存的bundle。

執行npm run build,實際上執行了build/build.js,通過webpack的一系列配置及插件,將文件打包合并丑化,并創建dist目錄,放置編譯打包后的文件,這將是未來用在生產環境的包。

?

寫這篇文章我自身的收獲也挺多,第一是對vue-cli整體的認知更加清晰條理,第二是對webpack的一些插件有了新的認識。以前對一些插件模棱兩可,直接越過,這是不對的,要一步一個腳印兒,遇坑填坑,這樣才會有收獲。雖然過程可能是艱辛的,但收獲將會是巨大的~

文章中不足之處希望大家多多指正!

參考文獻:

extract-text-webpack-plugin 的使用及安裝

vue-cli的webpack模板項目配置文件分析

webpack——devtool里的7種SourceMap模式

vue-cli#2.0 webpack 配置分析

__dirname與__filename

?

轉載于:https://www.cnblogs.com/tjyoung/p/7652930.html

總結

以上是生活随笔為你收集整理的【vue系列之二】详解vue-cli 2.0配置文件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。