初識webpack4.0-基礎原理

前言

以前都是使用,沒有系統的完整的好好學習過一遍webpack的原理,趁如今工做有些閒空,整理下。增強下記憶

什麼是webpack?

不想放webpack官網那張圖,感受都快看吐了。
算了仍是妥協把,要否則很差說清楚.....
image
官網的哈,看能看出的來,那繼續了~~css

分爲三個部分

左側:html

寫項目的源代碼,源文件
左側有一個入口,最上面的 .js
一個一個的方格能夠理解成一個一個的模塊,由於webpack是基於node的,因此能夠用模塊的概念來區分文件。
箭頭的表示➡️一個模塊能夠依賴多個模塊
箭頭➡️表示他們之間的依賴關係
左側會有不少,後綴的文件是瀏覽器沒法識別的。例如: .sass .hbs .cjs
因此須要通過webpack 來構建一次打包

通過webpack的構建node

右側:webpack

輸出瀏覽器能夠正確執行的文件,資源

咱們還能夠利用webpack來壓縮 js 、壓縮圖片 。
因此webpack就是一個模塊打包器web

webpack安裝

分爲兩種安裝方式npm

  • 項目安裝(推薦)
    有些項目可能很老,依賴的webpack的版本比較低。
    最新的是webpack4.X; webpack5.x尚未發佈
  • 全局安裝
    若是是全局安裝,版本會固定化。若是是去修改來的版本會衝突,依賴衝突等。因此根據項目來安裝webpack,會好些。

安裝:
webpacl4.x以後,這兩個必需要都安裝,webpack和 webpack-cli;不建議分開裝。json

建立項目以後,現須要npm init一下,以後在安裝。初始化一下。這個你們應該都知道。瀏覽器

npm install webpack webpack-cli -D

webpack啓動

webpack4.0發佈的時候,有說,支持零配置啓動。結果發現,哈哈哈哈哈哈哈哈~~~沒啥用。基本用不到項目中。sass

咱們來看下零配置:
安裝好webpack以後,咱們來建立一個入口文件,index.js閉包

零配置 :

默認入口: ./src/index.js
若是沒有src 下面的index.js 打包是不成功的。
默認出口:輸出的目錄是 ./dist,輸出的資源名稱:main.js

image
接下來,啓動webpack,啓動方式有兩種。

第一種啓動方式:

npx webpack

爲啥用npx啓動項目

npm5.2版本,就自帶npx這個功能;
如今咱們啓動的整個項目webpack是局部安裝的
若是全局沒有安裝webpack,全局執行 webpack 就會報錯, command not found。它會去全局環境變量中去尋找。
經過npx 啓動webpack,它會在當前項目下的 node_modules/.bin 目錄去找它的軟鏈接,在 .bin 目錄下找到webpack,去啓動它。

image

來看下,打包好裏面都顯示了啥?

  • 構建的哈希版本
Hash: 096bb4bcb72f81514554
  • 執行構建的webpack版本
Version: webpack 4.44.1
  • 執行構建的時長
Time: 217ms
  • 構造的內容是什麼?

// 輸出的資源叫main.js
// 這個資源是958 bytes
// Chunks 是爲 0

Built at: 2020-08-25 14:45:08
  Asset       Size  Chunks             Chunk Names
main.js  958 bytes       0  [emitted]  main

// 這塊表示 輸出的main.js,是根據./src/index.js文件built而來的
Entrypoint main = main.js
[0] ./src/index.js 29 bytes {0} [built]
  • 警告內容

本身百度吧,好嗎? 用我小學的英語水平大概就是:環境沒有設置:就是生產環境和開發環境沒設置。會走一個默認的值,默認值是production(生產模式);

生產模式下的代碼是進行壓縮的,如今能夠看下,main.js
image
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

測試打包好的main.js;是否可使用
在dist裏面,手動建立一個index.html,而後手動引入main.js;
dist/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <script src="./main.js"></script>
</body>
</html>

第二種啓動方式:

在package.json,的scripts中,添加啓動命令

"scripts": {
    "dev": "webpack"
  },

以後執行

npm run dev

效果和上面是同樣的,就不進行在進行演示了。

當咱們在scripts中去定定義了執行命令dev,執行webpack;是從本地的 node_modules/.bin目錄的軟鏈接去找webpack

webpack配置文件,自定義配置文件

在根目錄下建立, webpack.config.js
webpack.config.js 就是webpack的自定義配置文件
當咱們執行 npx webpack
首先會去項目下去查找 是否有 webpack.config.js,這個配置文件;若是沒有會走默認配置;若是存在,就會按照 webpack.config.js配置裏面的內容去進行構建

webpack.config.js

webpack是基於node 的,因此能夠直接導出模塊
module.exports={
    entry(入口):(有三種類型)
    output(出口): {
        // 指定輸入資源存放目錄,位置
        // path 必須是絕對路徑
        path:,
        //輸出文件名
        filename:,
    }
    // 剛剛報的警告,就是這個值沒有設置。
    mode: 構建模式
}

webpack.config.js

const path =require('path')
module.exports={
  entry:'./src/index.js',
  output:{
    path:path.resolve(__dirname,'./build'),
    filename:'main.js'
  },
  // 開發模式
  mode:'development'
}
npx webpack

image

目錄新建立了一個build;main.js中的文件沒有被壓縮,開發模式下,文件不會被打包。

image

main.js 文件內容分析

main中是一個自執行的閉包函數
//行參 modules 全部的模塊
(funcition(){modules})()
image

等下,我在建立個依賴js。爲了方便看這個modules裏面的內容。
image

image

modules是什麼?

//modules 是一個對象,這個對象記錄了,從入口模塊出發,以及依賴模塊的信息

image

來看下,在src/index.js中的內容

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _a_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./a.js */ \"./src/a.js\");\n\nconsole.log('hello webpack'+_a_js__WEBPACK_IMPORTED_MODULE_0__[\"str\"]);\n\n//# sourceURL=webpack:///./src/index.js?");

/***/ })
引入a.js的方式改成了 __webpack_require_
經過webpack構建,對內容進行了一層處理,模塊化語句也進行了一次處理
__webpack_require_ 在自執行函數中定義了這個方法的執行。

(先簡單說明下,後面會寫具體的文檔)


繼續webpack配置文件;好比咱們在Vue cli工具建立的文件;因此咱們能夠本身去定義webpack配置文件的名稱,能夠不叫webpack.config.js;默認是走這個文件;
好比在根目錄下新建一個,webpack.ohh.js;那如何讓webpack走這個配置文件呢,
須要在package.js

// --config 用這個--config來進行匹配 
"scripts":{
    "dev": "webpack --config ./webpack.ohh.js"
}

image
執行npm run dev 進行打包

webpack核心概念

  • enrty:webpack執行構建的入口,默認是./src/index.js;
看官網那個圖,就能看出來,須要一個js文件入口。固然這個文件入口也是能夠修改的。
建立一個webpack.config.js,entry 就能夠進行修改。
  • output: 配置資源輸出的位置和名稱,
打包好的文件放在什麼位置,叫什麼名字
  • mode:打包構建模式,有開發模式和生產模式兩種。
development:開發模式,不壓縮代碼,有利於查找錯誤
productiont:生產模式,發佈到線上的代碼,代碼會被壓縮
  • chunk:代碼片斷,由入口模塊文件與依賴模塊的內容生成的。
  • module:模塊,webpack基於nodeJs,有一切皆模塊的概念
在剛剛咱們打包的 a.js or index.js ;或者後面會去添加的 index.css,圖片等,均可以成爲模塊

bundle: 打包輸出到資源目錄的文件,構建成功後的輸出文件

順一順~~~~
bundle chunk module,三者的關係:

SPA 項目 一個單頁面應用,只會有一個bundle 文件;
MPA 項目 多頁面應用,就會有多頁面的bundle文件;

好比index.js 和login.js

上面放了不少都是跑的SPA 單頁面的應用;來看一個多頁面MPA的。
首先是配置:

webpack.ohh.js

const path = require('path')
// 多入口
module.exports={
  entry:{
    index:'./src/index.js',
    login:'./src/login.js'
  },
  output:{
    path:path.resolve(__dirname, 'ohh'),
    filename:'[name].js'
  },
  mode:'development'
}

image

一個bundle 文件,對應一個chunk裏面會有多個片斷

MPA 多頁面應用,纔會存在多個chunks;
SPA 單頁面應用,只有一個入口,一個chunk,(可是可能會有多個片斷組成:

好比index.js中引入了a.js;那麼chunk就有兩個片斷:一個是index、一個是a文件;);

**一個chunk對應一個entry
一個entry對應多個module**

  • loader:模塊轉換;webpack默認只支持js模塊,json模塊。

css模塊,和圖片模塊都不支持。就須要用到loader,
好比:

src/index.css

body{
 background: pink;
}

src/index.js
引入 css

// a.js
// export const str='這是ajs';
import {str} from './a.js'
import css from './index.css';
console.log('hello webpack'+str);

須要去配置loader
在配置文件,固然你也能夠額寫在webpack.config.js中。
建立一個module,寫入加載規則
webpack.ohh.js

const path = require('path')
 // 多入口
module.exports={
 entry:{
   index:'./src/index.js',
   login:'./src/login.js'
 },
 output:{ path:path.resolve(__dirname, 'ohh'),
   filename:'[name].js'
 },
 mode:'development',
 module:{ // 模塊
   rules:[ // 規則
     {
       test: /\.css$/,
       use: "css-loader"
     },
   ]
 }
}

進行安裝 css-loader

npm install css-loader -D

以後來跑一下項目:

npm run dev

看一下打包結果
image
沒有報錯 也沒有顯示,由於:
css-loader 的做用很是的單一,只是讓咱們的webpack知道了,如何去處理css的語法,如何讓css語法以字符串的方式,放到bundle文件裏面去。
image

不然就會報錯,接下來要作的是,將這段代碼提取出來放到html中。

npm install style-loader -D

style-loader 的做用:
將css提取出來,而且在html的頭部,動態的生成style標籤,將css放到裏面去。
這時,還須要去修改下配置文件的module
webpack的配置文件修改;

module:{
  rules:[
      {
          test:/\.css$/,
          use:["style-loader", "css-loader"]
      }
  ]
 }
添加一個style-loader
loader的自行順序,user:[];執行順序是從後往前的,因此先要把css解析出來,之後再用style-loader,生成style標籤,將css內容放進去。【從右到左】
  • 安裝完了style-loader
  • 配置文件修改了css文件的匹配規則
  • 執行 npm run dev,查看頁面加載狀況
  • 在打包好的文件中,【本身 建立】建立一個index.html;這樣能夠看到效果
image
瀏覽器打開這個index.html
image
展現成功~~~~~!耶✌️
  • 結論:
    css-loader和style-loader須要配合來使用
  • 爲何css-loader功能單一,爲何要配合style-loader 才生效?

由於 自定義loader規定,一個loader只作一件事情。
style-loader的功能也很單一,把樣式放在一個動態生成的style標籤裏面。因此不會在本地打包的html文件中顯示出來,是經過js動態生成的。因此引入js就能夠。
若是像將css處理成單獨的文件,而不是在頁面建立一個style標籤的形式放在html裏面。那就不能用style-loader;
index.less的文件,咱們就有須要去加新的匹配規則,["style-loader","css-loader","less-loader"]

  • plugin:webpack 的一個功能擴展

舉例: 像咱們剛剛手動去建立的index.html
若是咱們想要看到效果就須要,在打包個人文件夾中去手動建立index.html;很是的繁瑣,那麼如何解決呢?這個時候利用plugin;至關於webpack 的一個功能擴展。【官網中-右上角導航就有plugin,找一個合適的進行使用】
接下來,以如何自動建立index.html 來進行開展plugin的使用討論

先安裝:

npm install html-webpack-plugin -D

image

  • 配置webpack默認項:

webpack.config.js

const path =require('path')
// 這裏導入html-webpack-plugin
const htmlWebpackPlugin = require('html-webpack-plugin')
// 單入口
module.exports={
    entry:'./src/index.js',
    output:{
        path:path.resolve(__dirname,'./build'),
        filename:'main.js'
    },
    // 開發模式
    mode:'development',
    module:{
        rules:[
            {
                test:/.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },
    plugins:[
        new htmlWebpackPlugin({ // plugin的使用,先new一下
            template:'./src/index.html', // 模板文件
            filename:'index.html' //倒出的文件名
        })
    ]
}

由於是在默認文件配置,因此跑起來,須要執行

npx webpack

效果以下:
image
這樣就打包成功了,那麼直接用瀏覽器打開index.html
就能夠看到效果了。並不在截圖,由於和上面那個圖片展現是同樣的。就換成了自動生成html而已,僅此而已。
繼續~~~~~(爲何要總結原理,我越寫餓了,難過)

爲了保證每次建立出來的build,打包文件都是全新的,並且不存在冗餘的文件,好比說,當咱們修改了一下 plugins中的
new htmlWebpackPlugin中的打包目錄地址的配置:
filename:'html/ohh.html'
那麼上次打包在根目錄下的html並不會刪除,就冗餘了唄。
咱們就須要用到plugin來進行配置
先安裝:

npm install clean-webpack-plugin -D

使用,都是同樣的

const {CleanWebpackPlugin} = require('clean-webpack-plugin')
// 在pulugins中new一
plugins:[
   new htmlWebpackPlugin({ // plugin的使用,先new一下
   template:'./src/index.html', // 模板文件
   filename:'index.html' //倒出的文件名
   }),
    new CleanWebpackPlugin()
]
  • 引入css文件而不是寫在style標籤裏面,把樣式抽離成獨立的文件

首先安裝plugin

npm install mini-css-extract-plugin -D

修改webpack的配置文件

  1. 引入plugin
plugins:[
   new miniCssExtractPlugin({
       filename:'css/index.css'
   })
]
  1. 修改css文件的模塊匹配規則和渲染方式
module:{
   rules:[
       {
           test:/.css$/,
           use:[miniCssExtractPlugin.loader,'css-loader']
       }
   ]
},

image

基本原理就差很少順明白了。總結下


總結

webpack.config.js: webpack配置文件

基本概念

  • entry:webpack執行構建任務的入口文件
  • output:執行構建後,資源配置的輸出位置和名稱
  • module: 模塊
  • chunk:入口文件和依賴模塊組合,通過webpack構建成生的一段代碼片斷
  • bundle: webpack構建完成夠後輸出的文件
  • loader: 模塊轉化,讓webpack能夠支持轉化更多的模塊類型
  • plugin:插件,讓webpack功能更強大
  • modle: 打包構建模式,開發模式or生產模式

核心配置

  • enrty:String|[]|{}
[] : 單頁面應用
{}: 能夠SPA or MPA。多入口對應多出口文件
  • output:{path:,filename:「」}
path:必須是絕對路徑
filename 可使用佔位符 [name] [hash]等
  • mode:String
參數:「production」 「development」 「node」
  • module :{}
{rules:[]}
  • plugins : []
    • *

webpack的學習,其實就是各類plugin和module的使用,用多了就寫的順了,因此主要的仍是基礎概念要清楚,因此才單獨拿出來進行一個梳理,鄙人看法哈。

相關文章
相關標籤/搜索