1.了解Webpack
- 什么是webpack
- webpack是一個(gè)模塊打包器(bundler)
- 在webpack看來(lái),前端的所有資源文件(js/json/css/img/less/...)都會(huì)作為模塊處理
- 它會(huì)根據(jù)模塊的依賴關(guān)系進(jìn)行靜態(tài)分析,生成對(duì)應(yīng)的靜態(tài)資源
- 四個(gè)核心概念
- Entry:入口起點(diǎn)(entry point)指示webpack應(yīng)該使用哪個(gè)模塊,來(lái)作為構(gòu)建其內(nèi)部依賴圖的開(kāi)始
- Output:告訴webpack在哪里輸出它所創(chuàng)建的bundles,以及如何命名這些文件,默認(rèn)值為 ./dist
- Loader:loader可以讓webpack能夠去處理那些非JavaScript文件(webpack自身只能解析:JavaScript、json)
- plugins:插件可以用于執(zhí)行范圍更廣的任務(wù)。插件的范圍包括,從打包優(yōu)化和壓縮,一直到重新定義環(huán)境中的變量等
- 理解Loader
- webpack本身只能加載js/json模塊,如果要加載其他類(lèi)型的文件(模塊),就需要使用對(duì)應(yīng)的loader進(jìn)行轉(zhuǎn)換/加載
- 它本身是一個(gè)函數(shù),接受源文件作為參數(shù),返回轉(zhuǎn)換的結(jié)果
- loader一般以xxx-loader的方式命名,xxx代表了這個(gè)loader要做的轉(zhuǎn)換功能,比如json-loader
- 理解插件plugin
- 插件可以完成一些loader不能完成的功能
- 插件的使用一般是在webpack的配置信息plugins選項(xiàng)中指定
- CleanWebpackPlugin:自動(dòng)清除指定文件夾資源
- HtmlWebpackPlugin:自動(dòng)生成HTML文件
- UglifyJSPlugin:壓縮js文件
- 配置文件(默認(rèn))
-
webpack.config.js:是一個(gè)node模塊,返回一個(gè)json格式的配置信息對(duì)象
-
2.學(xué)習(xí)文檔
- webpack官網(wǎng):http://webpack.github.io/
- webpack3文檔(英文):https://webpack.js.org/
- webpack3文檔(中文):https://doc.webpack-china.org/
3.webpack的基本使用
1.生成package.json文件
2.安裝webpack(都要安裝):
- npm install webpack@3 -g //全局安裝
- npm install webpack@3 --save-dev //局部安裝
3.小試牛刀處理一個(gè)js
執(zhí)行命令:webpack src/js/index.js build/index.js
觀察發(fā)現(xiàn)webpack會(huì)把es6語(yǔ)法,直接編譯為瀏覽器識(shí)別的模塊化語(yǔ)法,不過(guò)類(lèi)似于箭頭函數(shù)等依然存在
4.使用webpack配置文件
webpack的核心文件:執(zhí)行webpack命令時(shí),會(huì)在當(dāng)前目錄查找webpack.config.js文件讀取配置
1.通過(guò)commonjs暴露出去一個(gè)對(duì)象
2.四個(gè)關(guān)鍵的概念:
entry:入口文件,將所有打包資源全部引入
output:輸出,將資源輸出到指定目錄下
loader:處理webpack不能夠解析的模塊
plugins:執(zhí)行l(wèi)oader做不了的任務(wù)
3.如何找到自己想要的loader?
優(yōu)先去官網(wǎng)找自己想要的loader,沒(méi)有再去npm官網(wǎng)上找
4.在終端輸入:webpack ./src/js/app.js ./build/js/build.js
問(wèn)題:這種方式只能夠編譯打包js、json文件,其他文件處理不了
5.webpack --display-modules可以查看隱藏的任務(wù)
const path = require('path') //path內(nèi)置的模塊,用來(lái)設(shè)置路徑
module.exports = {
//入口(從哪里進(jìn)入開(kāi)始解析)
entry:'./src/js/index.js',
//出口(最終加工完的代碼輸出到哪里)
output: {// 輸出配置
path: path.resolve(__dirname, 'build'),//輸出文件路徑配置
filename: 'index.js',//輸出文件名
}
}
5.在package.json中配置npm命令
"scripts":{
"build":"webpack"
}
//打包應(yīng)用運(yùn)行:npm run build
6.使用loader解析less文件(使用less-loader)
1.安裝:npm install less-loader less --save-D
2.安裝:npm install css-loader style-loader --save-D
3.向rules中寫(xiě)入配置:
{
test: /\.less$/,
use: [
{
loader: "style-loader" //創(chuàng)建一個(gè)style標(biāo)簽,將js中的css放入其中
},
{
loader: "css-loader" //將css以commonJs語(yǔ)法打包到j(luò)s中
},
{
loader: "less-loader" //將less轉(zhuǎn)換成css
}
]
}
4.在入口js中引入less文件:import '../less/demo.less'
7.file-loader處理圖片資源
1.安裝:npm install --save-dev file-loader
2.新增loader:
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader', //如果不做圖片轉(zhuǎn)base64,可以用file-loader
options: {
outputPath: 'img', //圖片最終輸出的位置
publicPath: '../build/img', //css資源圖片路徑
name: '[hash:5].[ext]' //修改圖片名稱(chēng)
}
}
]
}
8.url-loader處理圖片資源&base64
1.安裝:npm install url-loader --save-D
2.修改loader為:
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader', // 如果不做圖片轉(zhuǎn)base64,可以用file-loader
options: {
limit: 8192,
outputPath: 'img', // 圖片最終輸出的位置
publicPath: '../build/img', // css資源圖片路徑
name: '[hash:5].[ext]' // 修改圖片名稱(chēng)
}
}
]
}
3.備注:一定要注意路徑的問(wèn)題
9.使用插件提取css,合并為單獨(dú)的文件
1.安裝ExtractTextWebpackPlugin插件:npm install extract-text-webpack-plugin --save-D
2.引入插件:const ExtractTextPlugin = require("extract-text-webpack-plugin")
3.新增plugins插件配置項(xiàng),并實(shí)例化ExtractTextPlugin插件:
plugins: [
//提取css為單獨(dú)文件
new ExtractTextPlugin("./css/index.css")
]
4.修改原less-loader的配置如下:
{
test: /\.less$/, //匹配文件的規(guī)則,說(shuō)明該loader對(duì)哪個(gè)文件生效
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "less-loader"]
})
}
5.備注:因?yàn)閏ss提取成單獨(dú)文件,不再包含在js中了,所以要修改url-loader配置publicPath為: '../img'
10.js語(yǔ)法檢查
1.安裝jshint-loader:npm i jshint-loader --save -D
2.新增loader:
{
test: /\.js$/, //涵蓋.js文件
enforce: "pre", //預(yù)先加載jshint-loader
exclude: /node_modules/, //排除掉 node_modules 文件夾下的所有文件
use: [
{
loader: "jshint-loader",
options: {
//jshint的錯(cuò)誤信息默認(rèn)情況下會(huì)顯示為warning(警告)類(lèi)信息
//將emitErrors參數(shù)設(shè)置為true可使錯(cuò)誤顯示為error(錯(cuò)誤)類(lèi)信息
emitErrors: false,
//jshint默認(rèn)情況下不會(huì)打斷webpack編譯
//如果你想在jshint出現(xiàn)錯(cuò)誤時(shí),立刻停止編譯
//請(qǐng)?jiān)O(shè)置 failOnHint 參數(shù)為true
failOnHint: false
}
}
]
}
3.備注:有一個(gè)小坑,就是僅僅安裝jshint-loader還不夠,
還要安裝js-hint,命令:npm i jshint --save -D
11.es6轉(zhuǎn)es5
1.安裝babel-loader,命令:npm install babel-loader babel-core babel-preset-es2015 --save -D
2.配置新的loader
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
persets: ['es2015']
}
}
}
3.坑!提示找不到"@babel/core",根據(jù)提示執(zhí)行:npm i babel-loader@7 --save -D
12.html文件的處理和清除文件夾
1.對(duì)于html的操作,雖然有了html-loader這個(gè)loader,不過(guò)功能有限我們的需求是:
想讓webpack自動(dòng)的幫我們創(chuàng)建一個(gè)html,然后把我們想要引入的東西引入進(jìn)來(lái),所以要借助插件。
2.使用插件HtmlWebpackPlugin,安裝:npm install --save-dev html-webpack-plugin
3.引入插件:const HtmlWebpackPlugin = require('html-webpack-plugin')
4.新增一個(gè)插件配置項(xiàng):
new HtmlWebpackPlugin({
title: 'webpack',
filename:'index.html',
template:'./src/index.html'
})
備注:要在html模板中寫(xiě)入<title><%= htmlWebpackPlugin.options.title %></title>,title配置才生效
5.刪除掉模板html中的所有引入
6.為了清空工作目錄,安裝插件:clean-webpack-plugin,命令:npm i clean-webpack-plugin -D
7.引入插件:const {CleanWebpackPlugin} = require('clean-webpack-plugin')
8.實(shí)例一個(gè)插件:
new CleanWebpackPlugin('./build')
備注:最新版的CleanWebpackPlugin不傳任何參數(shù)
13.提取build環(huán)境配置文件
1.新建文件目錄:config
2.移動(dòng)webpack.config.js文件到config中,改名為:webpack.build.js
3.通過(guò)執(zhí)行:webpack --display-modules --config ./config/webpack.build.js 指定配置文件運(yùn)行
4.完善一下:在package.json中定義命令:
"build": "webpack --display-modules --config ./config/webpack.build.js"
5.以后可以通過(guò):npm run build代替完整命令
6.【問(wèn)題】:發(fā)現(xiàn)build文件夾出現(xiàn)在了config中,解決辦法如下:
修改出口output中的path為:resolve(__dirname, '../build')
7.【問(wèn)題】:上一步的清空位置發(fā)生了改變,解決辦法如下:
修改CleanWebpackPlugin插件的配置如下:
new CleanWebpackPlugin('./build', {
root:resolve(__dirname,'../')
})
備注:如果使用的clean-webpack-plugin插件是2.0以上的,則不會(huì)出現(xiàn)問(wèn)題7
14.提取dev環(huán)境配置文件(dev環(huán)境搭建)
1.復(fù)制一份webpack.build.js,改名為:webpack.dev.js
2.安裝dev-server:npm i webpack-dev-server@2 -D(下載第2個(gè)版本,3版本有兼容性問(wèn)題)
3.修改package.json的配置:"dev": "webpack-dev-server --config ./config/webpack.dev.js"
4.在webpack.dev.js中配置dev服務(wù)器編:
//配置開(kāi)發(fā)服務(wù)器
devServer: {
hot: true,//熱模替換
open: true,//自動(dòng)打開(kāi)瀏覽器
port: 3001,
compress: true//啟用gzip壓縮
}
備注:官網(wǎng)-->配置-->開(kāi)發(fā)中server(devserver)可見(jiàn)詳細(xì)配置
5.啟用HMR(熱模替換)
引入webpack:const webpack = require("webpack")
追加一個(gè)插件:new webpack.HotModuleReplacementPlugin()
6.存在的問(wèn)題:改了css、html還得手動(dòng)刷新才可以,解決如下:
7.【解決css無(wú)法模塊熱更新的問(wèn)題】因?yàn)閏ss用的是插件,不是loader,所以不行,解決辦法:重新使用loader的方式
8.【解決html無(wú)法自動(dòng)刷新的問(wèn)題】因?yàn)閔tml也是插件,辦法:html依然用插件,追加使用loader,安裝:npm i html-loader -D
新增html-loader配置項(xiàng)如下
{
test: /\.(html)$/,
use: {
loader: 'html-loader'
}
}
同時(shí)entry重寫(xiě)為:['./src/js/index.js','./src/index.html']
備注:需要注意的是:dev方式的運(yùn)行是加載在內(nèi)存中的,沒(méi)有任何輸出
15.提取公共代碼實(shí)現(xiàn)復(fù)用
1.參考webpack.build.js,新增:webpack.common.js
2.webpack.common.js中刪除所有css的loader,刪除CleanWebpackPlugin,刪除ExtractTextPlugin插件,刪除最上方二者的引用
3.在webpack.build.js上方引入:const common = require('./webpack.common')
4.安裝合并庫(kù):npm i webpack-merge -D,引入merge庫(kù):const merge = require('webpack-merge')
5.module.exports = merge(common,{當(dāng)前文件所有配置})
6.剔除webpack.build.js中:入口,出口,圖片處理,js語(yǔ)法檢查,es6轉(zhuǎn)換,HtmoWebpackPlugin
7.剔除webpack.dev.js中:出口,圖片處理,js語(yǔ)法檢查,es6轉(zhuǎn)換,插件只保留:HotModuleReplacementPlugin
16.prod環(huán)境配置
復(fù)制webpack.build.js。改名:webpack.prod.js
package.json中追加:"prod": "webpack --display-modules --config ./config/webpack.prop.js"
pro模式輸出的文件在dist文件夾中,修改出口配置:path:resolve(__dirname, '../dist'),filename: './js/[name].[hash:10].js'
修改css插件配置:new ExtractTextPlugin("./css/[name].[hash:10].css")
【壓縮js】
使用插件(用于壓縮js文件):UglifyjsWebpackPlugin
引入webpack:const webpack = require('webpack')
插件中新增配置:new webpack.optimize.UglifyJsPlugin({sourceMap:true})
追加一個(gè)配置(與插件同級(jí)):devtool:'source-map'
【css擴(kuò)展前綴】
使用loader:postcss-loader,執(zhí)行安裝:npm i -D postcss-loader
在css的loader配置中加入postcss-loader:use: ["css-loader","postcss-loader","less-loader"]
在根目錄新建postcss.config.js文件,配置如下內(nèi)容:
module.exports = {
"plugins": {
"autoprefixer": {
"browsers": [
"ie >= 8",
"ff >= 30",
"chrome >= 34",
"safari >= 7",
"opera >= 23"
]
}
}
}
安裝所需的autoprefixer,命令:npm i autoprefixer -D
【壓縮css】
使用less-plugin-clean-css插件,命令:npm i less-plugin-clean-css -D
引入插件:const CleanCSSPlugin = require("less-plugin-clean-css")
替換use中的less-loader為對(duì)象,如下:
loader: "less-loader",options: {
plugins: [
new CleanCSSPlugin({ advanced: true })
]
}
【壓縮html】
將webpack.common.js中的HtmlWebpackPlugin插件復(fù)制過(guò)來(lái)
追加一個(gè)配置項(xiàng):minify:{ removeComments:true, collapseWhitespace:true }
webpack面試題
1.webpack的核心概念
Entry:入口,webpack進(jìn)行打包的起始點(diǎn)(文件)
Output:出口,webpack編譯打包生成的bundle(打包文件)
Loader:模塊加載(轉(zhuǎn)換)器,將非js、非json模塊包裝成webpack能理解的js模塊
Plugin:插件,在webpack構(gòu)建流程中的特定時(shí)機(jī)插入具有特定功能的代碼
Module:模塊,在webpack眼中一起皆模塊,默認(rèn)只識(shí)別js文件,如果是其他類(lèi)型文件利用對(duì)應(yīng)的loader轉(zhuǎn)換為js模塊
2.webpack配置文件的整體結(jié)構(gòu)
module.exports = {
entry: '', //入口
output: {}, //輸出
module: {rules: []}, //配置loader
plugins: [] //配置plugin
}
3.webpack模塊化打包的基本流程
1.連接:webpack從入口js開(kāi)始,遞歸查找出所有相關(guān)聯(lián)的模塊,并【連接】起來(lái)形成一個(gè)圖(網(wǎng))的結(jié)構(gòu)
2.編譯:將js模塊中的模塊化語(yǔ)法【編譯】為瀏覽器可以直接運(yùn)行的模塊語(yǔ)法(當(dāng)然其他類(lèi)型資源也會(huì)處理)
3.合并:將圖中所有編譯過(guò)的模塊【合并】成一個(gè)或少量的幾個(gè)bundle文件,瀏覽器真正運(yùn)行是打包生成的bundle文件
4.比較loader與plugin
1.loader:用于加載特定類(lèi)型的資源文件,webpack本身只能打包js。
2.plugin:用來(lái)擴(kuò)展webpack其他方面的功能,一般loader處理不了的資源,完成不了的操作交給插件處理。
5.區(qū)別live-reload(自動(dòng)刷新)與hot-realod/HMR(熱模替換)
相同點(diǎn):
代碼修改后都會(huì)自動(dòng)重新編譯打包
不同點(diǎn):
live-reload:刷新整體頁(yè)面,從而查看到最新代碼的效果,頁(yè)面狀態(tài)全部都是新的。
Hot-reload:沒(méi)有刷新整個(gè)頁(yè)面,只是加載了修改模塊的打包文件并運(yùn)行,從而更新頁(yè)面的局部界面,整個(gè)界面的其他部分的狀態(tài)還在
6.webpack常用loader與plugin匯總
loader:
1.【less-loader】:用于將less文件翻譯成為css
2.【css-loader】:用于將css以commonjs語(yǔ)法打包到j(luò)s中
3.【style-loader】:用于動(dòng)態(tài)創(chuàng)建一個(gè)style標(biāo)簽,將css引入頁(yè)面
備注:上述三個(gè)loader一般配合使用,最終實(shí)現(xiàn):翻譯less為css,以style標(biāo)簽形式將樣式引入頁(yè)面
4.【file-loader】:提取源代碼圖片資源,到指定位置,可修改文件名等操作
5.【url-loader】:與file-loader功能幾乎一致,優(yōu)勢(shì)是可以對(duì)圖片進(jìn)行動(dòng)態(tài)轉(zhuǎn)換base64編碼(控制limit屬性值可以控制閾值)
備注:上述兩個(gè)loader中url-loader應(yīng)用比f(wàn)ile-loader廣泛
6.【jshint-loader】:對(duì)項(xiàng)目中的js語(yǔ)法進(jìn)行檢查,可選的配置項(xiàng)有:
emitErrors: true/false
-- emitErrors為true,檢查出的錯(cuò)誤顯示為error(錯(cuò)誤)類(lèi)信息
-- emitErrors為false,檢查出的錯(cuò)誤顯示為warning(錯(cuò)誤)類(lèi)信息
failOnHint: true/false
-- failOnHint為true,當(dāng)jshint檢查出錯(cuò)誤時(shí),直接打斷當(dāng)前的代碼的編譯
-- failOnHint為false,當(dāng)jshit檢查出錯(cuò)誤時(shí),會(huì)繼續(xù)編譯
esversion:6
-- 告訴jshint,不再提示新語(yǔ)法兼容性問(wèn)題(有專(zhuān)門(mén)的loader解決新語(yǔ)法問(wèn)題)
-- 自定義一個(gè)報(bào)告錯(cuò)誤的函數(shù),輸出想要的內(nèi)容
reporter: function(errors) {}
-- 自定義一個(gè)報(bào)告錯(cuò)誤的函數(shù),輸出想要的內(nèi)容
7.【babel-loader】:將es6語(yǔ)法轉(zhuǎn)換為es5語(yǔ)法
備注:該loader的使用要借助:babel-loader babel-core babel-preset-es2015
8.【postcss-loader】:用于擴(kuò)展css前綴
備注:
(1).該loader需要一個(gè)postcss.config.js配置文件
(2).該loader要配合autoprefixer庫(kù)使用
(3).該loader使用的時(shí)機(jī)為:["css-loader","postcss-loader","less-loader"]
pulgin:
1.【extract-text-webpack-plugin】:用于提取項(xiàng)目中的css,最終合并為一個(gè)單獨(dú)的文件。
備注:上述插件需要配合:css-loader、less-loader兩個(gè)loader使用,css-loader、less-loader處理之后,交給extract-text-webpack-plugin處理
2.【html-webpack-plugin】:自動(dòng)創(chuàng)建html文件,且自動(dòng)引入外部資源。配置項(xiàng)如下:
title:"webpack",
filename:"index.html",
template:"./src/index.html"
//用于壓縮html
minify:{
removeComments: true, //移除注釋
collapseWhitespace: true //移除換行
}
3.【clean-webpack-plugin】:清空webpack的輸出目錄,防止其他文件“亂入”
4.【HotModuleReplacementPlugin】:熱模替換(HMR)插件
備注:1.該模塊必須配合webpack-dev-server模塊使用,且webpack-dev-server中必須啟用HMR
2.想要讓指定文件支持HMR,必須要:
(1).無(wú)論是否有插件操作過(guò)該類(lèi)型的資源,最終必須交給loader處理
(2).必須在入口文件中聲明使用。
5.【UglifyJsPlugin】:壓縮js的插件,且可以生成sourceMap映射文件,用于方便排查錯(cuò)誤
6.【less-plugin-clean-css】:壓縮css文件,在less-loader翻譯less文件之后,該插件介入,開(kāi)始?jí)嚎s
