Webpack + vue 搭建

快速到達:初始化項目     入口文件     webpack配置    配置路由    配置Vuex     eslint     webpack生產環境配置    常見錯誤總結 css

前言: 爲什麼使用webpack? 爲什麼相對於gulp&grunt更有優點

WebPack(前往官網)能夠看作是模塊打包機:直接分析項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其打包爲合適的格式以供瀏覽器使用。Gulp/Grunt是一種可以優化前端的開發流程的工具。html

   Grunt和Gulp的工做方式是:在一個配置文件中,指明對某些文件進行編譯,組合,壓縮等任務的具體步驟,運行以後自動逐步完成設定的任務。
前端

   而WebPack是一種模塊化的方案,經過給定的主文件(如:index.js)使用不一樣的loaders處理項目的全部依賴文件,最後打包爲一個瀏覽器可識別的JavaScript文件。
vue

   其實二者並不具有太多可比性,grunt/gulp 在配置上比較簡單,環境搭建更容易實現;而webpack的處理速度更快更直接,能打包更多不一樣類型的文件。html5

開始使用webpack

相關的技術:webpack@2,vue@1,vue-router@0.7,vuex@1 node

目錄結構:

<ul>
<li>config全局變量
<li>dist編譯後的項目代碼</li>
<li>src項目代碼
<ul> <li> apis api封裝react

<li>components Vue組件
<li>libs js工具類
<li>router 路由
<li>index.js 路由對象
<li>routes.js 路由配置
<li>store Vuex的store
<li>modules vuex模塊
<li>types.js type管理
<li>styles css樣式
<li>views 頁面組件
<li>main.js vue入口文件</ul>

<li>webpack.config Webpack各類環境的配置文件
<li>package.json
</ul>webpack

step1   初始化項目 ---- Webpack 使用npm安裝

1.建立項目文件夾, npm init -y 建立 package.json git

2.項目根目錄下創建srcdist文件夾,分別用來存放項目源碼webpack編譯後的代碼es6

step2   入口文件--- 簡單跑一下

1.在根目錄下直接創建一個index.html,做爲頁面的入口文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
</head>
<body>
  <div id="app">{{message}}</div>  <!-- Vue模板入口 -->
  <script src="dist/main.js"></script>
</body>
</html>

2.在src下創建一個main.js,做爲Vue的入口文件

// require的語法是Commonjs的,webpack自身能夠實現直接使用
// es6的語法須要依賴babel哦
const Vue = require('vue')
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
      }
})

3.安裝模塊: vue npm install vue@1 --save ; webpack npm install webpack --save-dev(在本地安裝)

本地安裝的webpack 須要在package.json的 scripts 配置中添加運行腳本

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack src/main.js dist/main.js"  // <---自行添加,指定運行的文件 **webpack [入口文件] [出口文件]**
 },

運行npm run dev,再用瀏覽器打開index.html就能看到效果了:

Hello Vue.js!

全局安裝webpack npm install -g webpack 則無需指定腳本~

step3   編寫webpack配置文件 !!

在上一步中專門指定了webpack運行腳本去運行指定的文件,但實際開發中,對於不一樣環境的大型項目/系統開發顯然是不知足的。所以建立一個文件專門存放webpack配置~

1.在根目錄下建立 webpack.config 文件夾來存放webpack的配置文件;

2.在上面的目錄下首先建立一個base.js文件來存在一些公共環境下的配置文件(例如loaders的配置)

const path = require('path')
const root = path.resolve(__dirname, '..') // 指向 根目錄

module.exports = {
entry: path.join(root, 'src/main.js'),  // 項目入口文件
output: {
path: path.join(root, 'dist'),  // 出口目錄
filename: 'main.js'  // 出口文件名
    }
}

以上便實現了「webpack src/main.js dist/main.js」webpack指定 入口文件 -> 出口文件 的功能了。

此外還能夠拓展一下,使得兼容更多的功能~ (webpack@2 resolving)

const path = require('path')
const root = path.resolve(__dirname, '..') // 根目錄

module.exports = {
entry: path.join(root, 'src/main.js'),  // 入口文件
output: {
path: path.join(root, 'dist'),  // 出口目錄
filename: 'main.js'  // 出口文件名
},
resolve: {
   alias: { // 配置目錄別名,來確保模塊引入變得更簡單
     // 在任意目錄下require('components/example') 至關於require('項目根目錄/src/components/example')
     components: path.join(root, 'src/components'),
     views: path.join(root, 'src/views'),
     styles: path.join(root, 'src/styles'),
     store: path.join(root, 'src/store')
   },
   extensions: ['.js', '.vue'], // 引用js和vue文件能夠省略後綴名 (此處有坑坑坑==。)!!webpack@2+已經再也不要求強制轉入一個空字符串
   resolveLoader: {
   module: { // 配置loader
   loaders: [
     {test: /\.vue$/, loader: 'vue'}, // 全部.vue結尾的文件,使用vue-loader
     {test: /\.js$/, loader: 'babel', exclude: /node_modules/} // .js文件使用babel-loader,切記排除node_modules目錄
    ]
  }
}

根目錄下添加.babelrc用於配置 babel

{
 "presets": ["es2015"]
 }
關於 Babel 是什麼 : 一般與webpack搭配一塊兒使用,webpack能夠看做是是打包工具,babel則視爲編譯工具,可把最新標準編寫的js代碼(例如 es6,react..)編譯成當下隨處可用的版本。是一種「源碼到源碼」的編譯(轉換編譯)!


而.babelrc就是讓 Babel 作你要它作的事情的配置文件。

babel-preset-es2015          打包了es6的特性

使用了vue-loader和babel-loader須要安裝包: 運行以下命令(可能有坑哦,若踩可見文末 bug修復篇==。)

npm install --save-dev vue-loader@8 babel-loader babel-core babel-plugin-transform-runtime babel-preset-es2015 css-loader vue-style-loader vue-hot-reload-api@1 vue-html-loader

3.在 webpack.json 中建立 dev.js

const path = require('path')
  const webpack = require('webpack')
  const merge = require('webpack-merge')
  const baseConfig = require('./base')
  const root = path.resolve(__dirname, '..')
      
  module.exports = merge(baseConfig, {})  \\首先 與base.js一樣的配置

其中 webpack-merge 用於合併兩個配置文件,須要安裝 => npm install --save-dev webpack-merge

4.自行搭建一個小型服務器,以避免手動調試 index.html 。定義使用 webpack dev server 。 (webpack@2 Proxy)
所以須要繼續配置dev.js以下: 還有其餘一切配置,可查閱 webpack-dev-server-cli

module.exports = merge(baseConfig, {
devServer: {
historyApiFallback: true, // 404的頁面會自動跳轉到/頁面
 inline: true, // 文件改變自動刷新頁面
// progress: true, // 顯示編譯進度 !!有坑,待解決。下同~ 暫時不加這兩個屬性繼續走下去吧~!
// colors: true, // 使用顏色輸出
 port: 3800, // 服務器端口  !!注意不要被佔用了哦
},
 devtool: 'source-map' // 用於標記編譯後的文件與編譯前的文件對應位置,便於調試
})

5.添加熱替換配置 HotModuleReplacementPlugin ,每次改動文件不會再整個頁面都刷新。該配置是webpack內部插件,不須要安裝。

module.exports = merge(baseConfig, {
 entry: [
   'webpack/hot/dev-server', // 熱替換處理入口文件
    path.join(root, 'src/index.js')
 ],
devServer: { /* 同上 */},
plugins: [
new webpack.HotModuleReplacementPlugin() // 添加熱替換插件
  ]
}

6.使用 HtmlWebpackPlugin ,實現js入口文件自動注入。npm install --save-dev html-webpack-plugin,且須要在頭部引入 => const HtmlWebpackPlugin = require('html-webpack-plugin') (還在dev.js中哦)

module.exports = merge(baseConfig, {
entry: [ /* 同上 */ ],
devServer: { /* 同上 */ },
plugins: [
  new webpack.HotModuleReplacementPlugin(),
  new HtmlWebpackPlugin({
    template: path.join(root, 'index.html'), // 模板文件
    inject: 'body' // js的script注入到body底部
    })
  ]
}

7.修改index.html(根目錄i 啊),去掉入口文件的引入:<script src="dist/main.js"></script>
8.修改package.json 的運行腳本:

{
 "dev": "webpack-dev-server --config webpack.config/dev.js"//指向配置文件,而不是某一單一頁面的js
}

再來跑一下,檢測是否webpack配置都成功運做了。建立一個vue組件 src/components/Hello.vue

<template>
<div>{{message}}</div>
</template>

<script>
  export default {
    data: () => ({message: 'Hello Vue.js!'})
   }
</script>

相應的main.js也作出修改:

// import...from的語法是ES6的,因爲已經安裝了babel(可編譯),故能夠直接使用
import Vue  from 'vue'  
import Hello from './components/Hello.vue'

new Vue({
  el: '#app',
  template: '<div><hello></hello></div>', 
  components: {Hello}
})

運行npm run dev,瀏覽器打開 localhost:3800 查看結果 Hello Vue.js! 而且改動頁面會自動刷新,不須要再一遍遍command+r刷新啦。

step4   配置路由

1.安裝 vue-routernpm install --save vue-router@0.7 (固然了當下的vue + axois 會更搭哦)

2.src下建立views文件夾,用於存放頁面組件;另外再建立router文件夾,用於存放全部路由相關的配置

3.添加路由頁面 src/views/Home.vue:

<template>
  <div><hello></hello></div>
</template>

<script>
  import Hello from 'components/Hello' //引入已寫vue組件
  export default {
    components: {Hello}
   }
</script>

4.添加 src/router/routes.js 文件,用於配置項目路由:

import Home from 'views/Home'

export default {
  '/': {
    name: 'home',
    component: Home
     }
 }

5.添加路由入口文件 src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'

Vue.use(Router)

const router = new Router({
  hashbang: false,  // 關閉hash模式
  history: true,    // 開啓html5history模式
  linkActiveClass: 'active' // v-link激活時添加的class,默認是`v-link-active`
})

router.map(routes)

router.beforeEach(({to, next}) => {
  console.log('---------> ' + to.name)  // 每次調整路由時打印,便於調試
  next()
})

export default router

6.再次修改main.js

import Vue  from 'vue'
import router from './router'  //直接導入路由配置    

const App = Vue.extend({})

router.start(App, '#app')

7.最後別忘了index.html:

<div id="app">{{message}}</div>  <!-- 讀取Vue,替換成? -->   
     
      <router-view></router-view><!--路由替換位置-->

能夠再次執行 npm run dev: 瀏覽器直接訪問 localhost:3800查看效果。

step5    配置Vuex

(vuex)
專門爲vue.js開發而配套的 狀態管理模式 .一般用於存放和管理不一樣組件中的共用狀態,例如不一樣路由頁面之間的公共數據.

其餘 幾個概念:
state:狀態,即數據 ;
store:數據的集合,一個vuex引用,僅有一個store,包含n個state
mutation:state不能直接賦值,經過mutation定義最基本的操做
action:在action中調用一個或多個mutation
getter:state不能直接取值,使用getter返回須要的state
module:store和state之間的一層,便於大型項目管理,store包含多個module,module包含state、mutation和action

1.安裝 : npm install --save vuex@1 添加 src/store 文件夾,存放vuex相關文件,添加 src/store/modules 用於vuex分模塊管理 ;
2.添加 src/store/types.js,vuex的全部mutation type(操做類型)建議放在一塊兒,有效避免重名狀況:

export const INCREASE = 'INCREASE' // 累加
export const RESET = 'RESET' // 清零

3.vuex模塊,添加 counter 模塊目錄 store/modules/counter添加 store/modules/counter/actions.js

import {INCREASE, RESET} from 'store/types'

 export const increase = (({dispatch}) => {
 dispatch(INCREASE) // 調用type爲INCREASE的mutation
})

export const reset = (({dispatch}) => {
 dispatch(RESET) // 調用type爲RESET的mutation
})

添加 store/modules/counter/index.js

import{INCREASE, RESET} from 'store/types.js'

 const state = {
    count: 0
  }

 const mutations = {
  [INCREASE] (state) { state.count++ },
  [RESET] (state) { state.count = 0 }
}

export default {state, mutations}

4.vuex入口文件: store/index.js:

import Vue from 'vue'
import Vuex from 'vuex'
import counter  from 'store/modules/counter'

Vue.use(Vuex) // 確保在new Vuex.Store()以前

export default new Vuex.Store({
  modules: {counter}
 })

5.修改main.js,將store引入並添加到App中:

import Vue  from 'vue'
import router from './router'
import store from 'store'

const App = Vue.extend({store})

router.start(App, '#app')

6.改造一下 src/components/Hello.vue,把action用上:

<template>
 <div>
    <p>{{message}}</p>
    <p>click count: {{count}}</p>
    <button @click="increase">increase</button><!--能夠直接調用引入的action-->
    <button @click="reset">reset</button>
  </div>
</template>

<script>
  import {increase, reset} from 'store/modules/counter/actions' // 引入action
  export default {
    data: () => ({message: 'Hello Vue.js!'}),
    vuex: {
    actions: {increase, reset},
    getters: {
        count: ({counter}) => counter.count
      }
    }
  }
</script>

step6   配置eslint ---規範js編碼

eslint定義的是編碼風格,巧妙利用提供的rules,能夠自定義配置 ,增減規則 ; 同時,在使用中檢測不經過,不必定不能運行,只是違反了規則==。監督自我。

網上也已經有不少現有的配置了,建議(standard)
1.配置.eslintrc文件

{
  "parser": "babel-eslint", // 支持babel
  "extends": "standard", // 使用eslint-config-standard的配置
  "plugins": [
     "html" // 支持.vue文件的檢測
  ],
  "env": {
    "browser": true, // 不會將window上的全局變量判斷爲未定義的變量
    "es6": true // 支持es6的語法
  },
  "rules": { // 自定義個別規則寫在這,0忽略,1警告,2報錯
  "no-unused-vars": 1 // 將」未使用的變量「調整爲警告級別,原爲錯誤級別,更多規則請看官網
  }
}

用了啥就安裝啥:npm install --save-dev eslint babel-esli nt eslint-config-standard eslint-plugin-standard eslint-plugin-html eslint-plugin-promis

step7 webpack生產環境配置 ---對於編譯出來的文件進行壓縮,提取公共模塊等操做

1.添加webpack.config/pro.js文件,相比dev.js把生產環境用不到的刪掉,好比webpack-dev-server、webpack-hot-replacement.

const path = require('path')
 const webpack = require('webpack')
 const merge = require('webpack-merge')
 const HtmlWebpackPlugin = require('html-webpack-plugin')
 const baseConfig = require('./base')
 const root = path.resolve(__dirname, '..')

 module.exports = merge(baseConfig, {
       plugins: [
        new HtmlWebpackPlugin({
        template: path.join(root, 'index.html'), // 模板文件
        inject: 'body' // js的script注入到body底部
     })
   ]
})

(經常使用插件)

extract-text-webpack-plugin 提取css到單獨的文件
compression-webpack-plugin 壓縮gzip
webpack.optimize.UglifyJsPlugin 壓縮js文件,內置插件
.....

2.在package.json中添加運行腳本:"build": "webpack --config webpack.config/pro.js";

3.運行npm run build,能夠在dist文件夾中看到打包好的文件~~

webpack+vue的環境搭建到此算是初見雛形了,具體時實際運用還須要更多的實踐

常見錯誤總結

安裝一些npm包失敗: 出現背景:執行npm install --save dev ....時

查問題shasum check failed


人話:npm鏡像源錯誤。

解決:1.經過config命令

npm config set registry http://registry.cnpmjs.org 
npm info underscore

2.命令行指定

npm --registry http://registry.cnpmjs.org info underscore

以上兩種均可以快速解決安裝問題,但治標不治本,下次安裝時仍會出現。所以推薦?,直接在配置中指定寫死,一勞永逸~

3.編輯 ~/.npmrc 加入以下配置:

registry = http://registry.cnpmjs.org

npm版本過低報錯:


解決:
一、首先安裝n模塊 npm install -g n

二、升級node.js到最新穩定版 n stable
若肯定在最新版本中仍是在報錯的話,則須要檢查是否時webpack.config中配置有錯誤,webpack@1.xx->webpack@2.xx 各中的(升級特性) 仍是很重要的

出現segmentation fault 11報錯: 出現背景:在一次須要最新版本的node時,捨棄了$n stable穩定版(由於系統仍是提示須要升級最新版)執行 sudo n latest 後升級過慢,中間不夠穩定,直接強行被退出。以後再運行,關於npm 和node 的全部命令均在報segmentation fault 11這個錯誤。

覺得os被玩壞了,系統錯亂,嚇死寶寶了==。

緣由:執行n命令,顯示當前沒有選中任何版本。 解決:用n命令從新設置要使用的版本 sudo n 版本號

版本過低的報錯


解決:執行npm install --save-dev eslint-plugin-import@^2.0.0
npm install --save-dev eslint-plugin-node@4.2.2

完。感謝閱讀,不足之處歡迎指出~thx!

                wendy.wenxia@foxmail.com          2017/05/18

相關文章
相關標籤/搜索