一、總覽webpack的作用:
webpack在中間的作用就是將左邊的一些列文件,進行打包、模塊化,形成右邊的文件和文件包;因為左邊的文件有的是瀏覽器不識別的,經過打包以后,形成右邊的文件后,可以在瀏覽器是直接運行的。
即:問:webpack是什么?
答:是前端模塊化打包(構建)工具。
webpack可以看作是 模塊打包機:它做的是,分析你項目結構,找到JavaScript模塊、其他的一些瀏覽器不能直接運行的拓展語言(Scss , less等)以及新語法(像ES6等)
,並將其轉換和打包為合適的格式供瀏覽器使用。
問:為什么要使用webpack?
答:1、瀏覽器不識別SAA、LESS ==>需要對less/sass預編譯成css => 供瀏覽器使用;(光這一步就需要手動使用一個工具)
2、項目中的模塊化以及互相之間引用依賴造成文件分散 ==> 需要把各個分散的模塊集中打包成大文件,減少HTTP的鏈接的請求次數(這一步也需要一個工具)
3、打包成了大文件,體積就變大了 ==> 所以代碼要進行壓縮(這一步還需要一個工具)
4、部分ES6語法有兼容問題 => ES5 ==>瀏覽器使用 (這里還需要一個工具)
5、。。。。。。
6、以上這些操作以前都是需要手動處理,需要很多個工具,這是非常繁瑣的,這個時候webpack就可以上場了。
7、以上這些操作,在webpack里,只需要配置好,一下就可以搞定了。
webpack的基本能力:處理依賴、模塊化、打包
1、處理依賴:方便引用第三方模塊,讓模塊更容易復用、避免全局注入導致的沖突、避免重復加載或者加載不必要的模塊
2、合並代碼:把各個分散的模塊集中打包成大文件,減少HTTP的鏈接的請求次數,優化代碼的體積(壓縮代碼)
3、各種插件:babel把ES6+轉化為ES5-等。
webpack的工作原理:
1、簡單說就是分析代碼,找到“require”、“import”、“define”等關鍵詞,並替換成對應的模塊的引用。
2、在一個配置文件中,指明對某些文件進行編譯、壓縮、組合等任務。把你的項目當成一個整體,通過一個給定的主文件(index.js),webpack將從這個文件開始找到你的項目的所有的依賴文件,使用loaders處理它們,最后打包為一個瀏覽器可以識別的文件。
用示意圖解釋就是這樣的的一個過程。
webpack四個核心概念:入口(entry)、出口(output)、加載器(loader)、插件(plugins)
1、入口:要打包哪個文件
2、出口:要打包到哪里
3、加載器:加載除了js文件其他文件的功能
4、插件:處理加載器完成不了的功能,使用插件
示意圖
手動配置webpack的目的:
1、為了更好的使用腳手架做准備
2、能夠完成webpack的基本安裝
3、能夠了解webpack配置文件的作用
4、能夠說出webpack中的loader的作用
5、能夠使用webpack處理常見資源(css\less\圖片)
6、能夠說出webpack-dev-server的作用以及 配置
二、webpack配置使用步驟
(一)命名初始化階段 --- 相當於初始化一個項目
注:項目名不能有漢字,不能取名為 webpack。
1、創建項目名稱(手動創建文件夾名),並 生成 package.json文件(生成這個文件靠后面的命令),執行的命令是: npm init -y
2、安裝webpack:npm i webpack webpack-cli -D
*解析該命令:前面的“webpack"指得是安裝,后后面的"webpack-cli"指的是安裝了webpack-cli后,就可以把webpack這個詞當作命令來用了
- webpack:是webpack工具的核心包
- webpack-cli:提供了一些在終端中使用的命令
- -D(--save-dev):表示項目開發期間的依賴,也就是:線上代碼中用不到這些包了
安裝包的幾個命令:(幾個命令相互可以代替的)
- npm i xxx / npm i xxx -S / npm i xxx --save => 都會被記錄在dependencies里面(發布階段)
- npm i xxx -D / npm i xxx --save-dev => 記錄在devDependencies里面(開發階段)
【執行安裝命令時,什么時候加-D,什么時候不加"-D",關鍵就要看上線后,是否還需要這個插件包,線上需要的話,就不加"-D",線上不需要就加"-D",因為加了,那么該包只會在存在 本地,當上線時,該包就會自動被過濾掉,不會被打包傳上去】
【webpack只是上線需要的,線上不需要打包了,所以只是在開發階段安裝使用】
3、創建main.js文件
在里面先隨便寫一句代碼,使其不為空:如:console.log('我要被打包了')
4、在package.json的script中,添加腳本
"scripts": { // webpack 是webpack-cli中提供的命令,用來實現打包的 // ./mian.js 入口文件,要打包哪個文件 "build":"webpack main.js" },
5、運行命令:npm run build ,進行打包
打包原理圖如下:
6、【很重要】設置開發狀態模式:mode
運行完 npm run build 后 會出現一個驚濤,如上圖的黃色字體,拷貝下來如下:
警告:
WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value.
翻譯:‘mode'選項,你沒有設置,webpack 默認給你一個值'production',
【注:如果沒有設置mode配置項,webpack會默認提供 生產環境production】
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
翻譯:可以設置兩個值:'development' 'production'
'production': 生產/發布(代碼壓縮)
'development':開發環境(代碼不壓縮) 如何設置mode?
命名行設置選項有個格式: --key value ==> --mode production/development
項目開發的兩種環境:
1、開發環境(development):開發過程就是開發環境
2、生產環境(production):線上環境,就是--項目做好了,發布上線
生產環境下,打包生產的js文件都是壓縮后的,開發環境下代碼一般是不壓縮的。
(二)隔行變色小案例
1、先創建一個src文件夾,
然后在里面新建要給index.html起始文件,
然后將main.js文件拖進來;
2、在index.html寫隔行變色案例:
<ul>
li{今天第 $ 號}*10
</ul>
3、安裝jQuery:npm i jquery ,並引入jQuery
4、暫時引入main.js,在main.js里寫入如下代碼
console.log("我要被打包了"); // 引入jQuery,在js文件里面不能用script引入文件了;可以用另外兩種 // 一種是,用原來的,如下: // const $ = require('jquery') // 另一種是ES6的方法: import $ from "jquery"; // 現在采用ES6的語法引入 $("li:odd").css("background", "pink"); $("li:even").css("background", "skyblue");
5、以上寫完后,在瀏覽器中打開index.html后報錯,效果沒有了。問題如下:
// 引入的main.js 會報錯,因為瀏覽器不支持這個import 的ES6語法 // npm run build 之后,引入打包壓縮后的main.js文件 // 即 引入dist/main.js后,就ok了。因為webpack幫我們將ES6轉化成瀏覽器能夠識別的ES5的語法了。
注意:運行npm run build之前先去package.json里面修改路徑,因為打包時,都是相對根路徑的,所以要修改main.js的路徑也要相對根路徑
6、將以上都操作完后,就可以在瀏覽器中正常顯示了。
7、整體代碼截圖如下:
(三) webpack配置文件
1、webpack的配置:兩種方式
命名行 + 配置文件
2、命名行
現在:"build": "webpack ./src/main.js --mode development",
格式:
--> " webpack ./src/main.js --mode development"
--> webpack 入口 --output 出口
==>webpack ./src/main.js --output ./dist/app.js 【后面的這個出口文件名那個app.js可以隨便取】
==>完善一下:webpack ./src/main.js --output ./dist/app.js --mode development
執行命令:npm run build
3、配置文件:
【因為隨着文件的增多,命名行方式會越來越復雜,隨意可以單獨提出來,用配置文件方式,將配置都集體放一塊】
> 如果 腳本寫成這樣:"build" : "webpack"
>webpack.config.js ==> 它是webpack的默認配置文件
>意思是:當執行npm run build 時,會自動找到webpack.config.js文件,執行里面的內容
>注意:原本是沒有webpack.config.js文件的,需要自己手動創建
4、配置文件里的示例代碼(webpack.config.js):
// 將這個配置寫到配置文件里:./src/main.js --output ./dist/app.js --mode development
// webpack 是基於node的,所以node的語法webpack的配置文件里面可以直接使用
// 所以在webpack.config.js里面導出一個模塊,就可以使用node的到處模塊語法:
// 引入path模塊
const path = require("path"); module.exports = { // 入口【寫絕對路徑】
entry: path.join(__dirname, "./src/main.js"), // 出口
output: { // 出口目錄
path: path.join(__dirname, "./dist"), // 出口文件
filename: "app.js", }, // 開發模式
mode: "development", };
(四)html-webpack-plugin插件
1、html-webpack-plugin是必備的插件
作用:
(1)能夠根據指定的模板文件index.html,自動生成一個新的index.html,並且注入到dist文件夾下
(2)能夠自動引入js文件
2、安裝:npm i html-webpack-plugin
3、引入 "const htmlWebpackPlugin = require('html-webpack-plugin')
// 引入html-webpack-plugin const htmlWebpackPlugin = require("html-webpack-plugin");
4、配置(在webpack.config.js里)
// 引入html-webpack-plugin
const htmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { // 入口【寫絕對路徑】
entry: path.join(__dirname, "./src/main.js"), // 出口
output: { // 出口目錄
path: path.join(__dirname, "./dist"), // 出口文件
filename: "app.js", }, // 模式
mode: "development", // 插件plugins
plugins: [ // 配置html-webpack-plugin插件;需要實例出一個模板文件
new htmlWebpackPlugin({ template: path.join(__dirname, "./src/index.html"), }), ], };
(五)webpack-dev-server插件
webpack-dev-server 是使用webpack必備的功能插件
1、作用:為使用webpack打包提供一個服務器環境(打一個虛擬包放到服務器里面去)
- 自動為我們的項目創建一個服務器
- 自動打開瀏覽器
- 自動監視文件變化,自動刷新瀏覽器(當改動一個或幾個地方代碼時,會自動刷新瀏覽器)
- [說白了,就是當我們改動一個小地方時,不用再麻煩的自己手動執行命令打包了]
2、使用步驟:
2.1、安裝: npm i webpack-dev-server -D
2.2、新加一個腳本:"dev" : "webpack-dev-server"
2.3、運行腳本:npm run dev
2.4、配置
2.4.1、自動打開瀏覽器:加 --open
2.4.2、指定端口號:加 --port 3001 【這個端口號可以自己分配】
2.4.3、熱更新(主要體現在css上):加 --hot
3、可以把webpack-dev-server的幾個配置項放到 配置文件里面去(以上方法時命令行方式配置,接下來時配置文件方式)
此步需要配置兩處:一處是package.json,一處是webpack.config.js;兩處分別截圖如下:
三、webpack打包上線
1、開發階段:
- 腳本 -> dev : npm run dev
- 工具:webpack-dev-server
2、發布階段:
- 腳本 -> build:npm run build
- 工具:webpack
注:
1、開發模式:nm run dev ==> 是不會打包的,只會把項目放到服務器里
2、假設項目開發完成了,要上線,怎么操作?
(1)執行 npm run build 對項目進行打包,生成dist文件夾
(2)模擬本地服務器 :安裝 :npm i http-server -g
(3)把dist文件里面的內容放到服務器里面即可,直接執行http-server,注意,此時進入dist文件夾目錄,用終端打開至此,然后執行http-server就運行起項目了。
四、打包非js文件
(一)處理css文件
1、創建一個css文件,然后在mian.js中引入 import '../css/demo.css'
ul{ list-style:none; }
2、需要兩個插件:style-loader 、css-loader
3、安裝:npm i -D style-loader css-loader
4、在webpack.config.js中添加新的配置項module
5、在module中添加loader來處理css
【非常重要的注意點:順序:style-loader 寫在前面,css-loader寫在后面;但是真正執行的時候是從后往前執行的】
(二) 處理less文件
1、創建一個less文件,然后再main.js中引入import '../css/index.less'
2、安裝: npm i less-loader less -D
【注:less-loader是依賴less的,所以也要裝less】
【注2:實際上處理less,是需要三個loader的,分別是style-loader css-loader less-loaser,即實際是需要這樣:npm i -D less-loader less style-loader css-loader ,這里因為先前已經安裝了前兩個,鎖着這里不必再安裝了】
3、在webpack.config.js中配置module -> rules
4、在module中,添加loader來出來less
ul { background-color: skyblue; li { &:hover { color: yellow; } } }
5、配置:
// 2. 處理less文件 { test: /\.less$/, use: ["style-loader", "css-loader", "less-loader"] },
(三)處理 圖片 文件
1、設置背景圖片
.img { width: 300px; height: 300px; background: url("./logo.png"); background-size: 100%; }
2、安裝對應加載器插件:npm i url-loader file-loader -D
【url-lodare(推薦) 和 file-loader 二選一即可;按時安裝時還是要全安裝的,原因在下面3里面】
3、找對應的配置文件,進行配置,即添加loader規則:
這里聲名的時候只需要聲名一個url-loader 就可以了,因為它里面已經包含的file-loader 里面的方法了。所以不用聲名;但是會依賴file-loader ,
所以依然需要安裝。
4、url-loader默認會將圖片轉化為base64編碼格式,【注:是轉化的圖片本身】;目的:提高性能
5、file-loader在加載圖片時,會對文件進行重命名,即加載路徑會被加密修改掉:
原始: background: url("./logo.png");
處理后:background:url(26bd867dd65e26dbc77d1e151ffd36e0.png);
6、base64編碼格式的圖片說明:
- 精靈圖:將一些小圖片合並為一張圖片,減少請求次數,提高性能
- 字體圖標:直接將一些小的圖片,合並到字體文件中,並且不會失真。
- base64:是一種編碼格式,能夠將圖片文字等常見的 文件,轉化為bas64格式這種字符串格式,瀏覽器能夠識別並讀取顯示到頁面中;
- base64是一個字符串,也可以直接被嵌到頁面中,或css中。
- 注意:大圖片不適合用base64,只有小圖片才適合用base64處理。
7、設置配置的兩種方式:
方式一:
// 3.處理圖片 // 圖片大小 < limit的值,轉化為base64;此時是url-loader在起作用; // 圖片大小 >= limit的值,不要轉化為base64;而是默認將路徑轉(還是之前的路徑)化為md5的加密格式;此時是file-loader在起作用 { test: /\.(jpg|png|gif)$/, use: ["url-loader?limit=1000"] },
方式二:
{ test: /.\(jpg|png|gif)$/, use: { loader: "url-loader", options: { // 比1000小,=> 轉化為base64 // 比1000大,=> 不會轉為base64,而是內部調用file-loader加載圖片,並用md5方式加密圖片路徑 limit:1000 }, }, },
(四)處理 字體 文件
1、主備字體圖標:字體圖標文件iconfont 或者 從 阿里矢量圖標 里下載
2、將下載好的包拷貝到項目中的css文件中,
3、在main.js中引入css文件,即引入字體圖標的css文件
// 引入字體圖片樣式文件
import "./assets/iconfont/iconfont.css";
4、在html頁面中使用: <i class="iconfont icon-zan"></i>
5、安裝使用:處理字體圖標用到的loader是->url-loader,而這個插件上面在配置圖片文件時已經下載安裝過了,所以直接使用即可。
6、在webpack.config.js中配置
// 處理字體圖標 { test: /\.(eot|svg|ttf|woff|woff2)$/, use: ["url-loader"] },
(五)處理 ES6 語法
1、現在的項目都是使用ES6開發的,但是這些新的ES6語法並不是所有的瀏覽器都支持的,所以就徐婭有一個工具,幫我們轉成ES5語法,這個就是babel;
3、Babel is a JavaScript compiler, ==> babel是一個JavaScript編譯器。
4、webpack只能處理import/ export 這個es6的模塊語法;而其他的js新語法,應該使用babel來處理。
5、比如:var a = { ... obj } 【意思是 將對象obj里面的內容都遍歷一遍,然后都賦給a對象,有點像沈拷貝拷貝的意思】在谷歌上可以,在edge就不可以了。
6、Babel的使用:
6.1安裝一:npm i babel-core babel-loader@7 -D
-
- babel-core 是Babel的核心包
- babel-loader用來加載各個版本的js文件的,並將js代碼內容交給babel-core解析為es5低版本的js語法
6.2 安裝二:npm i -D babel-preset-env babel-preset-stage-2
-
- babel-preset-*表示能夠解析什么版本的js語法
- babel-preset-env:表示能夠解析es2015, es2016, es2017, es2018等這些標准的語法
- babel-preset-stage-2:解析非標准語法,即用來解析已經被使用到的,但是還沒有被采納為標准的語法。
- 比如:'abc'.padStart(10, '6'):准備10位字符,有abc,前面不夠6補充es2017的語法;
- babel-polyfill 與 babel-plugin-transform-runtime也是做兼容處理的,以前都是用這個,兼容更早的。
6.3 配置:在webpack.config.js中,添加一個loader
// 4.處理字體圖標 { test: /\.(eot|svg|ttf|woff|woff2)$/, use: ["url-loader"] }, // 5. 處理js;后面exclude指的是,排除node_modules里面的js文件,因為node_modules里面的js文件都是已經處理好的,
所以不需要再進行處理;再說里面的文件太多了,處理的化,也影響效率 { test: /\.js$/, use: "babel-loader", exclude: /node_modules/ },
6.4 在項目根目錄中創建babel的配置文件,叫:.babelrc
{ "presets": ["env", "stage-2"], // 暫時不用 // 如果未來某一天真的用到了polify "plugins": [ [ "transform-runtime", { "helpers": false, "polyfill": true, "regenerator": true, "moduleName": "babel-runtime" } ] ] }
(六) 熱更新 :--hot : 局部更新
局部熱更新,原理就是改動了代碼里的一部分內容,然后實時的更新到頁面,而不是整體刷新頁面;這樣能提高效率;
具體配置就是,在package.json里面,如上圖的位置,加上 --hot,就能實現了;注:改變完,需要重新運行npm run dev,才能生效。
【備注:只要修改了webpack.cofig.js里面的內容,就需要重新執行項目,因為是配置文件,所以只有重新運行npm run dev之后,新該的配置的會生效】
五、總結:
以上就是自己配置webpack的全部步驟了;整個過程主要目的不是在做項目時自己手動配置,而是通過自己手動配置,能了解里面的步驟、以及開發項目時都需要哪些插件、以及注意點,甚至這些配置是如何一步步進化到最后的全自動化的一個過程。
因為在實際項目時,通過幾行命令安裝了腳手架以后,一個命令就可以生成了;生成的包都是已經配置好的。不需要完整的配置了。
當然,這並不是說,就不用了解配置的過程了,因為項目中說不定就缺哪個插件,就需要隨時安裝插件,如何安裝,在手動配置的時候都有訓練。
回歸到那句話:知其然,更要知其所以然!
end !