webpack
中文網:https://www.webpackjs.com/
一、webpack是什麼? 4.x
webpack是一個現代javascript應用程序的靜態模塊打包器(module bundler)。
實際它的定義時有個模塊打包工具,將前端開放中的不同的模塊打包到一起,在頁面引入時減少模塊的加載,以模塊化的形式關聯個文件間的關係,所以我們可以看到在很多的腳手架工具中使用webpack打包後的項目最終只引入了一個js文件,就將所有的關聯的模塊文件都給引入了。
webpack簡單的說一個模塊打包器。
二、爲什麼要使用webpack?webpack能解決什麼問題?
現在很多的網頁都可以看做是功能豐富的應用,他們擁有着複雜的javascript代碼和一大推依賴包。爲了解決這個問題,前端社區湧現出了很多好的實踐方法。
a:模塊化 requirejs 我們可以把複雜的程序細化爲小的文件。
b:scss,less等css預處理器
c:.vue文件
d: ES6語法
以上這些瀏覽器都不能直接識別,都需要經過額外的處理之後才能讓瀏覽器識別,而我們手動去繁瑣,webpack就可以幫我們解決這些問題。
三、webpack和grunt及gulp相比有什麼特性?
grunt 和 gulp是一種能夠優化前端開發流程的工具。
grunt 和 gulp的工作方式是:在一個配置文件中,指明對某些文件進行類似編譯,組合,壓縮的具體步驟,這個工具可以幫你自動完成這些任務。
webpack 是一種模塊化的解決方案。
webpack的工作方式是:把你的項目當做一個整體,通過一個給定的主文件(如:index.js),webpack將從這個文件開始找到你的項目的所有依賴文件,使用loader處理它們,最後打包爲一個瀏覽器可識別的javascript文件。
1、 打包 (依賴關係,把多個文件打包成一個文件,減少請求,服務器的壓力)
2、 轉化 (比如:sass 、vue) 需要使用loader
3、 優化 (SPA(單頁Web應用)越來越流行,webpack可以對你的項目進行優化)
四、webpack可以很好的實現如下目標:
1> 將依賴樹拆分成按需加載的模塊
2> 初始化加載時耗時儘量少
3> 各種靜態資源都可以視作模塊(css,js,模塊,…)
4> 將第三方庫整合成模塊的能力,可以自己配置
5> 適合大型項目,無論是單頁面還是多頁面
五、使用webpack
1、webpack安裝
webpack基於nodejs,必須要保證你的電腦安裝過nodejs
本地安裝webpack ---> 推薦
npm install webpack --save-dev
webpack 4.x版本需要安裝webpack-cli
npm install webpack-cli --save-dev
全局安裝webpack ---> 不推薦
npm install webpack -g
六、基於commonjs的模塊實現
既然webpack可以讓我們使用模塊化的方式編寫代碼。
第一步:構建一個項目目錄,如下:
第二步:定義模塊,如下:
第三步:在app.js中引入模塊,如下:
第四步:在index.html中引入app.js,如下:
在瀏覽器中查看:
第五步:執行webpack app.js -o bundle.js
webpack 入口文件路徑 -o 出口文件路徑
npx webpack ./src/app.js -o ./dist/dist.js
在index.html中引bundle.js
在瀏覽器中查看:
七、webpack是如何工作的?
針對上面的案例,看看webpack是如何工作的
在執行webpack app.js -o bundle.js時,webpack會讀取app.js,在app.js中有一個require語句,需要在讀取a.js。
在這個案例中,到a.js所有的依賴的模塊查找完畢。在實際工作中,有更長的模塊加載鏈,需要加載很多次,直到沒有require爲止。
所有的模塊查找完畢之後,就會分析這些依賴的模塊(文件),然後就開始打包,最後生成一個最終文件。
這是最後生成的文件:
說明:所有引入的文件,最終都會打包到bundle.js中,這是我們爲什麼 只引入一個文件的原因。
再舉一個es6模塊的例子,
說明webpack對commonjs和es6模塊都有很好的支持
八、在工作中使用webpack
在剛纔的兩個案例中,每次需要手動編寫命令執行,非常繁瑣。
實際上是可以簡化,並且還可以提供更強大的功能。
八、webpack的四大核心概念:
-
入口 (entry):入口起點,告訴webpack應該使用哪個模塊,來構建其內部依賴的開始。
入口分兩種情況:單個入口,多個入口
1>單入口:entry: string|array
//只指定入口文件,會默認輸出到dist目錄下的main.js文件內
module.exports = {
entry:'./app.js'
}
//只指定入口文件,值爲對象時,會輸出到dist目錄下的app.js文件內
module.exports = {
entry:{
app:'./app.js'
}
}
//只指定入口文件,其值爲數組時,多個入口文件,但是最後會輸出到dist文件下的main.js內(一個文件)
module.exports = {
entry:['./app.js','./detail.js']
}
2>多入口:entry:{entryChunkName:string|array} 一般用在多頁面開發時(少)
//只指定入口文件,其值爲對象,多入口文件,會分別輸出到dist文件下的對應的文件內
module.exports = {
entry:{
app:'./app.js',
detail:'./detail.js'
}
}
出口 (output)告訴webpack在哪裏輸出它所創建的bundles,以及如何命名這些文件,默認值爲’./dist
module.exports = {
entry:{
app:'./app.js'
},
output:{
filename: '[name]-[hash].js' //name對應entry對象裏面的對應鍵名
path:path.join(__dirname,'./bundle') //目標輸出;目錄的絕對路徑
}
}
注:path:絕對路徑,需要path模塊拼接一下路徑,直接寫:’/bundle’會直接輸出到d:的根目錄下
加載器 (loader)
loader 讓 webpack 能夠去處理那些非js文件轉換成通用的模塊(webpack自身只理解javascript)。
webpack的目標是,讓webpack聚焦於項目中的所有資源,而瀏覽器不需要去關注考慮這些。webpack把每個文件(js,css,less,scss,圖片等)都作爲模塊處理。
注:有了webpack之後,前端的模塊不僅僅限於js的模塊化,也包括css、less、vue、react等,都是模塊化開發。
loader參數:
1、test屬性,用於識別進行轉換某些文件。注:test的值爲正則,切記不能加引號。
2、use屬性,表示進行轉換時,使用哪個loader。 use的值可以是string,array,object 三種類型。
3、options:object 對當前loader的配置
loader 使用
const path = require('path')
module.exports = {
entry: path.join(__dirname, "src/main.js"),
output: {
filename: "bundle.js",
path: path.join(__dirname, "dist")
},
module:{
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: ...,
use: ...
}
]
}
}
在 module 配置項中使用 loader, module配置中配置一個 rules 它是一個規則,當我們打包的文件滿足相應的規則就會使用對應的loader進行打包。
test :表示的是文件的匹配規則,爲一個正則表達式,這裏表示的就是所有以 .css結尾的文件,也就是我們的css文件了。
use:對應這一類型文件採用什麼樣的loader進行處理,對loader進行一些參數的配置。
這裏介紹一下這兩個loader的作用:
- css-loader: css-loader和之後的sass-loader, less-loader一樣,是將我們的css文件轉換爲通用的源文件。
- style-loader: style-loader的作用是在我們的css, less, scss文件被轉化處理好後,會通過style標籤的形式掛載到我們的html頁面上
(注意: 我們的loader的執行順序是自下到上的,所以我們配置時是先執行css文件的轉化後在掛載到html上的,所以之後大家配置loader的時候也需要注意loader的順序)
綜上使用loader的經典步驟:
1>安裝對應的loader
2>配置 module 的 rules 選項,每個loader對應一個對象
3>配置主要包括以下內容:
test:一個匹配loaders所處理的文件擴展名的正則表達式
use:使用的loader 數據類型:string | array | object
常用的 loader
- 樣式文件打包 loader: style-loader, css-loader, sass-loader, less-loader
- 文件打包loader: file-loader, url-loader
- js編譯打包loader: babel-loader …
css的使用方式
1、安裝 style-loader 和 css-loader
下載:
npm install style-loader css-loader --save-dev
webpack.config.js 配置
module: {
rules: [
{
test: /\.css$/,
use:["style-loader","css-loader"] //解析 @imoort 語法,style-loader 插入html 標籤中
}
]
}
運行
npx webpack
在輸出的文件中新建一個html文件去引入使用 編譯好的 js 文件
樣式 sass-loader css-loader style-loader
安裝:
npm install sass-loader node-sass css-loader style-loader --save-dev
以上是把css文件內嵌到 js 中,而不會單獨放到一個css文件中。
可以使用extract-text-webpack-plugin這個插件,把所有入口中引入的*.css文件,移動到獨立分離的css文件。
安裝 :
npm install extract-text-webpack-plugin@next webpack4.x版本
使用的步驟:
第一步:先引入extract-text-webpack-plugin插件
第二步:配置
loader的配置
插件的配置
執行webpack後,生成的目錄
3.html-loader html裏引用的靜態資源,如:img,audio等。
安裝:cnpm install html-loader --save-dev
完全禁用:attrs:false
url-loader 處理圖片和字體文件的loader
安裝:cnpm install url-loader --save-dev
url-loader的fallback配置是file-loader,所以需要安裝file-loader。
- 插件(plugins)
插件(plugins)是用來擴展webpack功能的,它們會在整個構建過程中生效,執行相關的任務。
插件可以完成更多loader不可能完成的功能。
插件分爲兩種:
1)內置插件
2)第三方插件
- html-webpack-plugin 有兩個主要作用:
1)爲html文件中引入外部資源如script、link動態添加每次compile後的hash,防止引用緩存的外部文件問題。
2)可以生成創建html入口文件,比如單頁面可以生成一個html文件入口,配置N個html-webpack-plugin可以生成N個頁面入口。
第一步:安裝html-webpack-plugin插件
cnpm install html-webpack-plugin --save-dev
第二步:在plugins內配置
注:需要替換title,需要在html內title標籤內添加<%= htmlWebpackPlugin.options.title%>,這個配置和html-loader衝突。
生成多個html頁面時,需要用filename來區分,引入的js需要使用chunk來配置。
配置多個:寫多個即可。
- 構建本地服務器 webpack-dev-server
第一步:
安裝:cnpm install webpack-dev-server --save-dev
第二步:在webpack.config.js中配置
第三步:配置package.json裏的scripts字段裏
第四步:在命令行裏執行
npm run dev
注:執行完後不會生成文件,文件會運行在內存中。
九、開發環境和構建環境的構建配置差異
我們在日常的前端開發工作中,一般都會有兩套構建環境:一套開發時使用,構建結果用於本地開發調試,不進行代碼壓縮,打印debug信息,包含sourcemap文件;另外一套構建後的結果是直接應用於線上的,即代碼都是壓縮後,運行時不打印debug信息,靜態文件不包括sourcemap的。有的時候可能還需要多一套測試環境,在運行時直接請求mock工作。
webpack的運行環境是nodejs,我們依賴通過nodejs提供的機制給要運行的webpack程序傳遞環境變量,來控制不同環境下的構建行爲。
例:
在npm中的scripts字段中添加一個用於生產環境的構建命令。
{
"scripts":{
"build":"NODE_ENV=production webpack",
"dev":"NODE_ENV=development webpack-dev-server"
}
}
然後可以在webpack.config.js文件中可以通過process.env.NODE_ENV來獲取命令傳入的環境變量。
注:在這裏會報下面的錯
**原因是window不支持NODE_ENV=development
解決方案:**
第一步:安裝cross-env包 cnpm install --save-dev cross-env
什麼是cross-env?
它是運行跨平臺設置和使用環境變量的腳本。
第二步:在NODE_ENV=development前面加上cross-env即可,如下
{
"scripts":{
"build":"cross-env NODE_ENV=production webpack",
"dev":"cross-env NODE_ENV=development webpack-dev-server"
}
}
十、模塊熱更新
(Hot Module Replacement或HMR)是webpack提供的最有用的功能之一。它允許在運行時更新各種模塊,而無需進行完全刷新。
引用:const webpack = require(‘webpack’);
配置:
devServer:{
hot:true
},
plugins:[
new webpack.HotModuleReplacementPlugin(),
new webpack.NameModulesPlugin()
]