1. 程式人生 > >詳解 Vue + Webpack 的配置

詳解 Vue + Webpack 的配置

前端的價值

  •   搭建前端工程
  •   網路優化
  •  API定製
  •  nodejs層

Vue + Webpack 打造todo應用

  第1章 vue + webpack 專案工程配置

 1.1 vue-loader + webpack專案配置

 專案初始化: ` npm init `
 安裝:  ` npm install webpack vue vue-loader `
  安裝完後可以看見WARN,根據WARN繼續下載相應的依賴`css-loader vue-template-compiler`
 這樣一個專案就初始化好了。
*  新建src目錄,新建app.vue檔案,裡面寫上基本的 
   *  `<template>...</template>`
   *  `<script> export default{ data(){  return{ }   } }</script>`
   *  `<style></style> `
* 顯然這個檔案是不能在瀏覽器執行的,這個時候需要新建webpack.config.js檔案
   * webpack是用來幫我們打包前端資源的.資源有很多型別: css、js、img、字型...
   * 這些資源都是要通過http請求載入的內容
   * 在開發webapp的過程中,很多時候都是將一整個js檔案載入到瀏覽器然後把所有的內容渲染出來
   * 所以很多時候可以簡單的以js檔案作為入口
* 在src下新建index.js作為入口
* app.vue是一個元件,這個元件不能直接掛載到html裡面去
   * 要進行掛載,則在index.js裡面

 ```
 import Vue from 'vue'            引入 Vue類庫
 import App from './app.vue'      引入要掛載的檔案

 const router  = document.createElement('div')
 document.body.appendChild(root)     

 new Vue({      建立Vue例項
       render: (h)=>h(App);   h引數實際上是Vue裡的createApp引數,通過它把App的內容渲染出來
 }).$mount(root)            掛載--通過.$mount()到html裡的一個節點上.


 節點可以自己建立。
 `.$mount(root)`將vue的內容插到root裡面,這樣就可以展示app.vue元件裡面需要展示的內容
 ```
*  webpack.config.js檔案
 
```
const path = require('path')
module.exports = {      
   entry : path.join(__dirname,'src/index.js'),     設定入口  -- 絕對路徑,保證不出錯
   output:{                                         設定出口
      filename: 'bundle.js',                        出口檔名
      path:path.join(__dirname,'dist')              出口路徑 -- 在當前目錄下建立一個dist目錄
 },

*  輸入一個index.js檔案,webpack會把該檔案以及它裡面所依賴的(比如:vue,app)都打包成一個完整的bundle.js,
*  並且打包的是我們能在瀏覽器裡執行的js程式碼.
*  然後在package.json里加一個指令碼(配置)
    *  第一個物件的sripts的裡面加入 ` "build":"webpack --config webpack.config.js"`
*  為什麼要在這個檔案裡面寫? 
    *  因為只有在這裡面呼叫webpack,它才會呼叫安裝在這個專案裡面的webpack;
    *  如果直接在命令列裡輸,它會呼叫全域性的webpack,那這個全域性的webpack可能跟我們專案裡使用的版本不一樣。
    *  所以在這裡使用這種方式會好一點。
*  這個時候命令列`npm run build`
    *  報錯: Error in ./sr/app.vue
             Module parse failed:Unexpected token(1:0)
             You may need an appropriate loader to handle this file type. 
    *   這是告我我們: 需要為.vue檔案去宣告一個loader
    *   因為webpack原生是隻支援js檔案型別的,並且它支援的語言只是ES5的語法.
    *   所以在我們要使用超出它理解範圍的語法的時候,我們要使用一些幫它去處理這些語法的工具.去幫我們處理這些檔案
*   怎麼做呢? 增加module配置

   module: {
      rules: [                 rules規則,它是一個數組,可以在裡面寫很多的rules
           {test: /.vue$/ , loader:'vue-loader'}   
      ] 
    *  test: 檢測一個檔案型別,是一個正則(以.vue結尾的); 該型別檔案的loader是'vue-loader
    *  這樣,在webpack裡面就由vue-router來為webpack去處理.vue型別的檔案,最終能輸出正確的js程式碼
   }
}
``` 

*  再去跑一下 ` npm run build`
    *  沒有報錯,顯示bundle.js xxkb, 可見到根目錄下多了一個dist目錄,裡面有一個bundle.js,可以進去看一下
    *  上面一段是webpack固有的程式碼,用來處理模組依賴;
    *  下面是vue的原始碼,因為我們要依賴vue這個包,所以它將vue整個打包到這個js裡來.也可以將它分離出去
    *  搜一下`$mount()`,可找到程式碼, 和我們寫的幾乎一樣。
*  所以webpack它做的事情,其實就是把不同的靜態資源的型別打包成一個js,然後我們在html裡面引用這個js的時候,html裡面的js就可以正常執行,然後去執行我們的操作。
*  做前端專案的時候,我們希望把很多零碎的js打包到一起,因為這樣可以減少http請求。
*  同樣我們會做模組依賴,因為我們會做很多可複用的程式碼,把它寫到一個模組裡面去.這樣我們在下次有新專案時,可以使用原來的模組,而不需要把原來的程式碼重新寫一遍或者拷貝一份.
    *  拷貝一份的意思就是:如果你兩個專案使用同一份的程式碼,它裡面如果有一個問題你就要修改兩邊。

   1.2 webpack配置專案載入各種靜態資源及CSS前處理器

 同樣是配置各種loader  

module: {
  rules: [             
    {test: /\.vue$/ , loader:'vue-loader'},                       
       /*
        * {test: /\.css$/ , loader:'css-loader'},
        * 正則表示式的.是要轉譯的,用\
        * 這個css-loader 只是幫我們處理了css檔案
        * css在前端專案執行的時候,是要作為一個外部檔案去處理的,
        * 或者是把樣式寫到html內容裡面作為一個style標籤把裡面的樣式全部列出來
        * 所以有不同的處理方式
        * 這個方式怎麼去宣告它呢?就要換一個模式,使用use,它是一個數組 
        */
    {test: /\.css$/ , use:['style-loader','css-loader']},
           /*
            * 'css-loader'只是將css檔案裡的內容讀出來
            * 至於最終是寫到一個css檔案裡面還是html的style標籤裡面要用其他的loader去處理
            * 'style-loader' 寫到html裡面的方式
            */
    { test:/\.styl/ , use:['style-loader','css-loader','stylus-loader']},
        /*
         * CSS前處理器,也就是說可以模組化的去寫CSS程式碼.
         * stylus-loader專門用來處理stylus檔案,它處理完成後是css內容.
         * 所以css內容怎麼處理,它還要扔給上一級css-loader
         * webpack的loader就是這麼一層一層的往上扔的,往上扔得過程中其實就代表每一個loader只處理它關心的那一部分
         * 這種方式的好處就是它可以無數種的loader進行搭配,最終達到一個你想要的結果
         * 注意安裝stylus-loader,而它依賴stylus包,也要安裝
         * 在index.js檔案裡import相關檔案就可以跑一下了
         * 同理sass,less等css編譯器也可以在webpack裡面配置對應的loader
         */
    {  test: /\.(gif|jpg|jpeg|png|svg)$/ , 
        use:[             // 這裡use裡面包著物件,因為每個loader是可以配置一些選項的
           { loader:'url-loader',options:{limit:1024, name:'[name].[ext]' } },
        ]
    } 
  ]      
}
``` 
* 在options裡面指定url-loader的一些操作方式.
  * `url-loader`可以將圖片轉化成base64程式碼,直接寫在js裡面而不用生成一個新的檔案.
     * 這樣對於幾kb的小圖片作用是挺大的,因為可以減少http請求.
  * `url-router`其實是封裝了一下 file-router,
     * file-router將圖片讀取一下,然後再進行一些簡單的操作之後再把這個圖片檔案重新換一個名字換一個地方,把它存在另外的地方。
     * 所以url-router就判斷圖片的大小,如果<limit,它就會去將圖片轉譯成base64程式碼,寫到我們的程式碼裡面去
  * `name`:指定輸出檔案的名字.
     * 這個檔案的名字可以使用一些webpack的選項來幫我們定義這個名字.因為有可能有很多的圖片
     * `name:'[name].[ext]'`根據原來進來的名字輸出.使用 []包含一個name,[ext]是檔案的副檔名.注意引號
     * 也可以隨便加一些,比如說 ` name:'[name]-aaa.[ext]' `
*  這些配置完以後,將相應的loader安裝一下 ` npm i style-loader url-loader file-loader`
     *  file-loader是url-loader的依賴,所以也要安裝
*  安裝完以後,就可以在js檔案裡去import這些非js的內容. 
*  怎麼import呢?
     *  在src目錄下建立assets目錄.
         *  在其下images目錄,放入專案需要的圖片;
         *  建立style目錄,放入css檔案;
     *  這樣就可以在index.js檔案裡去import
*  然後可以看見dist目錄下多了圖片檔案,而css檔案由於用了style-loader所以寫入了bundle.js檔案.
*  搜尋body可以看到出現在`exports.push()`裡面。
*  如果css裡面還依賴了別的檔案,webpack依然會幫我們處理.這就是它的強大之一。
 
#### 1.3 webpack-dev-server的配置和使用
 * 可以體驗到一個非常高效、方便的開發模式,提高我們的開發效率
 * `webpack-dev-server` 是webpack的一個包,需要安裝 : `npm i webpack-dev-server`
 * `webpack-dev-server`的簡單實用方法:
   * 在build時,使用的是webpack去啟動webpack.config.js檔案,然後webpack就會幫我們打包js程式碼
   * 如果要使用webpack-dev-server,只需要在package.json裡配置的build後面加一行命令`"dev" : "webpack-dev-server --config webpack.config.js"`
   * 使用的是同一個webpack的配置檔案-->webpack.config.js。
* `webpack-dev-server`會給我們帶來和`webpack`不一樣的效果。
* 它是專門用在開發環境的,當然也要修改一下webpack的配置來專門適合`webpack-dev-server`的開發模式。
```  
const path = require('path')
const HTMLPlugin = require('html-webpack-plugin')
const isDev = process.env.NODE_ENV === development      宣告變數,便於判斷
const config = {             由於需要判斷就不能用module.exports了
      1.先在全域性加一個target
 target:"web",     因為我們開發的是前端專案,跑在瀏覽器裡面的,所以webpack的編譯目標是web平臺。
 entry : path.join(__dirname,'src/index.js'),      
 output:{                                          
    filename: 'bundle.js',                        
    path:path.join(__dirname,'dist')                
 }
 module: {
    rules: [              
       {test: /.vue$/ , loader:'vue-loader'}, 
       {test: /\.css$/ , use:['style-loader','css-loader']}, 
       {test:/\.styl/ , use:['style-loader','css-loader','stylus-loader']},
       {test: /\.(gif|jpg|jpeg|png|svg)$/ , use:[ { loader:'url-loader',options:{limit:1024, name:'[name].[ext]' } }  ]  }
    ] ,
    plugins: [                它是一個數組.可以接受很多個plugin
        new webpack.DefinePlugin({ 使用vue,react這些框架時,一定要用webpack的plugin-->webpack.DefinePlugin
            'process.env':{           給它定義一個變數
                NODE_NEV:isDev?'"development"':'"production"'   單引號裡的雙引號一定要加
            }
        }),
        new HTMLPlugin()   這樣webpack的plugin就加進去了.它是一個最基礎的配置,但是裡面有很多引數,看文件。
    ]
  }
}
   2.判斷一下.
     因為這個配置檔案是要同時用在正式環境和開發環境的,所以這裡的配置要根據不同的環境去做一些判斷。
   * 如何去判斷?
     * 根據在跑`npm scripts`的時候給它設定一個環境變數,來標識現在是開發環境還是生產環境
   * 變數怎麼設定?
     * 安裝一個包 `npm i cross-env`
     * 因為在不同的平臺上設定環境變數的方式是不一樣的.
   * package.json檔案裡: 
     * Mac平臺上直接設定`"build":"NODE_ENV=production webpack --config webpack.config.js"`就能讀取這個環境變數NODE_ENV=production;
     * 但在windows平臺,使用`"build":"set NODE_ENV=production webpack --config webpack.config.js"`方式來做
     * 不想為不同的平臺寫兩個命令,所以用cross-env: `"build":"cross-env NODE_ENV=production webpack --config webpack.config.js"`
   * 直接cross-env在寫上環境變數NODE_ENV=production,這樣就可以讓我們在不同的平臺裡面都可以去執行同一個指令碼
     * dev環境肯定要設定成一個不一樣的NODE_ENV,它的NODE_ENV是development==>` "dev":"cross-env NODE_ENV=development webpack --config webpack.config.js"  `
     * 這樣命令就寫好了,可以去webpack.config.js裡去判斷了.
 * 首先在最上面設定一個變數 isDev: ` const isDev = process.env.NODE_ENV ===development`    
 * ` process.env.NODE_ENV `是否等於 `development `,以此來判斷isDve是否是true。
 * 在啟動指令碼時設定的這些變數全部都是存在於 process.env這個物件裡面的,
 * 所以package.json中可以設定很多的變數名,然後都可以通過` process.env.變數名 `去讀到。
        
if(isDev){
  config.devServer ={   在config上加一個devServer的設定.
      // devServer是一個物件,在webpack2的時候加入的,所有關於webpack dev的設定全寫在了裡面。
      port:8000,                   devServer會啟動,啟動後它是一個伺服器,需要監聽一個埠 。  
      host:'0.0.0.0',              一般會設定成'0.0.0.0'。
        // 好處:可以通過localhost:127.0.0.1來進行訪問 ,同時也可以通過本機的內網IP進行訪問.
        //如果直接設定成localhost,通過內網IP是無法訪問的.
        //通過IP訪問的好處:在別的電腦導航也可以訪問這臺電腦,或者除錯手機頁面時可以通過手機去連結我們的電腦去訪問。
      overlay:{                      
            errors:true,           如果在webpack編譯的時候,有任何的錯誤,都讓它顯示到網頁上面。
      }  
  }                    
}
module.exports = config        這樣的話我們可以在上面隨意的去改配置。
``` 
* 可以看到我們現在編譯的東西都是js、圖片什麼的,沒有一個html去容納我們的這個js檔案,那麼這個專案是跑不起來的.
  * 因為作為前端專案,肯定要有一個html作為入口
* 這個html應該怎麼做,又能讓它自動包含js檔案?
* 在webpack裡面有一個非常好用的元件: `html-webpack-plugin`. 
  * 先安裝再引入。

第2章 vue 介紹和專案實戰

2.1 vue2的核心只是介紹 2.2 配置vue的jsx寫法以及postcss 2.3 實現todo應用的介面 2.4 實現todo應用的業務邏輯  

第3章  webpack 配置優化

3.1 webpack配置css單獨分離打包 3.2 webpack區分打包類庫程式碼及hash優化