解析 vue-cli 如何構建項目

vue-cli

用 vue-cli 直接生成一個 vue 項目很簡單方便,不過要想深入學習並掌控 vue 項目,瞭解項目是如何建構的是很必要,今天就來一邊學習一邊試着分析。

本文 vue-cli 版本 2.9.6

一、初始化目錄結構

vue 主要文件目錄:

  1. build (構建項目相關代碼)
  2. config (項目開發環境配置)
  3. src (代碼目錄)
  4. static (靜態資源)
  5. index.html (訪問的主頁面)
  6. package.json (項目基本信息、依賴信息)

通常 src 存放源代碼,static 存放靜態資源,package.json 存放項目信息以及依賴信息,config 存放配置文件,通過 build 的腳本文件,使用依賴 vue-loader 解析源代碼的 vue 文件轉化成 js 文件,壓縮代碼,合併 html 並引入相關 js 文件及資源文件,生成項目文件等操作。

這次主要講講 package.json、build 以及 config 文件

二、package.json 文件

{
  ......
  ......
  ......
  "scripts": {		//npm 命令
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "build": "node build/build.js"
  },
  "dependencies": {		//運行時依賴(生產環境)
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
  },
  "devDependencies": {		//開發時依賴(開發環境)
      ......
      ......
  },
  ......
  ......
}

scripts

scripts 定義的是用 node 執行的命令
如:npm run build,就是執行了 build/build.js 文件,
npm run dev,就是執行了 build/webpack.dev.conf.js 文件

dependencies vs devDependencies

dependencies 是運行時依賴(生產環境)       npm install --save  **(package name)
devDependencies 是開發時的依賴(開發環境)  npm install --save-dev  **(package name)

dependencies 存放的是本地運行所需的文件,像 babel(JavaScript 轉化) 和 vue-loader(vue 文件轉化)等依賴

dependencies 存放的是打包時需要運行的依賴

三、 config 文件(項目開發環境配置)

內部目錄:
(1) dev.env.js 設置開發環境變量
(2) index.js
(3) prod.env.js 設置生產環境變量

config 文件主要是一些配置環境,重點說說 index.js 文件,其他兩個都只有一句代碼,設置一個變量表示開發或者生產環境。

index.js

module.exports = {
  // 開發模式配置
  dev: {
    // 文件路徑
    assetsSubDirectory: 'static', 	// 資源引用路徑
    assetsPublicPath: '/',    		// 生成 index.html 路徑
    proxyTable: {     	// 代理
      'xxx': {        	// 代理名稱(請求路徑帶上這個名稱時自動轉換)
          target: 'xxx',   		 // 代理服務器地址
          changeOrigin: true,
          secure: false,
          pathRewrite: {  
                '^/xxx': '/xxx'   // 請求路徑重寫        
          }
      }
    },   

    // 服務器設置
    host: 'localhost',	// 測試頁面地址
    port: 8080, 		// 測試頁面端口號
    autoOpenBrowser: true, // 開啓服務器時是否自動打開瀏覽器

    // 映射
    devtool: 'cheap-module-eval-source-map',

    cssSourceMap: true  //是否開啓css映射
  },

  //生產環境配置
  build: {
    // 生成 index.html 模板位置
    index: path.resolve(__dirname, '../dist/index.html'),

    // 路徑
    assetsRoot: path.resolve(__dirname, '../dist'),   //生成項目位置
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',

    // 映射
    productionSourceMap: true,
    devtool: '#source-map',

    productionGzip: false,  	// 用於 gzip 壓縮判斷,看 webpack.prod.conf.js 文件講解
    productionGzipExtensions: ['js', 'css'],

    // npm run build --report 構建完成後查看bundle analyzer報告
    // process.env 是 node 的全局變量,這裏用來讀取 npm 命令後面的值 report 
    // 用於 webpack.prod.conf.js 文件做判斷值
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

四、build 文件(構建項目)

內部目錄:
(1) build.js 打包編譯入口
(2) check-version.js 檢查版本
(3) utils.js 工具代碼
(4) vue-loader.conf.js vue-loader 配置
(5) webpack.base.conf.js 基礎配置文件
(6) webpack.dev.conf.js 開發環境配置文件
(7) webpack.prod.conf.js 生產模式配置文件

check-version.js 用於檢查版本,被引入各個文件之中
utils.js 是工具代碼,會設置 css-loader、postcss-loader 等
vue-loader.conf.js 則是配置 vue-loader 解析 vue 文件

重點在其他幾個文件

webpack.base.conf.js 基礎配置文件

module.exports = {
  context: path.resolve(__dirname, '../'),  // 目錄 
  entry: {   		 // 入口文件
    app: './src/main.js'
  },
  output: {  		 // 輸出內容
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: ......
  },      
  resolve: {
    extensions: ['.js', '.vue', '.json'],   // 檢測文件後綴
    alias: {   	 // 指定路徑的別名,在引用文件路徑中,如果有別名的符號,會被替換成指定的路徑。
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [    // 解析規則配置
    	vue-loader		// vue-loader 解析 vue 文件輸出 js 模塊 
    	babel-loader	// babel-loader 轉換 ES6
    	url-loader		// url-loader 把一定大小內的資源變成base64格式
	]
  }
}

webpack.dev.conf.js 開發環境配置文件

const devWebpackConfig = merge(baseWebpackConfig, {	// 合併之前的基礎配置文件
  module: {		// 增加cssSourceMap的功能
    rules: utils.styleLoaders({ ...... })
  },
  devtool: config.dev.devtool,	// 定義開發模式,cheap-module-eval-source-map使得開發更快

  devServer: {	// 定義服務器的一些配置
  	......	
  	......
  },
  plugins: [	// 插件
    DefinePlugin				// 定義 process.env(開發環境)
   	HotModuleReplacementPlugin	// 模塊熱替換插件
	NamedModulesPlugin			// 顯示模塊加載相對路徑插件
    NoEmitOnErrorsPlugin		// 進程遇到錯誤代碼將不會退出,在控制檯輸出錯誤日誌
	HtmlWebpackPlugin			// 使用插件生成一個指定的模版
    CopyWebpackPlugin			// 自定義靜態資源目錄
  ]
})

webpack.prod.conf.js 生產模式配置文件

打包到生產環境,和 webpack.dev.conf.js 一樣也是先合併基礎配置文件,但是插件有些變化。

1.新增了 output 配置,將源碼打包成帶有 hash 尾綴的不同模塊的 js 文件,如 vendor.cd57a1ba620b10849fab.js 。
這裏使用 chunkhash 尾綴,根據文件映射,在修改時如果沒有修改到當前模塊或者當前引用的模塊, chunkhash 就不會改變,從而在部署的時候可以減少文件緩存帶來的部署問題,是一個優化方案。

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

2.插件

DefinePlugin				定義 process.env(生產環境)
UglifyJsPlugin				代碼壓縮
OptimizeCSSPlugin			壓縮css代碼
HtmlWebpackPlugin			生成主頁面模板
HashedModuleIdsPlugin		根據模塊的相對路徑生成一個 hash 作爲模塊 id
ModuleConcatenationPlugin	作用域提升,加快代碼執行速度
CommonsChunkPlugin			提取第三方庫和公共模塊

// 抽離css代碼(webpack打包 css會變成用 js的模塊方式引入,有延遲,所以要抽離css)
// 爲該文件增加 contenthash 尾綴(contenthash:當前模塊的內容變了,hash值才改變)
new ExtractTextPlugin({
  filename: utils.assetsPath('css/[name].[contenthash].css'),
  allChunks: true,
}),

額外要注意的插件:

// gzip 壓縮插件
if (config.build.productionGzip) {		// 判斷生產模式下的 productionGzip 值
  // 提供帶 Content-Encoding 編碼的壓縮版的資源
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(	// 把此插件插入 webpack 插件設置內
    new CompressionWebpackPlugin({ ......	})
  )
}

// 查看 bundle analyzer 報告插件
if (config.build.bundleAnalyzerReport) {	// 在config/index.js中已說明,npm 輸入的命令
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

順便小結一下文件尾綴:

尾綴 狀態變動 使用
hash 文件變動,立即改變 圖片等資源
chunkhash 修改到當前模塊或者當前引用的模塊才改變 常用於 js
contenthash 當前模塊的內容變了,值才改變 常用於 css

build.js

項目打包時執行的文件,npm run build

主要是先刪除(rimraf 插件)以前打包的 dist 文件,刪除後讀取 webpack.prod.conf.js 的設置然後開始 webpack 的構建

五、總結

最後總結一下整個 vue 項目構建流程(主體爲 webpack 的構建流程)

啓動構建,讀取與合併配置參數,加載 Plugin

使用 Loader 遞歸翻譯所有模塊。這裏是 vue-loader 解析 vue 文件,變成 js 文件 module.exports 大概三個語言模塊(html,script,style)。中間穿插 es6 轉換,css 轉換,資源文件引用增加 hash 尾綴以及 base64 格式轉化。

根據依賴關係,組裝成一個個包含多個模塊的 Chunk,再把每個 Chunk 轉換成一個單獨的文件加入到輸出列表。即打包壓縮、抽取插件和公共代碼,生成 app.[chunkhash].js 、按需加載.[chunkhash].js、vendor.[chunkhash].js 和 manifest.[chunkhash].js

文件 來源
app 源代碼
vendor 抽離 node_modules 依賴及公共模塊
manifest 映射各個模塊的數據集合,便於快速更替文件

最後生成主頁面模板引入相關靜態資源和 js 文件,把項目輸入到 dist 文件夾內。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章