看完你就會用 webpack 了

終極目標

可使用 webpack 打包 vue 項目。javascript

整體計劃

  1. webpack 安裝和簡單使用
  2. 經過配置文件增長打包的功能
  3. 學習各類loader可讓webpack去打包各類文件
  4. 學習 plugins強大webpack 的功能
  5. 學會配置 webpack-dev-server 能夠在開發過程當中實時更新預覽代碼
  6. 配置webpack 實現 .vue 文件的打包

webpack-安裝基本使用

學習目標

  • 明白 webpack 的做用。
  • 掌握 webpack 的基本使用。
  • 解決項目中代碼打包的問題。(經過 webpack 對代碼進行打包)

學習計劃

  1. webpack的用處。
  2. webpack 的安裝環境
  3. webpack 的安裝
  4. 代碼文件結構
  5. 如何改造普通代碼文件爲模塊化,便於 webpack 打包
  6. 使用 簡單命令預覽 webpack 打包效果
  7. 查看打包後的 js 並簡單介紹下 webpack 打包依據。
  8. 經過 es6 模塊化文件使用 webpack 打包
  9. 總結

開始學習

webpack 的世界 一切皆模塊css

1. webpack 的做用(打包)

webpack 把模塊收集梳理打包html

  • 對咱們開發的項目進行打包(編譯,把咱們的代碼轉換成瀏覽器能夠編譯的代碼,例如 es6 轉 es5,scss 轉 css ,css 增長前綴,把.vue 拆分紅.js和.css)
    • 開發過程當中時時編譯
      • 經過 webpack server 生成一個臨時的本地服務,對咱們開發的項目的代碼進行時時編譯。
    • 項目開發完畢對資源進行打包
      • 壓縮
      • 不壓縮

2. 安裝 webpack

webpack中文網前端

1. 安裝環境

  1. 安裝 node,目前安裝 node 會自動安裝 npm。vue

    node 中文網java

  2. 建立一個文件夾。例如 demo1node

  3. 使用 npm 命令初始化 node 環境。webpack

    npm init -y
    複製代碼

    這樣會產生一個 package.json 文件es6

    {
      "name": "demo1",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    
    複製代碼

2. 安裝webpack

1.在命令行工具中輸入(推薦局部安裝)web

npm i webpack webpack-cli -D
複製代碼

當看到命令行中出現以下代碼,表明安裝成功了。

+ webpack-cli@3.3.12
+ webpack@4.43.0
added 391 packages from 218 contributors in 56.033s
複製代碼
"devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12"
  }
複製代碼

i 是 install 的簡寫

-D 是--save-dev的簡寫,其包名稱及版本號會存在 package.json 的 devDependencies 這個裏面,而--save則會將包名稱及版本號放在 dependencies 裏面。

延伸:dependencies是運行時依賴,devDependencies是開發時的依賴 (這裏你們知道就能夠了,之後的課程會終點介紹)

webpack 4x以上,webpack將命令相關的內容都放到了webpack-cli,因此還須要安裝webpack-cli。

注意:

  1. webpack 和 webpack-cli 推薦同時安裝,這樣能夠保證webpack-cli 對應 當前安裝的 webpack。

  2. 項目名稱不要叫 webpack 會致使安裝失敗。

  3. 如何查看版本號?因爲webpack 不是全局安裝 查看版本不能使用

    webpack -v
    複製代碼

    而是使用

    node_modules\.bin\webpack -v
    // 4.43.0
    複製代碼

    或者

    npx webpack -v
    // 4.43.0
    複製代碼

者來檢測版本,注意這裏npm版本號要求 5.2 以後。

npx webpack 等價於 node_modules\.bin\webpack

3. 建立基本文件代碼

環境準備完成以後咱們開始建立幾個基本文件,其目錄結構以下:

deomo1/root
|-index.html
|-index.js
|-package.json
|-tool.js
複製代碼

index.html 代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
</body>
<script src="tool.js"></script>
<script src="./index.js"></script>
</html>
複製代碼

tool.js 代碼

const updateDom = (id, content) =>{
    window.document.getElementById(id).innerHTML =  content
}
複製代碼

index.js 代碼

updateDom('app','傳智播客')
複製代碼
痛點
  1. index.js 依賴 tool.js 因此 index.html 中文件不能夠換位置

  2. 多人開發項目時候沒法保證變量是否惟一性(變量衝突)。例如兩個文件中分別存在 tool.js var a = 100;index.js var a =1000;

  3. 低版本瀏覽器不識別 ES6 語法。

  4. 代碼沒有通過混淆存在安全隱患,例如別人能夠經過你的代碼推斷出服務器接口請求的一些參數。

  5. 隨着 js 文件個數增長,增長了項目管理的難度,例如各個js 文件依賴,變量等等

解決方案

​ 經過使用 webpback 把多個 js 文件打包成一個。

4. 修改基本文件代碼爲模塊化寫法

本代碼實例爲 CommonJS 模塊化寫法,具體改造以下

tool.js

const updateDom = (id, content) =>{
    window.document.getElementById(id).innerHTML =  content
}
// nodejs中的模塊
module.exports = {
    updateDom
}
複製代碼

index.js

const {updateDom} = require('./tool');
updateDom('app','傳智播客')
複製代碼

改完以後的代碼咱們再次直接經過瀏覽器打開發現瀏覽器報錯,由於瀏覽器不能識別。接下來經過 webpack 對咱們的diamond進行打包操做。

注意

在 webpack 4 中,能夠無須任何配置就可使用。

  1. 簡單的打包操做

    npx webpack index.js //入口文件
    複製代碼

    npx 解釋見上文

    結果

    Hash: c4b4044439973defe187 Version: webpack 4.43.0 Time: 425ms Built at: 2020-07-16 4:51:35 PM Asset Size Chunks Chunk Names main.js 1.05 KiB 0 [emitted] main Entrypoint main = main.js [0] ./index.js 71 bytes {0} [built] [1] ./tool.js 160 bytes {0} [built] 複製代碼

    同時根目錄生成了一個叫作 dist 的文件夾裏面存在一個 main.js 的文件。

    同時有一段黃色的警告,由於咱們沒有告訴 webpack 咱們的須要打包的模式是開發模式(我理解爲開發代碼階段)仍是生產模式(我通常理解爲打包上線)。

5 打包後的 js

main.js 就是 index.jstool.js 兩個文件打包後的結果。

基本原理 webpack 會分析入口文件中的引用關係把相關的文件合併到一塊兒,例如:

若是 index.js 中沒有引用 tool.js 那麼打包的 main.js 就沒有tool.js 的代碼。

(簡單給學生看下mian.js)

6. 引入打包後的js

修改 index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
</body>
    <script src="./dist/main.js"></script>
</html>

複製代碼

7. 使用 ES6 的模塊化導出

建立一個 tooles6.js 文件

const log = (content) => {
    console.log(Date.now(), content)
}

// es6 模塊化導出
export { log }

複製代碼

在 index.js 文件中引入

// node 模塊化導入
const {updateDom} = require('./tool');

 // es6 模塊化導入
import {log} from './tooles6';

updateDom('app','傳智播客')

log('測試webpack是否能識別es6的模塊化')

複製代碼

小結

  1. webpack 自動識別各類依賴處理打包文件
  2. webpack 經過入口文件
  3. webpack 能夠用來打包多個或一個 js 文件(多個合成一個)
    1. 優勢:沒必要去關心它們的依賴
  4. 基於 node.js 不建議全局安裝,直接經過 -D 安裝到項目便可。
  5. 每次打包都會生成新的文件,若是有一樣名字的會覆蓋
  6. 支持兩種模塊化
    1. commonjs
    2. es6

webpack-基本配置

學習目標

咱們如何配置webpack 來知足咱們的需求?

咱們如何簡化 webpack 的命令,能夠快速使用

咱們如何自定義打包入口和出口路徑?

經過下面的課程咱們能夠掌握webpack 的基本配置知足咱們項目打包的基本需求。

學習計劃

  1. 建立默認配置文件 webpack.config.js
  2. 指定配置文件進行打包操做
  3. 經過package.json 進行簡化 webpack 的命令
  4. 自定義打包文件和輸出文件位置及名稱
  5. 總結

開始學習

在 webpack 4 中,能夠無須任何配置使用,然而大多數項目會須要很複雜的設置,這就是爲何 webpack 仍然要支持 配置文件。這比在終端(terminal)中手動輸入大量命令要高效的多,因此讓咱們建立一個配置文件,取代咱們以前使用 cli 命令執行的方式。

來自官網的一段話

webpack 在工做時,它會默認去根目錄下找一個名爲 webpback.config.js 的文件(若是找不到,則它會用一些默認設置)。

webpback.config.js 就是webpack的配置文件,在這個配置文件中,咱們能夠經過一個 導出一個 json對象去配置webpback的參數,讓打包更加靈活。

1. 建立默認配置文件 webpack.config.js

位置

咱們先指定一下打包模式 mode

module.exports = {
    mode: "development" // production(生產)
}
複製代碼

接下來再次運行打包命令,查看產生的main.js文件的內容,對比與之間的變化。

  1. 黃色警告沒有了,由於咱們已經設置了 mode。
  2. 咱們能夠把 webpack 的配置文件想象成 webpack 是一個函數,它接受一個對象,經過對象來讓 webapck 函數來產生咱們想要的結果。

此文件的意義是導出一個配置項:用來配置 webpack 如何打包。

在操做層面,就是學習如何去使用這個文件。

mode模式:

  • development:開發模式(代碼不會壓縮 混淆)
  • production:生產模式(壓縮,混淆,加密....... 不可讀)

2. 指定配置文件(自定義配置文件名)

目的

爲了實現多種打包模式,例如開發模式,生產模式,咱們能夠寫在一個配置文件中可是它不利於維護。

我推薦把不一樣功能的配置文件單獨分開寫,一般工做中也是這樣的。

在默認狀況下,webpack會找一個名爲 webpack.config.js的文件做爲它的配置文件,可是,針對不一樣的場景,咱們能夠自行決採用哪一個配置文件,換句話說,配置文件不必定必須叫webpack.config.js

下面,自已建立一個webpack.dev.js的文件用它來作配置文件,並使用它進行打包

1. 在根目錄下建立自定義配置文件

在項目根目錄下建立webpack.dev.js,內容以下:

module.exports = {
  mode: 'development',
  output:{
    filename:'bundle.js'
  }
}
複製代碼

2. 使用這個文件進行打包的配置

基本格式
npx webpack --config webpack的配置文件 入口文件
複製代碼
運行命令
npx webpack --config webpack.dev.js index.js
複製代碼

3. 經過 package.json 中的 scripts 簡化運行命令

基本格式
"scripts": {
    "自定義命令名": "要具體執行的代碼",
  }
複製代碼
示例
"scripts": {   
    "build": "webpack --config webpack.dev.js index.js"
 }
複製代碼
運行命令
npm run build 
//至關因而 npx webpack --config webpack.dev.js  index.js
複製代碼

4. 設置打包入口文件和出口路徑

在webpack中:

  • 默認入口是:./src/index.js
  • 默認出口是:./dist/main.js。

1. 設置入口路徑

咱們在實際工做中入口文件每每不是 index.js 也許叫 app.js

調整目錄結構

|-package.json
|-index.html
|-src/
|-src/js
|-------app.js
|-------tool.js
|-------tooles6.js
複製代碼
  • 修改src/index.js的名字爲src/js/app.js

  • 在webpack.config.js的配置項中添加 entry ,以下

  • module.exports = {
      mode: 'development', // 打包方式
      entry:'./src/js/app.js' // 入口文件
    }
    複製代碼
  • 修改快速打包命令

    • "scripts": {
         "build": "webpack"
       }
      複製代碼
    • 由於咱們使用的是 webpack.config.js 全部這裏不須要使用--config webpack.config.js 去指定配置文件。

  • 從新打包測試

npm run build
複製代碼

2. 設置出口路徑

  • 在webpack.config.js的配置項中添加 output ,以下

    • // 引入nodejs中的核心模塊
      const path = require('path') 
      console.log(path.join(__dirname,'/build'))
      module.exports = {
          mode: "production",
          entry: './src/js/app.js', // 入口文件
          output: {
              "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
              "filename": "bundle.js" // 設置出口文件的名字。默認狀況下,它叫main.js
          }
      }
      複製代碼
    • 說明:

      • output中的filename用來指定打包後的文件名字。
      • output中的path用來指定打包後的路徑。注意:它必須是絕對路徑。因此,這裏引用path模塊中的resolve方法來生成絕對路徑。
      • 若是path中的路徑不存在,它會自動建立一個默認的路徑名稱 dist
  • 從新打包測試

npm run build
複製代碼

小結

  • webpack的配置文件默認名是webpack.config.js
  • 也能夠單獨指定 webpack 的配置文件來知足多種場景的須要。
  • 學習webpack就學習webpack.config.js的使用。
  • 把webpack的打包命令集成到script中能夠簡化打包命令,同時方便其餘合做人員的使用。
  • 自行定義入口和出口文件

靈魂三問

​ 有什麼用?

​ 打包

​ 爲何用它?

​ 工程化:前端任務重須要有工具來管理

​ 開發、上線

​ 怎麼用?

​ 學習 webpack.config.js 不用記住,多看文檔,僅僅須要記住最外面基本配置做用便可。

webpack-高級配置

1. loader

介紹

爲何用 loader?

webpack 在不使用loader的時候僅僅能夠處理 .js 格式的文件,而咱們項目中有着各類格式的文件,以及須要對 js文件進行進一步處理例如 es6 轉 es5。

1.目的

經過loader 對要打包的文件進行語法轉化。

2.做用

將一個個文件以字符串的形式讀入,對其進行語法分析及進行轉換。

3.原理

能夠把 loader 理解成一個翻譯員,把源文件通過轉換後輸出結果,而且一個文件還能夠鏈式的屢次翻譯。

loader 也是一個模塊,默認導出爲一個 node 形式的函數,這個函數在 loader 進行資源轉換時候調用,並經過 this上下文訪問。

module.exports = function(source) {
  // source 爲 compiler 傳遞給 Loader 的一個文件的原內容
  // 該函數須要返回處理後的內容,這裏簡單起見,直接把原內容返回了,至關於該`Loader`沒有作任何轉換
  return source;
};
複製代碼

轉換:一個Loader的職責是單一的,只須要完成一種轉換。 若是一個源文件須要經歷多步轉換才能正常使用,就經過多個Loader去轉換。 在調用多個Loader去轉換一個文件時,每一個Loader會鏈式的順序執行, 第一個Loader將會拿到需處理的原內容,上一個Loader處理後的結果會傳給下一個接着處理,最後的Loader將處理後的最終結果返回給Webpack。 因此,在你開發一個Loader時,請保持其職責的單一性,你只需關心輸入和輸出。

實例

1. 使用 css-loader ,style-loader 處理文件中的 .css 文件

準備

public.css

body,html{
    padding:0;
    font-size:14px;
}
複製代碼

style.css

@import "public.css";
div {
  border:4px solid #ccc;
  width: 50%;
  height: 200px;
  margin:30px auto;
  box-shadow: 3px 3px 3px #ccc;
  background-color: #fff;
  text-align: center; 
}
複製代碼

app.js 增長引入 css 文件

// node 模塊化導入
const {updateDom} = require('./tool');
 // es6 模塊化導入
import {log} from './tooles6';
// + 新增 css 文件引入
import './../css/style';

updateDom('app','傳智播客')

log('測試webpack是否能識別es6的模塊化')
複製代碼

使用 webpack 打包

npm run bulid
複製代碼

此時控制檯

咱們看到控制檯報錯,這裏咱們只須要注意 關鍵子 loader 以及文件格式.css ,由此能夠推斷出是缺乏 css-loader

css-loader 安裝

npm install css-loader -D
複製代碼

-D devDependencies是開發時的依賴

css-loader 在webpack中配置

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['css-loader']
            },
        ],
    }
}
複製代碼

在 expors 的對象內部增長 module 對象 經過配置 rules 數組進行 loader 的配置

執行順序 :從數組的最末端開始執行,也能夠簡單的理解爲從右往左。

執行命令及結果

此時打開瀏覽器觀看 樣式並無生效 css-loader 的做用就是幫助 webpack 讀取 .css 文件,並打包進 bundle.js中,此時還須要 style-loader

安裝

npm i style-loader -D
複製代碼

使用

module.exports = {
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
        ],
    }
}
複製代碼

完整代碼:

const path = require('path') 
console.log(path.join(__dirname,'/build'))
module.exports = {
    mode: "production",
    entry: './src/js/app.js', // 入口文件
    output: {
        "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
        "filename": "bundle.js" // 設置出口文件的名字。默認狀況下,它叫main.js
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
        ],
    }
}
複製代碼

咱們看下輸出的 .js 包

bundle.js中有一些js代碼,它在運行時,會自動在.html文件中追加style標籤,並輸出樣式。

擴展

eval("var api = __webpack_require__(/*! ../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js")
複製代碼

再去node_modules\style-loader\dist\runtime\injectStylesIntoStyleTag.js 找下insertStyleElement這個方法,你就能夠發現這個過程。

function insertStyleElement(options) {
  var style = document.createElement('style');
  var attributes = options.attributes || {};

  if (typeof attributes.nonce === 'undefined') {
    var nonce = typeof __webpack_nonce__ !== 'undefined' ? __webpack_nonce__ : null;

    if (nonce) {
      attributes.nonce = nonce;
    }
  }

  Object.keys(attributes).forEach(function (key) {
    style.setAttribute(key, attributes[key]);
  });

  if (typeof options.insert === 'function') {
    options.insert(style);
  } else {
    var target = getTarget(options.insert || 'head');

    if (!target) {
      throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
    }

    target.appendChild(style);
  }

  return style;
}
複製代碼

此時瀏覽器就能夠渲染樣式了。

這裏你們要注意 loader 的配置順序。


小節 css-loader 幫助webpack 把.css 打包進去 style-loader 把打包的 .css 進行轉換經過函數以 style標籤的形式插入到 html 中。

擴展小知識** @import 用來引入另外一個 css 文件。

語法

@import url;
@import url list-of-media-queries;
@import [ <string> | <url> ] [ <media-query-list> ]?;
複製代碼

解釋

  • url:是一個表示要引入資源位置的 ](https://developer.mozilla.org/zh-CN/docs/Web/CSS/string) 或者 [ 。 這個 URL 能夠是絕對路徑或者相對路徑。 要注意的是這個 URL 不須要指明一個文件; 能夠只指明包名。
  • list-of-media-queries 是一個逗號分隔的 媒體查詢 條件列表,決定經過URL引入的 CSS 規則 在什麼條件下應用。若是瀏覽器不支持列表中的任何一條媒體查詢條件,就不會引入URL指明的CSS文件。

實例

  • css文件中用法
/* 方法一*/
@import 'test.css';
/* 方法二*/
@import url(test.css);
/* @import url list-of-media-queries;*/
@import "common.css" screen, projection;
@import url('landscape.css') screen and (orientation:landscape);
複製代碼
  • js 文件中用法
import 'test.css';
複製代碼
2. 使用 less-loader 處理 .less 文件

安裝

npm i less-loader  -D
// 不用在安裝 less
npm i less-loader less  -D
複製代碼

less-loader: 加載 less 文件而且把 .less 語法的代碼轉換成 .css

配置

module.exports = {
    module: {
        rules: [
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            }
        ],
    }
}
複製代碼

完整代碼

const path = require('path') 
console.log(path.join(__dirname,'/build'))
module.exports = {
    mode: "development", // development production
    entry: './src/js/app.js', // 入口文件
    output: {
        "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
        "filename": "bundle.js" // 設置出口文件的名字。默認狀況下,它叫main.js
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            }
        ],
    }
}
複製代碼

這裏你們要注意下 less 文件的 loader順序

use:['style-loader','css-loader','less-loader']
複製代碼

原理:先執行 less-loader 加載 .less 並轉換成 css 把轉換的結果給 css-loader ,css-loader 把結果在處理給 style-loader , 若是隻配置 less-loader webpback 沒法識別 css 格式。由於每一個 test 都是一個處理模塊 webpack 不會把 test:/.css/ 的規則用來處理 /.less/

代碼改造

index.less

@import "style.css";

body{ 
  div {
    border:4px solid #ccc;
    width: 50%;
    height: 200px;
    margin:30px auto;
    box-shadow: 3px 3px 3px #ccc;
    background-color: #fff;
    text-align: center; 
  }
}
複製代碼

app.js

// node 模塊化導入
const {updateDom} = require('./tool');
// 引入 less 文件
import '../css/index.less'
// 引入 css 文件
// import './../css/style.css';
 // es6 模塊化導入
import {log} from './tooles6';

updateDom('app','傳智播客')

log('測試webpack是否能識別es6的模塊化')
複製代碼

執行打包命令而且在瀏覽器中查看

3. 使用 url-loader file-loader 處理圖片資源

前端開發不可避免的使用各類圖片資源

代碼改造

index.less 文件

@import "style.css";

body{ 
  div {
    border:4px solid #ccc;
    width: 50%;
    height: 200px;
    margin:30px auto;
    box-shadow: 3px 3px 3px #ccc;
    background-color: #fff;
    text-align: center; 
    background-image: url(./../img/webpack-png.png);
  }
}
複製代碼

安裝 url-loader

npm i url-loader - D
複製代碼

配置

module.exports = {
    module: {
        rules: [
             {
                test:/\.png/,
                use:['url-loader']
            }
        ],
    }
}
複製代碼

執行

npm run build
複製代碼

結果

咱們發現只有一個js文件,那是由於 url-loader 把圖片文件轉換成了 base 64。

優勢:減小網絡請求。

缺點: 增長了 js包大小。

base64 通常比圖片會大一點點。

如何選擇?

小文件能夠轉換成 base 64,大文件不推薦。

url-loader 高級配置

咱們使用loader 的時候,以前是 use:['xxx-loader'],若是想詳細的設置loader能夠以下

通用規則

use:[
    {
        loader:'xxx-loader',
        options:{

        }}
]
複製代碼

若是你不是很瞭解能夠經過 npm 去找對應的loader,例如

配置完成後的代碼

const path = require('path') 
console.log(path.join(__dirname,'/build'))
module.exports = {
    mode: "development", // development production
    entry: './src/js/app.js', // 入口文件
    output: {
        "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
        "filename": "bundle.js" // 設置出口文件的名字。默認狀況下,它叫main.js
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
            {
                test:/\.less$/,
                use:['style-loader','css-loader','less-loader']
            },
            {
                test:/\.png/,
                use:[{
                    loader:'url-loader',
                    options:{
                        limit:3*1024 // 3* 1024b = 3kb
                    }
                }]
            }
        ],
    }
}
複製代碼

執行 build結果以下:

這是由於咱們經過配置 url-loder 使得它只處理 3k 一下的圖片,並轉換成 base64,若是須要處理大於 3kb的須要使用 file-loader 。

安裝 file-loader

npm i file-loader -D
複製代碼

執行代碼結果

這個時候咱們發現並無 配置 file-loader 就能夠直接起做用了。

注意

瀏覽器查看

此時頁面上面並不會顯示圖片,由於 file-loader 僅僅把圖片複製過去。這時候咱們查看路徑,瀏覽器中是找不到路徑的。這時候右鍵查看圖片路徑,咱們能夠很清楚的看到咱們的圖片路徑位置是不對的

緣由

上述代碼設置了 limit 選項,意思是當圖片體積小於 8192 字節時,會轉換成 base 編碼字符串,當圖片體積大於 8192 字節時,默認會使用 file-loader。

解決方案 (若是你們看着筆記去學習,這裏建議瞭解下直接跳過,由於後面經過 webpack 新增的 plugin 配置就會解決這個問題,不要浪費時間在這裏)

修改 css 引用路徑爲file-loader處理圖片後的路徑。

  1. 工具 mini-css-extract-plugin 參考下面的內容配置

可是 mini-css-extract-plugin 一般是項目打包的時候纔會用到。

擴展配置

咱們的 url-loader 功能強大,它能夠處理多種格式的文件,那麼怎麼優化配置 呢?具體以下

{
    test:/(\.png|\.jpg|\.svg)/,
    use:[{
        loader:'url-loader',
        options:{
        limit:3*1024 // 3* 1024b = 3kb
        }
    }]
}
複製代碼

其實就是使用正則表達式把咱們想用 url-loader 處理的文件寫在 test裏面這樣就能夠匹配啦。

優化配置 經過配置 name 能夠修改 打包以後圖片的名稱和輸出位置

{
    test:/\.png/,
        use:[{
            loader:'url-loader',
            options:{
                limit:3*1024, // 3* 1024b = 3kb
                name:'img/[name].[ext]'
            }
        }]
}
複製代碼

因爲咱們的 output 路徑寫的式 build 因此這裏的name 能夠成上面的樣子,name 是原來文件名稱 ext是文件類型

測試svg文件

代碼改造

index.less

@import "style.css";
body{ 
  background: url(./../img/webpack-svg.svg);
  div {
    border:4px solid #ccc;
    width: 50%;
    height: 200px;
    margin:30px auto;
    box-shadow: 3px 3px 3px #ccc;
    background-color: #fff;
    text-align: center; 
    background-image: url(./../img/webpack-png.png);
  }  
}
複製代碼

執行打包

由於咱們的svg圖片小於 3k 因此 url-loader 把svg資源轉成了 base64 大到了js裏面

loader 小結

如何使用

  1. 根據文件類型下載對應的loader。
  2. 配置loader。

2. plugin 插件

介紹

1. 目的

插件在於解決 loader 沒法實現的其餘事

2. 做用

plugin是用於擴展webpack的功能,

3. 經常使用 plugin 總結

html-webpack-plugin

功能:把咱們自已寫的.html文件複製到指定打包出口目錄下,並引入相關的資源代碼。

mini-css-extract-plugin

功能:這個插件幫助咱們把css代碼提取到一個獨立的文件中(而不是以style的方式嵌在html文件中)。

clean-webpack-plugin

在生成打包文件以前,把目錄清空掉。

實例

1. mini-css-extract-plugin

安裝過程

  1. 下載插件
npm i mini-css-extract-plugin -D
複製代碼
  1. 在配置文件中引入

webpack.config.js

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
複製代碼
  1. 修改 webpack.config.js 的 module.exports 中的 rules

    module.exports = {
        module:{
            rules:[
                 {
                     // 替換 style-loadr 爲 {loader: MiniCssExtractPlugin.loader}這個配置是咱們項目打包上線經常使用的寫法。
                    test:/\.less$/,
                    use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
                },
            ]
        }
    }
    複製代碼
  2. 在 webpack.config.js 的 module.exports 增長 plugins。全部的插件都須要在這裏面new 一下

    plugins:[
            new MiniCssExtractPlugin({
                // [name], [hash] 是佔位符
                // name: 表示入口文件的名稱
                // hash: 一串隨機值,是用於區別於本次打包與其它打包的過程。因爲源文件有變化,則每次打包時hash都不一樣
                filename: '[name]-[hash].css',
            })
        ]
    複製代碼

    完整代碼

    const path = require('path') 
    +const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    console.log(path.join(__dirname,'/build'))
    module.exports = {
        mode: "development", // development production
        entry: './src/js/app.js', // 入口文件
        output: {
            "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
            "filename": "bundle.js", // 設置出口文件的名字。默認狀況下,它叫main.js 
        },
        module: {
            rules: [
                {
                    test: /\.css$/,
                    use: ['style-loader','css-loader']
                },
                {
                    test:/\.less$/,
       +             use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
                },
                {
                    test:/(\.png|\.jpg|\.svg)/,
                    use:[{
                        loader:'url-loader',
                        options:{
                            limit:3*1024, // 3* 1024b = 3kb 
                        }
                    }]
                }
            ],
        },
    +    plugins:[
            new MiniCssExtractPlugin({
                // [name], [hash] 是佔位符
                // name: 表示入口文件的名稱
                // hash: 一串隨機值,是用於區別於本次打包與其它打包的過程。因爲源文件有變化,則每次打包時hash都不一樣
                filename: '[name]-[hash].css',
            })
        ]
    }
    複製代碼

執行打包命令

注意

這時後咱們的 index.html 路徑是不對的

咱們的index.html 沒有引用,這時候打開瀏覽器是看不到樣式的,這時候我看額能夠手動修改下 css 文件的引用地址。

2. html-webpack-plugin
  1. 安裝
npm i html-webpack-plugin -D
複製代碼
  1. 在配置文件中引入。

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin');
複製代碼
  1. 在 webpack.config.js 的 plugins 中 new HtmlWebpackPlugin並配置
plugins: [
    new HtmlWebpackPlugin({ // 打包輸出HTML
        minify: { // 壓縮HTML文件
            removeComments: true, // 移除HTML中的註釋
            collapseWhitespace: true, // 刪除空白符與換行符
            minifyCSS: true// 壓縮內聯css
        },
        filename: 'index.html',
        template: path.resolve('./index.html') // 指定模塊的位置
    })
]
複製代碼

刪除 html 中的引用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <link rel="stylesheet" href="./src/css/style.css"> -->
</head>
<body>
    <div id="app"></div>
</body>
<!--
    不經過webpack打包
     <script src="tool.js"></script> 
    <script src="./index.js"></script>
-->
<!-- 使用webpack 打包生成的文件路徑 -->
<!-- <script src="./build/bundle.js"></script> -->
</html>
複製代碼

執行代碼結果

build 裏面多了一個 html。

刪除HtmlWebpackPlugin 壓縮的配置項

plugins: [
    new HtmlWebpackPlugin({ // 打包輸出HTML 
        filename: 'index.html',
        template: path.resolve('./index.html') // 指定模塊的位置
    })
]
複製代碼

打包後的結果

咱們發現 url-loader 以前處理路徑有問題的背景圖片也顯示出來了。

這些配置項咱們一樣能夠在 npm 包的網站中找到,不須要去記住。接下來咱們在添加一個插件去鞏固下咱們的知識。

3. clean-webpack-plugin

下載插件

npm i clean-webpack-plugin -D
複製代碼

配置文件webpack.config.js

const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
    plugins: [
    new CleanWebpackPlugin()
]	
}

複製代碼

執行效果

所有代碼

const path = require('path') 
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
console.log(path.join(__dirname,'/build'))
module.exports = {
    mode: "development", // development production
    entry: './src/js/app.js', // 入口文件
    output: {
        "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
        "filename": "bundle.js", // 設置出口文件的名字。默認狀況下,它叫main.js 
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
            {
                test:/\.less$/,
                use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
            },
            {
                test:/(\.png|\.jpg|\.svg)/,
                use:[{
                    loader:'url-loader',
                    options:{
                        limit:3*1024, // 3* 1024b = 3kb 
                    }
                }]
            }
        ],
    },
    plugins:[
        new MiniCssExtractPlugin({
            // [name], [hash] 是佔位符
            // name: 表示入口文件的名稱
            // hash: 一串隨機值,是用於區別於本次打包與其它打包的過程。因爲源文件有變化,則每次打包時hash都不一樣
            filename: '[name]-[hash].css',
        }),
        new HtmlWebpackPlugin({ // 打包輸出HTML
            minify: { // 壓縮HTML文件
                removeComments: true, // 移除HTML中的註釋
                collapseWhitespace: true, // 刪除空白符與換行符
                minifyCSS: true// 壓縮內聯css
            },
            filename: 'index.html',
            template: path.resolve('./index.html') // 指定模塊的位置
        }),
        new CleanWebpackPlugin()
    ]
}
複製代碼

plugin 使用小結

plugin 用來加強 webpack 的能力

有了上面三個插件的使用經驗咱們總結下安裝插件的步驟和注意點

  1. npm 包下載插件。
  2. 在配置文件中引入插件。
  3. 在 plugin的數組中 new 這個插件。

注意:

  1. 有些插件是直接導出的函數,而有些插件是導出的對象,例如const { CleanWebpackPlugin } = require('clean-webpack-plugin'),當咱們引用npm 包報錯時候能夠去 npm 包官網查看下使用 demo。
  2. 全部的插件都必定會在 plugins 數組裏面經過 new 實例化。
  3. 插件在 plugins 中的順序不是它調用的順序,它的調用順序和 webpack 執行過程有關係。

3. webpack-dev-server

目的: 在開發過程當中實時更新咱們的代碼。

如何配置?

  1. 使用 npm 下載包

    npm i webpack-dev-server  -D
    複製代碼
  2. 在配置文件最外層配置

    module.exports = {
        // 配置 webpack-dev-server的選項
        devServer: {
            host: '127.0.0.1',  // 配置啓動ip地址
            port: 8081,  // 配置端口
            open: true  // 配置是否自動打開瀏覽器
        }
        // 其它配置
    }
    複製代碼
  3. 修改 package.json 的快速啓動配置

    "scripts": {
        "build": "webpack",
    +    "dev":"webpack-dev-server"
      },
    複製代碼

    執行新配置的命令

    npm run dev
    複製代碼

    這時咱們的瀏覽器就打開了,而且端口號是 8081,若是咱們不想讓咱們的項目端口號和其餘的項目衝突,能夠去掉 port webpback 就會根據當前 系統端口占用狀況自動生成一個端口號。

小結

webpack-dev-server 解決了咱們開發過程當中代碼實時預覽的問題,給咱們的開發代來了方便,它的功能不只僅如此,還可經過它配置跨越等功能。

3. webpoack 處理 .vue 文件

介紹

1 . 目的

經過webpack 能夠處理打包 .vue 文件

配置

代碼準備

vue 文件 /vuecomponents/App.vue

<template>
  <div>
    vue組件 {{title}}
  </div>
</template>

<script> export default { name: '', data() { return { title:'webpack-vue-這裏的vue單文件組件' } } } </script>

複製代碼

/js/main.js

import Vue from "vue"
import App from '../vuecomponents/app.vue'
new Vue({
  render(h) {
    return h(App)
  },
}).$mount("#app")
複製代碼

咱們這裏引用了 vue 全部要在 npm 中下載 vue

npm i vue -D
複製代碼

分析

  1. 咱們新增 main.js 因此要修改配置文件 entry
  2. 咱們要讓webpack 識別 .vue 因此要安裝 vue-loader
  3. 須要解析 .vue 的模板因此要有 vue-template-compiler
  4. 須要處理 .vue 內部的 style 全部要有 vue-style-loader

安裝依賴

npm i vue-loader  vue-template-compiler vue-style-loader -D
複製代碼

修改配置 webpack.config.js

  1. 修改 entry

    entry: './src/js/main.js',
    複製代碼
  2. 給.vue文件添加loader

  3. 添加VueLoaderPlugin

Vue-loader在15.*以後的版本都是 vue-loader的使用都是須要伴生 VueLoaderPlugin的。

vue-style-loader 和 以前的 file-loader相似不須要單獨配置。

{
    // 若是是.vue文件,使用以下的loader
    test: /\.vue$/,
        loader: 'vue-loader'
}

複製代碼
const VueLoaderPlugin = require('vue-loader/lib/plugin')

複製代碼

上面這段代碼是官網提供的配置實例

plugins:[
    new VueLoaderPlugin()
]

複製代碼

完整代碼

const path = require('path') 
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
    mode: "development", // development production
    entry: './src/js/main.js', // 入口文件
    
    output: {
        "path": path.join(__dirname,'/build'), // 決定出口文件在哪裏
        "filename": "bundle.js", // 設置出口文件的名字。默認狀況下,它叫main.js 
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader','css-loader']
            },
            {
                test:/\.less$/,
                use:[{loader: MiniCssExtractPlugin.loader},'css-loader','less-loader']
            },
            {
                test:/(\.png|\.jpg|\.svg)/,
                use:[{
                    loader:'url-loader',
                    options:{
                        limit:3*1024, // 3* 1024b = 3kb 
                        name:'img/[name].[ext]'                   
                    }
                }]
            },
            {
                // 若是是.vue文件,使用以下的loader
                test: /\.vue$/,
                    loader: 'vue-loader'
            }
        ],
    },
    plugins:[
        new MiniCssExtractPlugin({
            // [name], [hash] 是佔位符
            // name: 表示入口文件的名稱
            // hash: 一串隨機值,是用於區別於本次打包與其它打包的過程。因爲源文件有變化,則每次打包時hash都不一樣
            filename: '[name]-[hash].css',
        }),
        new HtmlWebpackPlugin({ // 打包輸出HTML
            
            filename: 'index.html',
            template: path.resolve('./index.html') // 指定模塊的位置
        }),
        new CleanWebpackPlugin(),
        new VueLoaderPlugin()
    ],
    devServer: {
        host: '127.0.0.1',  // 配置啓動ip地址
        port: 8081,  // 配置端口
        open: true  // 配置是否自動打開瀏覽器
    }
}

複製代碼

執行命令效果

小結

  1. 處理 .vue 咱們已經分析了 就是須要loader。
  2. 由此能夠得出 webpack 的模塊化其實並不複雜,咱們在使用它去爲咱們的項目打包的時候經過要處理的文件類型,目的去 npm 包網站上或者 webpack網站中找到對應的依賴包就能夠
  3. 咱們要掌握的是 webpack 的一般用法,和可以明白在打包過程當中爲何會有錯誤,以及能夠經過 webpack 提供的信息去配置。

總結

  1. webpack 是一個打包工具
  2. 在 webpack 的世界裏一切皆模塊。
  3. loader 幫助 webpack 去翻譯不一樣的文件讓 webpack 能夠把它們打包
  4. plugin 插件完善了 webpack 打包功能
  5. vue-cli 也是基於 webpack 開發實現的
相關文章
相關標籤/搜索