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
輸入命令後會詢問我們幾個簡單的選項,大家根據具體需要建立
- Project name :專案名稱 ,如果不需要更改直接回車就可以了。注意:這裡不能使用大寫,所以我把名稱改成了vueclitest
- Project description:專案描述,預設為A Vue.js project,直接回車,不用編寫。
- Author:作者,如果你有配置git的作者,他會讀取。
- Install vue-router? 是否安裝vue的路由外掛,我們這裡需要安裝,所以選擇Y
- Use ESLint to lint your code?
是否用ESLint來限制你的程式碼錯誤和風格。我們選擇yes。 - setup unit tests with Karma + Mocha?
是否需要安裝單元測試工具Karma+Mocha,我們這裡不需要,所以輸入n。 - Setup e2e tests with Nightwatch?是否安裝e2e來進行使用者行為模擬測試,我們這裡不需要,所以輸入n。
- 問你是否直接 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包含了三(四)個工具函式:
- 生成靜態資源的路徑(根據開發環境還是正式環境配置不同的路徑)
- css-loader配置,生成 ExtractTextPlugin物件(生成獨立的css檔案)或loader字串
- 生成 style-loader的配置
- 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’ 這個值,來配置的路徑