1. 程式人生 > >vue-cli詳解

vue-cli詳解

1.何為vue-cli

簡單來說就是Vue搭建的架子

2.安裝

全域性安裝vue-cli

npm isntall -g vue-cli

3.初始化建立專案

vue init <template-name> <project-name>
  • template-name為模板的名稱:

    官方模板:webpack ,webpack-simple, browserify,browserify-simple,pwa,simple
    淡然也可以安裝自己的模板:
    vue init username/repo my-project
    Where username/repo is the GitHub repo shorthand for your fork.

  • project-name 為自己專案的名字

注意:node版本要在4以上

我們使用的是webpack建立

npm install webpack vue-demo

輸入命令後會詢問我們幾個簡單的選項,大家根據具體需要建立
這裡寫圖片描述

  1. Project name :專案名稱 ,如果不需要更改直接回車就可以了。注意:這裡不能使用大寫,所以我把名稱改成了vueclitest
  2. Project description:專案描述,預設為A Vue.js project,直接回車,不用編寫。
  3. Author:作者,如果你有配置git的作者,他會讀取。
  4. Install vue-router? 是否安裝vue的路由外掛,我們這裡需要安裝,所以選擇Y
  5. Use ESLint to lint your code?
    是否用ESLint來限制你的程式碼錯誤和風格。我們選擇yes。
  6. setup unit tests with Karma + Mocha?
    是否需要安裝單元測試工具Karma+Mocha,我們這裡不需要,所以輸入n。
  7. Setup e2e tests with Nightwatch?是否安裝e2e來進行使用者行為模擬測試,我們這裡不需要,所以輸入n。
  8. 問你是否直接 npm install 安裝外掛(以前版本的是沒有這一項的,需要自己手動install)

完成後進入專案目錄

cd vue-demo

給我們自動構建了開發用的伺服器環境和在瀏覽器中開啟,並實時監視我們的程式碼更改,即時呈現給我們。

npm run dev

3.專案結構的講解

3.1整體結構

|-- build                            // 專案構建(webpack)相關程式碼,表示打包的配置檔案的資料夾
|   |-- build.js                     // 生產環境構建程式碼
|   |-- check-version.js             // 檢查node、npm等版本(因為對此有要求)
|   |-- dev-client.js                // 熱過載相關 (新版的已經沒有該檔案)
|   |-- dev-server.js                // 構建本地伺服器 (新版的已經沒有該檔案)
|   |-- utils.js                     // 構建工具相關
|   |-- vue-loader.conf.js           // vue-loader配置相關
|   |-- webpack.base.conf.js         // webpack基礎配置
|   |-- webpack.dev.conf.js          // webpack開發環境配置
|   |-- webpack.prod.conf.js         // webpack生產環境配置
|-- config                           // webpack的相關配置
|   |-- dev.env.js                   // 開發環境變數
|   |-- index.js                     // 專案一些配置變數
|   |-- prod.env.js                  // 生產環境變數
|   |-- test.env.js                  // 測試環境變數(新版沒有)
|-- src                              // 原始碼目錄
|   |-- components                   // vue公共元件
|   |-- store                        // vuex的狀態管理
|   |-- router                       //路由配置
|   |-- App.vue                      // 頁面入口檔案
|   |-- main.js                      // 程式入口檔案,載入各種公共元件
|-- static                           // 靜態檔案,比如一些圖片,json資料等
|-- .babelrc                         // ES6語法編譯配置
|-- .editorconfig                    // 定義程式碼格式
|-- .gitignore                       // git上傳需要忽略的檔案格式
|-- README.md                        // 專案說明
|-- favicon.ico 
|-- index.html                       // 入口頁面
|-- package.json                     // 專案基本資訊
|--.eslintignore                     //eslint的程式碼檢查的忽略檔案
|--.eslintrc.js                      //eslint的配置檔案

3.2 webpack重要檔案的講解

package.json

{
    .....
    //定義了你可以用npm run [name]執行的命令
     "scripts": {
        "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
        "start": "npm run dev",
        "lint": "eslint --ext .js,.vue src",
        "build": "node build/build.js"
      },
      //專案執行時所依賴的模組
      "dependencies":{
          ...
      }
      //專案開發時所依賴的模組
      "devDependencies": {
         ...
      }
      // 宣告專案需要的node或npm版本範圍
      "engines": {
        "node": ">= 6.0.0",
        "npm": ">= 3.0.0"
      },
      //對瀏覽器的要求
      "browserslist": [
        "> 1%",
        "last 2 versions",
        "not ie <= 8"
      ]
 }

vue-cli中webpack的相關配置

其實重要的是 build資料夾和 config資料夾,config資料夾中的內容更像是將一些變數單獨列出來的資料夾,特別是他下面的index.js,本來config資料夾下的檔案可以和webpack.base.config.js放在一起的,但是為了更加的清晰,所以就分開了。。

build / build.js

構建生產版本,或者說是打生產的包,我們可以看根目錄的package.json 中npm run build 執行的就是

node build/build.js

執行的就是build.js

'use strict'
//呼叫檢測版本的檔案,因為使用node和npm版本需要求的,因為check-versions.js是exports出一個函式,所以可以直接()呼叫
require('./check-versions')()

//全域性環境變數的設定  因為bundle.js是打的生成包,所以引數是production
process.env.NODE_ENV = 'production'
// loading 外掛,可以在npm run build時看到loading
const ora = require('ora')
//刪除命令,每次打包前會將上次打包的檔案刪除
const rm = require('rimraf')
//node.js中自帶的檔案路徑工具
const path = require('path')
//在命令列中輸出帶顏色的文字
const chalk = require('chalk')

const webpack = require('webpack')
//引入../config/index.js,也就是專案中的一些配置變數,只引入資料夾,是因為會自動去該資料夾下找index.js
const config = require('../config')
//引入生產包的配置
const webpackConfig = require('./webpack.prod.conf')

//日誌輸出外掛,會在命令列中顯示loading效果,並輸出提示
const spinner = ora('building for production...')
spinner.start()

// 刪除上次編譯生成過的檔案(遞迴刪除)
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
  if (err) throw err
  //在刪除完成的回撥函式中開始編譯    因為基本的webpack是有‘webpack’這個命令的,會自動去找根目錄下的webpck.config.js,而我們不是用的webpck.config.js,使用的是webpack的回撥函式打包
  webpack(webpackConfig, (err, stats) => {
     // 在編譯完成的回撥函式中,在終端輸出編譯的檔案
    process.stdout.write(stats.toString({
        ...
    })
    ...
  })
})

build / utils.js

utils.js包含了三(四)個工具函式:

  1. 生成靜態資源的路徑(根據開發環境還是正式環境配置不同的路徑)
  2. css-loader配置,生成 ExtractTextPlugin物件(生成獨立的css檔案)或loader字串
  3. 生成 style-loader的配置
  4. Node.js傳送跨平臺原生通知 (新版的有,老的沒有)
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')

exports.assetsPath = function (_path) {
}

exports.cssLoaders = function (options) {
}


exports.styleLoaders = function (options) {
}

exports.createNotifierCallback = () => {
}

build / webpack.base.conf.js

這個檔案是開發環境和生產環境,甚至測試環境,這些環境的公共webpack配置。可以說,這個檔案相當重要。

// node自帶的檔案路徑工具
var path = require('path')
// 工具函式集合
var utils = require('./utils')
  // 引用配置檔案,config資料夾下的index.js
var config = require('../config')
  // 工具函式集合
var vueLoaderConfig = require('./vue-loader.conf')

//這個函式是說目錄回退到該檔案絕對路徑的上一級,也就是根目錄下
function resolve(dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  entry: {
    app: './src/main.js'
  },
  output: {
    // 編譯輸出的靜態資源根路徑,可以在config資料夾下的index.js下build函式中看到,會生成dist資料夾
    path: config.build.assetsRoot,
    // 編譯輸出的檔名
    filename: '[name].js',
    // 正式釋出環境下編譯輸出的上線路徑的根路徑
    publicPath: process.env.NODE_ENV === 'production' ?
      config.build.assetsPublicPath : config.dev.assetsPublicPath
  },

  //關於我們在程式碼中require或者import檔案的相關配置
  resolve: {
    //可以省略字尾的檔案(可以自動補全字尾名)
    extensions: ['.js', '.vue', '.json'],
    //提供一些別名,例如在router.js中的引入
    alias: {
      // 例如 import Vue from 'vue',會自動到 'vue/dist/vue.common.js'中尋找
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [{
        // 審查 js 和 vue 檔案
        // https://github.com/MoOx/eslint-loader
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        // 表示預先處理
        enforce: "pre",
        include: [resolve('src'), resolve('test')],
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      },
      {
        // 處理 vue檔案
        // https://github.com/vuejs/vue-loader
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        // 編譯 js
        // https://github.com/babel/babel-loader
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test')]
      },
      {
        // 處理圖片檔案
        // https://github.com/webpack-contrib/url-loader
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        query: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        // 處理字型檔案
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        query: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  }
}

build / webpack.dev.conf.js

該檔案是開發環境中webpack的配置入口。

'use strict'
//工具方法
const utils = require('./utils')
const webpack = require('webpack')
//引入../config/index.js
const config = require('../config')
//合併配置檔案,用來和webpack.base.config.js合併
const merge = require('webpack-merge')
const path = require('path')

const baseWebpackConfig = require('./webpack.base.conf')
//複製Webpack外掛,將單個檔案或整個目錄複製到構建目錄
const CopyWebpackPlugin = require('copy-webpack-plugin')
  // 自動生成 html 並且注入到 .html 檔案中的外掛
const HtmlWebpackPlugin = require('html-webpack-plugin')
 // webpack錯誤資訊提示外掛
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
// 一個簡單的工具,查詢當前機器上的開放埠
const portfinder = require('portfinder')

//設定開發環境的的ip地址和埠
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

//dev的設定,將webpack-base.config和下面的合併
const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
      // //對獨立的css或者less,scss檔案進行編譯
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },

  // dev環境使用cheap-module-eval-source-map程式碼除錯用的
  devtool: config.dev.devtool,

  // 使用webpack-dev-server    相關配置在 ../config/index.js
  devServer: {
  },

  plugins: [
    //config.dev.env展示的是"development",我們可以根據這個欄位做一些操作,例如dev環境資源的配置  
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),

    //使用熱載入外掛
    new webpack.HotModuleReplacementPlugin(),

    //當開啟 HMR 的時候使用該外掛會顯示模組的相對路徑,建議用於開發環境
    new webpack.NamedModulesPlugin(), 

    //則啟用此外掛後,編譯時發生錯誤,webpack程序將不會退出並顯示錯誤程式碼
    new webpack.NoEmitOnErrorsPlugin(),

    //html外掛
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),

    // 將單個檔案或整個目錄複製到構建目錄
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

//將dev環境的config輸出
module.exports = new Promise((resolve, reject) => {
})

build / webpack.prod.conf.js

const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')

//引入../config/index.js
const config = require('../config')

//檔案的合併,可以繼承webpack.base.config.js
const merge = require('webpack-merge')

//引入webpack.base.conf.js
const baseWebpackConfig = require('./webpack.base.conf')

//複製Webpack外掛,將單個檔案或整個目錄複製到構建目錄
const CopyWebpackPlugin = require('copy-webpack-plugin')

//html外掛
const HtmlWebpackPlugin = require('html-webpack-plugin')

// webpack提供的外掛,將css提取出來生成單獨檔案
const ExtractTextPlugin = require('extract-text-webpack-plugin')

//壓縮css
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

//壓縮js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

//將env 設定為production
const env = require('../config/prod.env')

const webpackConfig = merge(baseWebpackConfig, {
  module: {
    //使用styleLoader
    rules: utils.styleLoaders({
      //使用開發工具sourceMap,因為引入../config/index.js,該檔案中 build下的productionSourceMap: true,
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  // 生產環境中的#sourceMap開啟
  devtool: config.build.productionSourceMap ? config.build.devtool : false,

  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },

  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    //定義環境變數   這裡是生產的環境變數,所以生產的檔案都會以生產的路徑為字首
    new webpack.DefinePlugin({
      'process.env': env
    }),

    //壓縮js
    new UglifyJsPlugin({
      ...
    }),

    //分離css到單獨的檔案
    new ExtractTextPlugin({
     ...
    }),

    //壓縮提取出的css,並解決ExtractTextPlugin分離出的js重複問題(多個檔案引入同一css檔案)
    new OptimizeCSSPlugin({
      ...
    }),

    // html外掛
    new HtmlWebpackPlugin({
     ...
    }),

    //這個外掛將使得雜湊基於模組的相對路徑,生成一個四個字元的字串作為模組ID,這裡使用是為了當供應商模組不變時ID不變
    new webpack.HashedModuleIdsPlugin(),

    //此外掛僅適用於由webpack直接處理的ES6模組。使得各個模組起到串聯的作用,瀏覽器可以更快的解析
    new webpack.optimize.ModuleConcatenationPlugin(),

    // 將通用模組與捆綁分離,可以將最終的分塊檔案初始化一次,然後將其儲存在快取中供以後使用。
    //這會導致頁速率優化,因為瀏覽器可以快速提供快取中的共享程式碼,而不必在訪問新頁面時強制載入更大的包。
    new webpack.optimize.CommonsChunkPlugin({
     ...
    }),


   //複製Webpack外掛,將單個檔案或整個目錄複製到構建目錄
    new CopyWebpackPlugin([
      ...
    ])
  ]
})

//開啟 gzip 的情況時,給 webpack plugins新增 compression-webpack-plugin 外掛
if (config.build.productionGzip) {
 ...
}

//開啟包分析的情況時, 給 webpack plugins新增 webpack-bundle-analyzer 外掛
if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

config / dev.env.js

其實就是輸出開發環境變數

    module.exports = merge(prodEnv, {
      NODE_ENV: '"development"'
    })

config / pro.env.js

輸出正式環境變數

    module.exports = {
      NODE_ENV: '"production"'
    }

config / index.js

就是一些開發或者正式環境的配置

var path = require('path')

module.exports = {

  // production 生產環境
  build: {
    // 構建環境
    env: require('./prod.env'),
    // 構建輸出的index.html檔案
    index: path.resolve(__dirname, '../dist/index.html'),
    // 構建輸出的靜態資源路徑
    assetsRoot: path.resolve(__dirname, '../dist'),
    // 構建輸出的二級目錄
    assetsSubDirectory: 'static',
    // 構建釋出的根目錄,可配置為資源伺服器域名或 CDN 域名
    assetsPublicPath: '/',
    // 是否開啟 cssSourceMap
    productionSourceMap: true,
    // 預設關閉 gzip,因為很多流行的靜態資源主機,例如 Surge、Netlify,已經為所有靜態資源開啟gzip
    productionGzip: false,
    // 需要使用 gzip 壓縮的副檔名
    productionGzipExtensions: ['js', 'css'],   
    // 執行“build”命令列時,加上一個引數,可以在構建完成後參看包分析報告
    // true為開啟,false為關閉
    bundleAnalyzerReport: process.env.npm_config_report
  },

  // dev 開發環境
  dev: {
    // 構建環境
    env: require('./dev.env'),
    // 埠號
    port: 3333,
    // 是否自動開啟瀏覽器
    autoOpenBrowser: true,
    assetsSubDirectory: 'static',
    // 編譯釋出的根目錄,可配置為資源伺服器域名或 CDN 域名
    assetsPublicPath: '/',
    // proxyTable 代理的介面(可跨域)
    // 使用方法:https://vuejs-templates.github.io/webpack/proxy.html
    proxyTable: {},
    // 預設情況下,關閉 CSS Sourcemaps,因為使用相對路徑會報錯。
    // CSS-Loader README:https://github.com/webpack/css-loader#sourcemaps
    cssSourceMap: false
  }
}

3.3執行流程

3.3.1開發環境

這裡寫圖片描述

首先npm run dev
這是因為package.json 中的設定 “dev”: “webpack-dev-server –inline –progress –config build/webpack.dev.conf.js”,

  • webpack-dev-server :

  • –inline

  • –progress
  • –config build/webpack.dev.conf.js :執行build/webpack.dev.conf.js

接著執行build/webpack.dev.conf.js
build/webpack.dev.conf.js主要是開發環境中 webpack的一些基本配置,

  • 引入了build / webpack.base.config.js 開發環境和正式環境都需要的webpack的配置,
  • 引入config/index.js 儲存開發環境和正式環境中配置webpake所需要的一些變數的值
  • 引入config/dev.env.js 主要獲取 ‘development’ 這個值,來配置的路徑

執行build / webpack.base.config.js
開發環境和正式環境都需要的webpack的配置

  • 引入config/index.js 儲存開發環境和正式環境中配置webpake所需要的一些變數的值

3.3.2正式環境

這裡寫圖片描述

首先npm run build
同樣是因為pakeage.json中 “build”: “node build/build.js”
在你的專案根目錄生成了dist資料夾,這個資料夾裡邊就是我們要傳到伺服器上的檔案。
執行 build/build.js
打包編譯時候的一些配置

  • 引入./webpack.prod.config.js 正式環境需要的webpack的配置

  • 引入config/index.js 儲存開發環境和正式環境中配置webpake所需要的一些變數的值

執行webpack.prod.config.js
正式環境需要的webpack的配置

  • 引入了build / webpack.base.config.js 開發環境和正式環境都需要的webpack的配置,
  • 引入config/index.js 儲存開發環境和正式環境中配置webpake所需要的一些變數的值
  • 引入config/pro.env.js 主要獲取 ‘production’ 這個值,來配置的路徑