Vuejs技術棧從CLI到打包上線實戰全解析
前言
本文是自己vue專案實踐中的一些總結,針對Vue2及相關技術棧,實踐中版本為2.3.3。
開發前須知
vue-cli
在開發前,我們要至少通讀一遍vue官方文件和API(看官方文件是最重要的,勝過看五十、一百篇部落格),英文閱讀能力還行的建議閱讀英文文件,中文文件內容會稍落後,還要通讀相關的vue-router、axios、vuex等。
一般來說我們都是先利用vue-cli來搭建專案基本架構。
vue-cli官方temaplte地址,我們選擇webpack版本,建議看看其文件vue-webpack-boilerplate瞭解基本用法和專案配置等。
深入地瞭解vue-cli的webpack配置請檢視vue-cli#2.0 webpack 配置分析
打造團隊的腳手架
vue-cli雖然強大,但是它有很多個步驟要我們去選擇配置,而實際上公司業務很多配置是固定的,比如我們公司規定了要安裝vue-router、要使用Standard風格Eslint等,還規定了必須使用sass,這樣在vue-cli配置完成後還必須要npm install node-sass和sass-loader,還有axios等也是一定要安裝的。所以不應該每次新建一個專案都去一步步選擇vue-cli的那些配置然後還要去安裝sass等,應該在vue-cli基礎上根據公司自身的情況打造團隊的腳手架,只需執行腳手架,就可以初始化整個專案。
目錄結構
建議在src/目錄增加views或pages目錄來存放對應路由的元件,新增api目錄,根據專案情況增加filters、vuex等目錄。components目錄存放公共元件或者全域性元件。每個元件目錄可以將圖片等資源放在一起。元件的子元件目錄建議命名為children放在父元件目錄下。如home元件目錄為home/home.vue,子元件banner路徑為home/chldren/banner/banner.vue。
靜態資源處理
vue-webpack-boilerplate文件中有靜態資源處理的詳細說明,但發現還有很多人都不知道,因此在這裡稍微提一下。
vue-webpack-boilerplate的專案結構中,我們有靜態資源兩個目錄:src/assets和static/
assets目錄中的檔案會被webpack處理,只支援相對路徑形式,assets/logo.png會被編譯為./assets/logo.png,不支援/assets/logo.png
在js中,我們可以這樣獲取檔案資源路徑
require('./assets/logo.png')
以下帶~字首類似require效果
<img src="~assets/logo.png">
static目錄中的靜態資源不會被webpack處理,這裡適合放一些外部不需要webpack處理的資源,build後的靜態資源都會被放進這個目錄。
vue元件化
關於vue元件化,360奇舞團前端工程師鍾恆的pptVue.js實踐 如何使用Vue2.0開發富互動式WEB應用寫得非常好,本節內容也是出自其中。ppt中提到元件化帶來的新問題:通訊、複用、耦合,以及如何解決。
通訊
1)props和events:props down,events up
2)函式呼叫:this.refs
3)元件樹: $parent.$parent
4)共享state
5)eventbus
6)vue技術棧之外的如localstorage等
複用
1)冗餘:if、else if、else判斷執行不同的程式碼
if(this.type === 'editing') { // some editing code } else if(this.type === 'preview') { // some preview code } else if(this.type === 'present') { // some present code } else { // some base code }
2)包裝:slots
// plugin-page.vue <div> <slot name="page"> i am a page </slot> </div> // present-plugin-page.vue <div class="PresetPluginPage"> <plugin-page ref="page"> <h1 slot="page"> i am a present page </h1> </plugin-page> </div> //output <div class="PresetPluginPage"> <div> <h1> i am a present page </h1> </div> </div>
3)繼承:mixins
// define a mixin object var myMixin = { created: function () { this.hello() }, methods: { hello: function () { console.log('hello from mixin!') } } } // define a component that uses this mixin var Component = Vue.extend({ mixins: [myMixin] }) var component = new Component() // -> "hello from mixin!"
元件耦合
1)元件耦合帶來的問題:
- 單元件修改困難
- 組合新元件困難
- 元件debug困難
2)解耦
解耦的本質就是將變化分離
一、元件功能單一
// wrong <control-input type="number"></control-input> // right <control-number></control-number>
二、採用穩定的介面
// wrong this.$parent.$parent.$refs['resource-image'].open() // right bus.$emit('open-resource-image')
三、處理好共享的部分
bindEvents (remove) { let method = remove ? 'removeEventListener' : 'addEventListener' window[method]('resize', this.handleResize) }
3)與服務端解耦
this.$http.get('/user/detail') .then(({body}) => { this.user = JSON.parse(body).data }, err => { console.error(err) }) user.detail().then(detail => this.detail = detail)
-
服務端與前端體系不一
-
同步非同步轉換
-
多服務端/跨域的程式碼
-
統一的錯誤處理程式碼
vuex使用中的一些注意事項
1)不要濫用vuex
使用Vuex並不意味著你需要將所有的狀態放入Vuex。雖然將所有的狀態放到Vuex會使狀態變化更顯式和易除錯,但也會使程式碼變得冗長和不直觀。如果有些狀態嚴格屬於單個元件,最好還是作為元件的區域性狀態。你應該根據你的應用開發需要進行權衡和確定。
2)最好在根例項中註冊store選項,該store例項會注入到根元件下的所有子元件中,子元件可以通過this.$store訪問,當狀態較多時使用建議mapState輔助函式。
3)polyfill
本次專案中使用了vuex,因此為相容IE9等低版本,須引入promise的polyfill--es6-promise。npm install後在main.js:
import 'es6-promise/auto'
開發中的常見問題
引入axios
為了和後端進行資料互動,我們一般引入axios庫。在main.js中如下將其加入vue的原型中,這樣可以在元件中通過this.$http來獲取axios:
Object.defineProperty(Vue.prototype, '$http', { value: axios }) // 或者 Object.defineProperty(Vue.prototype, '$axios', { value: axios })
這次實踐中未採用這種做法,而是建立了一個getData.js進行了統一管理:
import axios from 'axios' const getSomething = (param1,param2) => axios.get(url,{ params: { param1: param1, param2: param2 } }) export { getSomething }
在單檔案元件中import getSomething方法再進行呼叫即可。
引入iconfont
直接在main.js中import你下載的iconfont.css即可
js中判斷環境
常見的需求是開發環境須console,而線上環境不可以console。預設環境有'development'、'production'、'testing'三種。
if (process.env.NODE_ENV !== 'production') { console.log(data) }
設定資料模擬請求Mock
資料模擬請求利用了mock.js,配置文件,不過這個只是簡單的資料模擬,沒有生成文件的功,更全面的文件、Mock.js、視覺化、Rest、介面過渡、文件修改提醒、支援本地部署等功能可以使用阿里RAP。
npm install mockjs安裝後,可在/src/api目錄下新建data.js,引入mockjs,後可在程式入口或api入口根據開發環境來引入data.js,下面是幾個示例:
import Mock from 'mockjs' let data = Mock.mock({ 'list|1-10': [{ 'id|+1': 1 }] }) // mock一個資料 console.log(JSON.stringify(data, null, 4)) import Mock from 'mockjs' Mock.setup({ timeout: '300‐500' }) Mock.mock(/\/login/, { code: 0 }) // 攔截login請求,返回物件{ code: 0 } import Mock from 'mockjs' Mock.setup({ timeout: '300‐500' }) Mock.mock(sitemap.cms.banners, { results: [] }) // 攔截sitemap中cms.banners請求,返回物件{ results: [] }
seo
可以使用服務端渲染或者預渲染,預渲染webpack外掛github地址。
Webpack
實際專案中還是不可避免地要修改webpack配置,如果不知道怎麼改的話就去檢視webpack的配置分析去進行修改。
配置全域性變數
要設定全域性變數可以在build中的webpack.base.conf.js中配置externals,與module同級:
externals: { sitemap: 'sitemap' }
然後在eslinttrc.js的module.exports新增這樣一個配置:
globals: { 'sitemap': false }
根據環境的不同載入不同的js
在這個專案中要根據環境(開發環境、測試環境、生產環境)的不同載入不同的sitemap.js,這個sitemap.js會暴露出一個全域性的sitemap變數,sitemap變數是個由api地址構成的json物件。利用HtmlWebpackPlugin外掛的option選項來實現。
在index.html中這樣寫:
<script src="<%= htmlWebpackPlugin.options.src %>"></script>
然後在build中的各自conf.js的HtmlWebpackPlugin設定不同的src,如在開發環境中新增src那一行:
new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', src: '//dev.example.com/api/sitemap.js', inject: true })
配置alias(別名)
在webpack.base.conf.js,vue-cli已經預設配置好了src目錄的別名為@,建議配置src下一級目錄的別名,這樣能減少重複書寫也更美觀,如下新增src、pages、components別名:
resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), 'src': resolve('src'), 'pages': path.resolve(__dirname, '../src/pages'), 'components': path.resolve(__dirname, '../src/components') } }
圖片壓縮
可以使用webpack外掛image-webpack-loader來壓縮處理圖片。
多頁面
實際就是新增多個入口js然後再修改相應配置,網上資料很多,一搜就知道了。
eslint
我們有時候需要關閉某些程式碼檢查,具體配置參見Configuring ESLint - ESLint中文,下面是常見的兩個:
1)關閉eslint
/* eslint-disable */ alert('foo') /* eslint-enable */
2)關閉禁止new
/* eslint-disable no-new */
優化和其他
優化
1)由於vue的追蹤物件變化原理基於使用Object.defineProperty,在處理大量資料並且不需要追蹤物件變化時,可通過Object.freeze(data)凍結物件達到優化資料渲染處理
2)vue-router路由懶載入。當打包構建應用時,javascript包會變得非常大,影響頁面載入。如果我們能把不同路由對應的元件分割成不同的程式碼塊,然後當路由被訪問的時候才載入對應元件,這樣就更加高效了。
其他
1)使用表驅動法來註冊全域性filter、指令等,如在src下新建filters目錄,index.js中import所有全域性過濾器:
import milliFormat from './milliFormat' import reverse from './reverse' export default { milliFormat, reverse }
然後在main.js中註冊
import commonFiltes from './filters/index' Object.keys(commonFiltes).forEach(key => Vue.filter(key, commonFiltes[key]))
2)對於一些強耦合的元件如collapse和collapse-item,可以使用$parent和$children來進行通訊,沒必要像elementUI一樣自己實現元件的broadcast和dispatch,我還發現有UI庫竟然是使用bus來通訊的,這樣導致同一個頁面要是有兩個collapse,就會互相影響。
3)在根元件上註冊公共過濾器後,除了在“Mustache”語法中使用,還可在元件中通過this.$root.$options.filters.datetime(data)獲取datetime過濾器。
打包上線
優化分析
npm run build --report進行打包大小分析,視覺化地看到有什麼地方需要優化。
測試build後的檔案
build成功後有個tip提示你build後的檔案需要部署在http伺服器上,不能通過file協議開啟。
我們可以通過node-static來啟動服務。可以寫一個js配置檔案通過node來啟動,或者CLI中輸入static dist(先安裝node-static):
$ static dist serving "dist" at http://127.0.0.1:8080
更多如設定埠等請點選上面的連結檢視文件。
後語
本文最重要的是文章中給出的一些連結,尤其是開發前須知章節中的連結,最好點進去通讀一下。
相關文章
- 影片結構化技術棧全解析
- 從前端到全棧前端全棧
- 從技術到醫療,雲知聲全棧AI技術為智慧醫療加碼全棧AI
- Vue+Express全棧開發專案實戰技能:從0到1打造完整電商專案VueExpress全棧
- NLP機器翻譯全景:從基本原理到技術實戰全解析
- 解碼注意力Attention機制:從技術解析到PyTorch實戰PyTorch
- Spring Cloud微服務-全棧技術與案例解析SpringCloud微服務全棧
- 全棧技術導圖全棧
- 機器學習-ROC曲線:技術解析與實戰應用機器學習
- 快速創業之全棧技術棧創業全棧
- 全棧工程師技術學習路線圖全棧工程師
- 期望最大化(EM)演算法:從理論到實戰全解析演算法
- Python全棧工程師之從網頁搭建入門到Flask全棧專案實戰(6) - Flask表單的實現Python全棧工程師網頁Flask
- 機器學習-搜尋技術:從技術發展到應用實戰的全面指南機器學習
- 深度解讀DBSCAN聚類演算法:技術與實戰全解析聚類演算法
- BIRCH演算法全解析:從原理到實戰演算法
- Python全棧工程師之從網頁搭建入門到Flask全棧專案實戰(7) - 線上問答系統Python全棧工程師網頁Flask
- Python全棧工程師之從網頁搭建入門到Flask全棧專案實戰(5) - Flask中的ORM使用Python全棧工程師網頁FlaskORM
- RxJava 從入門到全解析RxJava
- 解鎖機器學習-梯度下降:從技術到實戰的全面指南機器學習梯度
- java全棧工程師:從java後端到全棧,高階電商全棧系統大課Java全棧工程師後端
- Hybrid App技術解析 — 實戰篇APP
- Hybrid App技術解析 -- 實戰篇APP
- 【從前端到全棧】- koa快速入門指南前端全棧
- 全棧式web開發技術-List全棧Web
- react技術棧實踐(從前到後擼一個電影蒐集應用)React
- 從容器化到資源池化,數棧雲原生技術實踐探索之路
- 從初創到頂級技術公司,都在用哪些資料科學技術棧?資料科學
- 深度解析BERT:從理論到Pytorch實戰PyTorch
- 從技術到管理
- 流星撞擊全棧之《Meteor實戰》全棧
- 全網最詳細最齊全的序列化技術及深度解析與應用實戰
- WEB實戰:使用MERN技術棧開發專案Web
- 全棧測試實戰:用Jest測試Vue+Koa全棧應用全棧Vue
- 13.5-全棧Java筆記:打飛機遊戲實戰專案|KeyEvent|Plane|live全棧Java筆記遊戲
- 從RabbitMQ平滑遷移到RocketMQ技術實戰MQ
- Elasticsearch技術解析與實戰(六)Elasticsearch併發Elasticsearch
- 機器學習 - 決策樹:技術全解與案例實戰機器學習