webpack配置0~1 進階篇

扯淡的話

我認為,學(xué)習(xí)這種工具類型的技能,掌握基礎(chǔ)部分的話,后面的就是只需要記住和主動去學(xué)習(xí)屬性配置就會玩的很好。
這一部分就是通過各種各樣的loader和plugin的屬性配置來將基礎(chǔ)部分的webpack配置。

明顯存在的問題

在lesson1中有很多明顯的問題:

  • 1、css代碼冗雜在js代碼中
  • 2、打包出來的文件一直為一個bundle.js會引起瀏覽器緩存
  • 3、開發(fā)代碼和打包發(fā)布(生產(chǎn))代碼沒有嚴格區(qū)分
  • 4、無圖片,json等其他文件類型的處理

那么下面便一點點的解決上述的問題:

抽離CSS代碼

在webpack4之前,可以用extract-text-webpack-plugin這個插件來解決這一問題。webpack4 暫不支持extract-text-webpack-plugin 所以需要使用extract-text-webpack-plugin@next版本 或者使用 mini-css-extract-plugin

配置也是非常簡單:

第一步需要在匹配到css代碼時用到這個插件:

     {
        test: /\.css$/, 
        use: [MiniCSSExtractPlugin.loader, 'css-loader'], // 使用MiniCSSExtractPlugin.loader來處理css代碼
        exclude: '/node_modules/'
      }

第二步是在plugins屬性中配置MiniCSSExtractPlugin

plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: 'index.html',
      title: 'DevServer'
    }),
    new MiniCSSExtractPlugin({
      filename: '[name].css' // 配置單獨出來的CSS文件名稱,默認為main.css
    })
  ],

build后:


build2.png

同時,index.html會自動引入bundle.js和main.css這兩個文件。打包生產(chǎn)的時候,直接把dist目錄上傳上去就ok了。

解決瀏覽器緩存問題

瀏覽器自動緩存了js和css文件是生產(chǎn)中常見的一個問題。解決方法卻是很簡單,我們只需將文件名稱完全更改html就會重慶獲取一次全新的js和css文件。為了保證文件名稱的唯一,在打包時我們采用hash值來幫助命名

// 輸出js文件名修改
output: {
    filename: '[name].[hash].js', 
    path: path.resolve(__dirname, 'dist')
  },

// 單獨抽離出來的css名稱修改
new MiniCSSExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].css'
    })

build結(jié)果:


build3.png

這個問題的解決方案比較簡單,但是也伴隨著另一個問題,如果我們再修改一次代碼build后,會出現(xiàn)下面這種情況:


build4.png

它不會清除之前存在的文件。這里有兩個方案供大家選擇:

一是使用clean-webpack-plugin

// 在plugins中添加這個插件配置
new CleanWebpackPlugin(['dist'], { // 接收一個數(shù)組和一個對象,數(shù)組來規(guī)定在指定目錄下刪除哪些文件,對象為配置項
      root: path.resolve(__dirname) // 定義開始清空的目錄
    })

這時候我們在運行build的時候就會發(fā)現(xiàn)dist文件先被刪除掉,然后生成了新的dist文件。不過還有個小缺陷就是在運行dev命令時,也會刪除掉dist文件。這個問題會在后面的優(yōu)化中解決。

第二個使用rimraf庫來完成刪除dist文件夾。這個庫提供的是rm -rf的刪除能力。關(guān)于這個清除功能,這里就不寫了,我覺得初學(xué)者這里會用上面那個插件就好。

區(qū)分dev和prod

寫到這里,前面的坑實在太多了,我必須要區(qū)分一下開發(fā)和生產(chǎn)這兩種環(huán)境了?,F(xiàn)在我要對整個項目的結(jié)構(gòu)做一些調(diào)整了:

org2.png

這三個配置文件各司其職,這樣做可以將dev的功能和build的功能以及他們共有的操作抽象出來。
這三個配置文件又是相互之間有聯(lián)系的,這里要用到webpack-merge來關(guān)聯(lián)他們:

base.js:

/*
 * @Author: leo 
 * @Date: 2018-08-28 11:50:44 
 * @Last Modified by: leo
 * @Last Modified time: 2018-08-28 15:30:11
 * webpack 基礎(chǔ)配置文件
 */

const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCSSExtractPlugin = require('mini-css-extract-plugin')
// 定義resolve函數(shù)便于處理路徑
const resolve = (src) => path.resolve(__dirname, '..', src)

module.exports ={
  entry: resolve('src/index.js'),
  output: {
    filename: '[name].[hash].js',
    path: resolve('dist')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: ['babel-loader'],
        exclude: '/node_modules/'
      },
      {
        test: /\.vue$/, // 匹配.vue結(jié)尾的文件
        loader: 'vue-loader',
        exclude: '/node_modules/'
      },
      {
        test: /\.css$/, 
        use: [MiniCSSExtractPlugin.loader, 'css-loader'],
        exclude: '/node_modules/'
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin({
      template: 'index.html',
      title: 'DevServer'
    }),
    new MiniCSSExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].css'
    })
  ]
} 

dev.js

/*
 * @Author: leo 
 * @Date: 2018-08-28 11:51:03 
 * @Last Modified by: leo
 * @Last Modified time: 2018-08-28 15:34:01
 * 開發(fā)環(huán)境下的webpack配置
 */
const path = require('path')
// 定義resolve函數(shù)便于處理路徑
const resolve = (path) => path.resolve(__dirname, '..', path)
const merge = require('webpack-merge')
const Base = require('./webpack.config.base')

module.exports = merge(Base, {
  devServer: {
    historyApiFallback: true,
  }
})

prod.js

/*
 * @Author: leo 
 * @Date: 2018-08-28 11:54:53 
 * @Last Modified by: leo
 * @Last Modified time: 2018-08-28 15:30:56
 * webpack 生產(chǎn)配置文件
 */
const path = require('path')
// 定義resolve函數(shù)便于處理路徑
const resolve = (src) => path.resolve(__dirname, '..', src)
const merge = require('webpack-merge')
const Base = require('./webpack.config.base')
const CleanWebpackPlugin = require('clean-webpack-plugin')

module.exports =  merge(Base, {
  plugins: [
    new CleanWebpackPlugin(['dist'], { // 接收一個數(shù)組和一個對象,數(shù)組來規(guī)定在指定目錄下刪除哪些文件,對象為配置項
      root: resolve('') // 定義開始清空的目錄
    })
  ]
})

接下來為修改package.json的命令

"build": "webpack --mode production --config build/webpack.config.prod.js",
"dev": "webpack-dev-server --mode development --config build/webpack.config.dev.js"

這樣最基本的分離工作就完成了,還有些其他的優(yōu)化在后續(xù)會慢慢完善。

我要處理其他文件

上面所有的代碼都是圍繞js,vue文件展開的。在實際開發(fā)中,除了這些之外,我們可能還需要處理JSON文件,圖片文件,還有sass less stylus等css預(yù)處理文件(代碼)等,這就需要webpack豐富的loader來處理了。這一部分可以總結(jié)為拓展loader

  • 1、處理json文件

如果是低版本(<= 2.0版本),那么處理json文件需要json-loader??梢栽谶@里看到:

json-loader.png

由于我們這里使用的是webpack4,所以json文件是可以直接處理的

  • 2、處理圖片文件

對于圖片類型的文件,webpack也有對應(yīng)的url-loader和file-loader兩種加載器來處理。這兩種loader具體有何差別呢?

url-loader相對于是file-loader的一個上層封裝,除了處理文件外,還有一個功能是限制大小,對于小于某個大小的特定圖片,可以轉(zhuǎn)換為Base64來減少請求。

// 安裝依賴
npm i url-loader file-loader --save-dev // url-loader 依賴于file-loader

// loader 配置
 {
  test: /\.(png|jpg|gif)$/, // 匹配png,jpg,gif這三類圖片
  loader: 'url-loader?limit=8192' // 限制大小小于8192b的圖片會轉(zhuǎn)為base64(經(jīng)查閱,8192b作為分割較好)
 }

為了測試效果,我準(zhǔn)備了100kb和5kb左右兩張圖片

<div class="icon">
      <img src="./assets/star.png" alt="" srcset="" width="200" height="200"> <!-- 100kb -->
      <img src="./assets/cz.png" alt="" width="100" height="100"><!-- 5kb -->
</div>

,啟動dev后顯示效果:

url-loader.png

通過控制臺可以看到其代碼:


console.png

build測試:


build5.png

可以看到,只打包出100kb那張圖片,而5kb的圖片則被打包到j(luò)s代碼中

code1.png

將圖片設(shè)置為背景屬性和上面效果基本一致,不過base64代碼會被打包到css代碼中。

  • 3、更方便的CSS預(yù)處理器

主流的CSS預(yù)處理器有sass(scss) less stylus,三者功能類似,具體使用哪個就要看個人喜好和項目需要吧。

這里我以sass(scss) 為例。

// 依賴安裝
npm i node-sass sass-loader --save-dev 

// loader配置
{
  test: /\.(sass|scss)$/, // 匹配sass或scss
  use: [MiniCSSExtractPlugin.loader, 'css-loader','sass-loader'] // loader的處理順序是從右到左
}

現(xiàn)在,我們把之前的css代碼改造一下,用上sass的語法

<style lang="scss" scoped>
$height: 200px;
$fontColor: rgb(66, 252, 29);
@mixin bg($url, $w, $h) {
  background: url($url) no-repeat  0px 0px;
  background-size: $w $h;
}

.body {
  color: $fontColor;
  .icon-big {
    height: $height;
    @include bg('./assets/star.png', 200px, 200px);
  }

  .icon-sm {
    height: $height;
    @include bg('./assets/cz.png', 50px, 50px);
  }
}

</style>

效果:


sass1.png

編譯結(jié)果,是正常的css代碼:

sass2.png

從css代碼到預(yù)處理器代碼,可以說是樣式編碼的一個質(zhì)的飛躍了。


截止到這里,上面比較明顯的待處理的問題都已經(jīng)完整解決。我這部分文章的中心點就是這樣,從0開始的webpack配置,一定要有自己的一些想法,然后一點一點完善,當(dāng)解決完一個問題,也許會出現(xiàn)另一個問題,而這個配置也是在慢慢完善,變得更加強大。

為Vue項目做準(zhǔn)備

既然是以作為Vue項目的webpack配置文件。那一些基礎(chǔ)的Vue依賴也要用一下:

// 安裝依賴
npm i vue-router vuex --save-dev

由于這個文章側(cè)重點是webpack,所以下面我只貼出代碼等。

目錄結(jié)構(gòu):

org2.png

router/index.js

import Vue from 'vue/dist/vue.esm'
import Router from 'vue-router'
import Home from '../pages/Home.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HOME',
      component: Home,
      meta: {
        title: '首頁'
      }
    }
  ]
})

store/index.js

import Vue from 'vue/dist/vue.esm'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  actions: {},
  mutations: {},
  getters: {}
})

index.js代碼配置

import Vue from 'vue/dist/vue.esm'
import App from './App.vue'
import router from './router'
import store from './store'

const vm = new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

現(xiàn)在把之前的App.vue的代碼移到Home.vue中。App.vue修改為:

<template>
  <router-view />
</template>

以上為最基本的vue項目配置

至此,一個可供使用的由webpack構(gòu)建的vue項目已經(jīng)完成。還有許多不足需要優(yōu)化。

github地址

后面會慢慢出直到配置出一個完整可用的webpack配置。

上一篇地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容