腳手架vue-cli系列四:vue-cli工程webpack的基本用法

webpack的打包依賴於它的一個重要配置文件webpack.config.js,在這個配置文件中就能夠指定全部在源代碼編譯過程當中的工做了,就一個配置就能夠與冗長的Gruntfile或者Gulpfile說再見了。javascript

一個完整的工程項目中的webpack的配置遠遠沒有這麼簡單,隨着工程的構建要求的增長,webpack.config.js內的配置項目也會隨之增長,webpack還有許許多多的選項提供給咱們進行靈活配置,它只是一個構建工具,咱們只須要了解在Vue項目中它基本能爲咱們作到的工做、最小化的配置是如何的就足夠了,在之後須要對它進行擴展與優化時,帶着問題去查官方文檔也是很是容易的事。css

●  樣式表引用html

某些頁面或者組件可能具備特定的樣式定義,這些樣式對於其餘頁面來講是冗餘的,咱們只但願這些組件在應用時才自動加載這些特定的樣式,此時用webpack咱們就能在源代碼中加入如下代碼來動態加載CSS:vue

import Vue from 'vue'
    // ... 省略
    // 引用指定的樣式源文件
    import './app/assets/less/dark.less'
    
    export default {
      // ... 省略
    }

此時咱們只須要在webpack的配置中加入less-loader,那麼webpack在打包的時候就會自動將less轉換爲CSS,並將CSS的動態代碼生成到JS文件中。當Vue組件被加載到頁面並實例化後,將在DOM內插入這個特定的行內樣式<style>以實現動態樣式的應用。java

對於*.css文件一樣也是適用的,例如導入某個第三方庫中必需的樣式表:webpack

import 'uikit/dist/css/components/tabs.css'

●  字體的引用git

假設在dark.less內加入對自定義字體文件的樣式定義:github

@font-face {
       font-family: 'Darkenstone';
       src: url('./Darkenstone.eot');
       src: url('./Darkenstone.eot?#iefix') format('embedded-opentype'),
           url('./Darkenstone.woff2') format('woff2'),
           url('./Darkenstone.woff') format('woff'),
           url('./Darkenstone.ttf') format('truetype'),
           url('./Darkenstone.svg#Darkenstone') format('svg');
           font-weight: normal;          
           font-style: normal;
}

.header{
       display: flex;
       flex-flow: row nowrap;

       & > h1 {
          font: 16pt 'Darkenstone';
       }
}

這裏.header>h1指定了一個Darkenstone的自定義字體,這個字體瀏覽器必定是不能識別的,之前咱們在樣式表中先定義這個字體樣式並指定加載位置(如上文@font-face的定義),而後在頁面中引用這個樣式表,這是多麼麻煩的一件事,不是嗎?web

若是用了webpack後,咱們只是在配置文件內加入了一個url-loader:vue-router

{
      test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
      loader: 'url'
}

咱們並不須要在源代碼中作任何改變,由於以前已經引用過樣式表dark.less,而字體是在樣式表中的,webpack將在打包的時候爲咱們識別並在代碼中引入字體的動態加載。這樣一來極大地解決了咱們對資源引用的依賴問題!

vue-cli的webpack模板已經爲咱們配置好了絕大多數經常使用的loader,在實際運用中咱們只須要了解它們是怎麼來的,應該怎麼用,須要的時候如何修改就夠了。

●  用別名取代路徑引用

在項目開發過程當中有可能有許多包是沒有放在npm上的,有一些較老的可能還依然只存在於bower上,某些甚至在bower與npm上都找不到,而不得不經過下載的方式在項目內引用,這樣一來咱們的代碼可能經過require就得在代碼內引用一段很長的文件路徑,以下所示

import Selector from '../../bower_components/bootstrap-select/dist/js/select'

這種包的引用方式明顯違反了CommonJS的編程規範,對於這些長路徑,甚至還具備「../..」這些相對路徑搜索的定義,咱們能夠經過webpack的resolve配置項來解決。就以select這個組件爲例,在webpack.base.config.js中加入如下的這個別名的定義:

module.exports = {
       entry:{ ... },
       output: { ... },
       module:{ ... },
       resolve: {
          extensions:['','.js'],
          alias:{ // 別名
             'bs-select':'bower_components/bootstrap-select/dist/js/select.js'
          }
       }
    }

有了這個定義之後,咱們就能夠將上面那個長引用改成下面的寫法:

import Selector from 'bs-select';

絕對不要讓路徑引用進入到咱們的代碼,由於這是代碼的「癌症」,一旦開始植入並生長起來,之前的代碼將難以維護!

●  配置多入口程序

多數狀況下咱們的程序入口不僅僅只有一個,舉一個最簡單的例子,前臺提供給最終用戶使用(http://www.domain.com/index),後臺提供給登陸用戶使用(http://www.domain.com/admin/),那麼天然須要多個與main.js相似的程序入口了。

首先在build/webpack.base.conf.js配置文件中的entry配置屬性上加上新的入口文件:

module.exports = {
      entry: {
        app: './src/main.js',
        admin : './src/admin-main.js'
      },
      // ... 省略
    }

這是用於告訴webpack哪幾個是入口文件,這些文件須要被生成到啓動頁的<script>內。

vue-cli的webpack模板使用HtmlWebpackPlugin插件,生成HTML入口頁面並自動將生成後的JS文件和CSS文件的引用地址寫入到頁內的<script>中。

這裏就須要在build/webpack.dev.config.js文件內的plugins配置項內多配置一個HtmlWebpackPlugin插件,用於生成admin.html入口頁。

plugins:[
      // ... 省略

      // 這是原有的配置項,用於匹配注入app.js的輸出腳本
      new HtmlWebpackPlugin({
        filename: process.env.NODE_ENV === 'testing'
          ? 'index.html'
          : config.build.index,
        template: 'index.html',
        chunks: ['app'], // 與原配置的不一樣的是要用chunks指定對應的entry
        inject: true,
        minify: {
          removeComments: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true
        },
        chunksSortMode: 'dependency'
      }),

      // 這是新增項,用於匹配注入admin.js的輸出腳本
      new HtmlWebpackPlugin({
        filename: process.env.NODE_ENV === 'testing'
          ? 'admin.html'
          : config.build.admin,
        template: 'index.html',
        chunks: ['admin'],
        inject: true,
        minify: {
          removeComments: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true
        },
        chunksSortMode: 'dependency'
      }),
    ]

須要強調一點的是,這裏的HtmlWebpackPlugin配置必須用chunks指定在上文entry內對應的入口文件的別名。

關於HtmlWebpackPlugin更多配置內容能夠參考:https://github.com/kangax/html-minifier#options-quick-reference。

還有就是得將一樣的配置加入到生產環境專用的webpack配置文件webpack.prod.conf.js中,不然當咱們運行npm run build時是不會輸出admin.js和admin.html這兩個入口文件的(因爲配置內容相同這裏就再也不重複了)。

最後,若是使用了vue-router就得對connect-history-api-fallback插件的配置進行修改,不然原有的默認配置只會將全部的請求轉發給index.html,這樣就會致使History API沒有辦法正確地將請求指向admin.html,致使熱加載失敗,具體作法以下所述。

打開dev-server.js文件,將app.use(require('connect-history-api-fallback')())配置改成如下的方式:

// handle fallback for HTML5 history API
    var history = require('connect-history-api-fallback')
    // app.use(require('connect-history-api-fallback')())

    app.use(history({
      rewrites: [
        { from: /^\/admin\/.*$/, to: '/admin.html' }
      ]
    }));

新入口須要有明確區分的路由規則,不然仍是會產生熱加載失敗的狀況,這樣就很是不便於開發了。

相關文章
相關標籤/搜索