vue-cli
用 vue-cli 直接生成一個 vue 項目很簡單方便,不過要想深入學習並掌控 vue 項目,瞭解項目是如何建構的是很必要,今天就來一邊學習一邊試着分析。
本文 vue-cli 版本 2.9.6
一、初始化目錄結構
vue 主要文件目錄:
- build (構建項目相關代碼)
- config (項目開發環境配置)
- src (代碼目錄)
- static (靜態資源)
- index.html (訪問的主頁面)
- 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 文件夾內。