第webpack 簡介
webpack 是一種前端資源構(gòu)建工具艺糜,一個靜態(tài)模塊打包器(module bundler)。
webpack 看來, 前端的所有資源文件(js/json/css/img/less/...)都會作為模塊處理滨嘱。它將根據(jù)模塊的依賴關(guān)系進行靜態(tài)分析,打包生成對應(yīng)的靜態(tài)資源(bundle)渣聚。
案例地址: https://github.com/pengjunshan/WebPJS/StudyWebpack
其它Web文章
CSS浮動的使用和解決浮動的五種方法
CSS定位relative愉耙、absolute、fixed使用總結(jié)
原生開發(fā)WebApi知識點總結(jié)
開發(fā)中常用jQuery知識點總結(jié)
C3動畫+H5+Flex布局使用總結(jié)
ES6常用知識總結(jié)
Vue學(xué)習(xí)知識總結(jié)
待續(xù)......
本編文章會講到的知識點
- webpack初體驗
- 常用命令
- HelloWebpack
- webpack開發(fā)環(huán)境配置
- 打包html資源
- 單頁面和多頁面配置
- 打包css資源
- 打包圖片資源
- 打包其它資源
- devServer自動化
- 文件歸類配置
- webpack生產(chǎn)環(huán)境配置
- 提取css樣式文件
- css兼容性處理
- 壓縮css
- js語法檢查
- js兼容性處理
- js和html壓縮
- 生產(chǎn)環(huán)境配置
- webpack優(yōu)化環(huán)境配置
- HMR
- source-map
- oneOf
- 緩存
- tree shaking
- code split
- 懶加載
- PWA
- 多進程打包
- externals
- dll
- optimization
- 常用輔助工具
- resolve
- watch監(jiān)控
- 清除dist文件
- copy文件到dist
- BannerPlugin聲明
- 定義全局變量
- webpack-merge
webpack初體驗
常用命令
了解yarn和npm命令,至于yarn和npm的區(qū)別我就不多說.
npm | yarn | 功能 |
---|---|---|
npm i | yarn | 構(gòu)建項目 |
npm init -y | yarn init -y | 初始化項目 |
npm i vue -s | yarn add vue | 局部安裝(會打包到代碼中) |
npm i vue -d | yarn add vue -d | 局部安裝(不會打包到代碼中) |
npm i vue -g | yarn add vue -g | 全局安裝依賴包 |
- npm i xx -S和yarn add xx
會在package.json的dependencies屬性下添加xx依賴包,生產(chǎn)環(huán)境需要用到的依賴包块饺,比如vue赞辩、jquery項目運行時需要用的庫。
- npm i xx -D和yarn add xx -D
會在package.json的devDependencies屬性下添加xx依賴包,生產(chǎn)環(huán)境不需要用到的依賴包授艰,比如css-loader辨嗽、less-loader轉(zhuǎn)換css的依賴包。
- npm i xx -g和yarn add xx -g
安裝模塊到全局淮腾,不會在項目node_modules目錄中保存模塊包糟需。不會將模塊依賴寫入devDependencies或dependencies 節(jié)點。
比如用npm安裝yarn: npm install yarn -g
HelloWebpack
1.新建一個文件夾 初始化項目谷朝,會生成一個package.json文件
yarn init -y
或者npm init -y
2.安裝webpack webpack-cli依賴包
yarn add webpack webpack-cli -D
或者npm i webpack webpack-cli -D
package.json下會生成devDependencies中會有webpack洲押、webpack-cli
{
"name": "StudyWebpack",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11"
}
}
3.項目中新建src文件夾,src文件夾下新建index.js
4.項目中新建webpack.config.js文件
5.在webpack.config.js中寫配置項
module.exports = {
mode:'development',//開發(fā)環(huán)境 development:開發(fā)環(huán)境 production:生成環(huán)境
entry:'./src/index.js',//入口文件
output:{//出口配置
filename:'index.js',//出口文件名
path:__dirname+'/dist'//出口路徑
}
}
6.在項目下打開命令行窗口圆凰,運行npx webpack命令杈帐,webpack項目會自動先找到webpack.config配置項,然后根據(jù)配置信息進行打包专钉,成功后項目中會多個dist文件挑童,dist就是打包輸出的結(jié)果。
7.注意:只要修改了webpack.config.js文件就要重新
webpack開發(fā)環(huán)境配置
打包html資源
1.安裝 html-webpack-plugin
yarn add html-webpack-plugin -D
或者npm i html-webpack-plugin -D
2.在webpack.config.js中引入html-webpack-plugin插件并配置使用跃须。詳情看代碼注釋炮沐!
/*
插件的使用步驟:
plugins: 1. 下載 2. 引入 3. 使用
*/
//引入html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
//模式
mode:'development',
//入口
entry:'./src/index.js',
//出口
output:{
filename:'bundle.js',//文件名
path:__dirname+'/dist'//出口路徑
},
//配置插件
plugins:[
// 功能:默認會創(chuàng)建一個空的HTML,自動引入打包輸出的所有資源(JS/CSS)
// 需求:需要有結(jié)構(gòu)的HTML文件
new HtmlWebpackPlugin({
// 復(fù)制 './src/index.html' 文件回怜,并自動引入打包輸出的所有資源(JS/CSS)
template:'./src/index.html'
})
]
}
3.運行npx webpack 打包項目大年,dist文件下會生成index.html文件,并且index.html中自動引入了bundle.js文件
單頁面和多頁面配置
entry: 入口起點
方式一:單入口 string -->'./src/index.js'
打包形成一個chunk玉雾。 輸出一個bundle文件翔试。此時chunk的名稱默認是 main。多入口 array -->['./src/index.js','./src/add.js']
所有入口文件最終只會形成一個chunk, 輸出出去只有一個bundle文件复旬。方式三:多入口 object{index:'./src/index.js', add:'./src/add.js'}
有幾個入口文件就形成幾個chunk垦缅,輸出幾個bundle文件,此時chunk的名稱是 key。
module.exports = {
mode: 'development',
// entry:'./src/index.js',方式一
// entry:['./src/index.js','./src/add.js'],方式二
entry: {//方式三
index: './src/index.js',
add: './src/add.js',
home:'./src/home.js'
},
//出口
output: {
//文件名 [name]根據(jù)入口的名稱定義
filename: 'js/[name].js',
//輸出文件目錄(將來所有資源輸出的公共目錄)
path: __dirname + '/dist',
// 所有資源引入公共路徑前綴
publicPath: '/',
// 非入口chunk的名稱
chunkFilename: 'js/[name]_chunk.js',
// library: '[name]', // 整個庫向外暴露的變量名
// libraryTarget: 'window' // 變量名添加到哪個上 browser
// libraryTarget: 'global' // 變量名添加到哪個上 node
// libraryTarget: 'commonjs'
},
plugins: [
//多出口 一般和多入口對應(yīng)
new HtmlWebpackPlugin({
template: './src/index.html',
filename:'index.html',
//只引入index.js驹碍,不指定的話會引入index壁涎、home.js
chunks:['index']
}),
new HtmlWebpackPlugin({
template: './src/index.html',
filename:'home.html',
chunks:['home']
}),
]
}
打包css資源
1.安裝css-loader style-loader less-loader less,我這里只介紹css和less其它樣式用同樣的配置凡恍。
yarn add css-loader style-loader less-loader less -D
2.配置webpack.config.js,在module中配置css-loader和lessloader怔球。詳情看代碼注釋
//引入插件
const HtmlWbpackPlugin = require('html-webpack-plugin')
module.exports = {
//模式
mode:'development',//開發(fā)環(huán)境 development:開發(fā)環(huán)境 production:生成環(huán)境
//入口
entry:'./src/index.js',
//出口
output:{
filename:'bundle.js',//出口文件名
path:__dirname+'/dist'//出口文件路徑
},
//插件配置
plugins:[
new HtmlWbpackPlugin({
template:'./src/index.html',//配置一個模板html
name:'index.html'//生成的html名稱
})
],
//loader配置
module:{
//rules是個數(shù)組嚼酝,因為不同的配置需要不同的loader處理
rules:[
{
//匹配以.css結(jié)尾的文件
test:/\.css$/,
// use數(shù)組中l(wèi)oader執(zhí)行順序:從右到左,從下到上 依次執(zhí)行
use:[
// 創(chuàng)建style標簽竟坛,將js中的樣式資源插入進行闽巩,添加到head中生效
'style-loader',
// 將css文件變成commonjs模塊加載js中,里面內(nèi)容是樣式字符串
'css-loader'
]
},
{
//匹配以.less結(jié)尾的文件
test:/\.less$/,
use:[
// 創(chuàng)建style標簽担汤,將js中的樣式資源插入進行涎跨,添加到head中生效
'style-loader',
// 將css文件變成commonjs模塊加載js中,里面內(nèi)容是樣式字符串
'css-loader',
// 將less文件編譯成css文件
'less-loader'
]
}
]
}
}
打包圖片資源
1.安裝loader,html-loader url-loader file-loader
yarn add file-loader url-loader html-loader -d
2.配置webpack.config崭歧,詳情看代碼注釋隅很。
解決使用html-loader處理html中引入圖片失效,解決方法在url-loader中的options對象中中添加esModule:false屬性率碾。
const HtmlWebpckPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
entry:'./src/index.js',
output:{
filename:'bundle.js',
path:__dirname+'/dist'
},
plugins:[
new HtmlWebpckPlugin({
template:'./src/index.html',
name:'idnex.html'
})
],
module:{
rules:[
{
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
},
{
//匹配圖片結(jié)尾的文件外构,可手動添加
test:/\.(png|jpg|jpeg|gif)/,
// 使用url-loader
loader:'url-loader',
options:{
// 圖片大小小于8kb,就會被base64處理
// 優(yōu)點: 減少請求數(shù)量(減輕服務(wù)器壓力)
// 缺點:圖片體積會更大(文件請求速度更慢)
limit:8*1024,
// 問題:因為url-loader默認使用es6模塊化解析播掷,而html-loader引入圖片是commonjs
// 解析時會出問題:[object Module]
// 解決:關(guān)閉url-loader的es6模塊化审编,使用commonjs解析
esModule:false,
// 給圖片進行重命名
// [hash:10]取圖片的hash的前10位
// [ext]取文件原來擴展名
name: '[hash:10].[ext]'
}
},
{
//匹配.html結(jié)尾的文件
test:/\.html/,
// 處理html文件的img圖片(負責(zé)引入img,從而能被url-loader進行處理)
loader:'html-loader'
}
]
}
}
打包其它資源
1.使用exclude屬性歧匈,排除法
2.配置webpack.config,詳情看代碼注釋
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bunder.js',
path: __dirname + '/dist'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
name: 'index.html'
})
],
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
//處理其它資源
{
//excude排除法 后期手動添加
exclude: /\.(css|js|html|less|png|jpg|jpeg|gif)$/,
//使用file-loader
loader: 'file-loader',
options: {
name: '[hash:10].[ext]'
}
}
]
}
}
devServer自動化
開發(fā)服務(wù)器 devServer后垒酬,只會在內(nèi)存中編譯打包,不會有任何輸出件炉;自動編譯勘究,自動打開瀏覽器,修改代碼后自動刷新瀏覽器斟冕;
1.安裝webpack-dev-server
yarn add webpack-dev-server -D
方法一:配置webpack.config,詳細配置請看代碼注釋
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
entry:'./src/index.js',
output:{
filename:'bundle.js',
path:__dirname+'/dist'
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html',
})
],
// 開發(fā)服務(wù)器 devServer:用來自動化(自動編譯口糕,自動打開瀏覽器,自動刷新瀏覽器~~)
// 特點:只會在內(nèi)存中編譯打包磕蛇,不會有任何輸出
// 啟動devServer指令為:npx webpack-dev-server
devServer: {
// 項目構(gòu)建后路徑
contentBase:__dirname+'/dist',
// 啟動gzip壓縮
compress: true,
// 端口號
port: 3000,
// 自動打開瀏覽器
open: true
}
}
方法二:在wepack.json中配置scripts
{
"name": "StudyWebpack",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"build": "webpack",//打包
"dev": "webpack-dev-server --open --port 3000 --host"http://開發(fā)服務(wù)器 devServer
}
文件歸類配置
當(dāng)src下的文件很多時顯得很亂景描,應(yīng)當(dāng)給相應(yīng)的文件歸類;
- outputPath屬性為loader處理后的文件增加文件夾歸類
- output輸出對象中 filename:'js/bundle.js'秀撇,增加js文件夾
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
// 模式
mode:'development',
// 入口
entry:'./src/js/index.js',
// 出口
output:{
filename:'js/bundle.js',//輸出路徑增加js文件夾
path:__dirname+'/dist'
},
//devServer自動化
devServer:{
contentBase:__dirname+'/dist',
compress:true,
port:3000,
open:true
},
// 插件配置
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
})
],
// loader配置
module:{
rules:[
{ // 處理css
test:/\.css$/,
use:[
'style-loader',
'css-loader'
]
},
{ //處理less
test:/\.less$/,
use:[
'style-loader',
'css-loader',
'less-loader'
]
},
{ //處理圖片
test:/\.(png|jpg|jpeg|gif)/,
loader:'url-loader',
options:{
limit: 8*1024,
name:'[hash:10].[ext]',
exModule:false,
outputPath:'imgs'//圖片輸出增加imgs文件夾
}
},
{ //處理html中圖片
test:/\.html$/,
loader:'html-loader'
},
{ //處理其它文件
exclude:/\.(css|html|js|less|png|jpg|jpeg|gif)/,
loader:'file-loader',
options:{
name:'[hash:10].[ext]',
outputPath:'media'//其它文件增加輸出文件夾
}
}
]
}
}
webpack生產(chǎn)環(huán)境配置
提取css樣式文件
1.安裝mini-css-extract-plugin插件
yarn add mini-css-extract-plugin -D
2.配置webpack.config超棺,詳情看代碼注釋
const HtmlWebpackPlugin = require('html-webpack-plugin')
//1.引入mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
mode:'development',
entry:'./src/index.js',
output:{
filename:'bundle.js',
path:__dirname+'/dist'
},
module:{
rules:[
{
test:/\.css$/,
use:[
// 'style-loader',
//3. 這個loader取代style-loader。作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test:/\.less$/,
use:[
// 'style-loader',
//3. 這個loader取代style-loader呵燕。作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader'
]
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
//2.配置插件
new MiniCssExtractPlugin({
//對輸出的css文件進行文件夾配置和重命名
filename:'css/bundle.css'
})
]
}
css兼容性處理
1.安裝postcss-loader postcss-preset-env
yarn add postcss-loader postcss-preset-env -D
2.package.json中配置browserslist
"browserslist": {
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
3.配置webpack.config棠绘,詳情看代碼注解
const HtmlWebpackPlugin = require('html-webpack-plugin')
//1.引入mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
// 設(shè)置nodejs環(huán)境變量 默認是production環(huán)境
// process.env.NODE_ENV = 'development';
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
},
module: {
rules: [
{
test: /\.css$/,
use: [
// 'style-loader',
//3. 這個loader取代style-loader。作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
'css-loader',
//幫postcss找到package.json中browserslist里面的配置,通過配置加載指定的css兼容性樣式
{
// 使用loader的默認配置
// 'postcss-loader',
// 修改loader的配置
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
// postcss 的插件
require('postcss-preset-env')()
]
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
//2.配置插件
new MiniCssExtractPlugin({
//對輸出的css文件進行文件夾配置和重命名
filename: 'css/bundle.css'
})
]
}
壓縮css
1.安裝optimize-css-assets-webpack-plugin插件
yarn add optimize-css-assets-webpack-plugin -D
2.配置webpack.config氧苍,詳情看代碼注釋
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
//1.引入optimize-css-assets-webpack-plugin
const OptimizeCssAssetsWebapckPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
require('postcss-preset-env')()
]
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'css/bundle.css'
}),
//2.配置插件optimize-css-assets-webpack-plugin
new OptimizeCssAssetsWebapckPlugin()
]
}
js語法檢查
1.安裝 eslint,eslint-loader,eslint-config-airbnb-base,eslint-plugin-import
yarn add eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import
2.package.json中配置eslintConfig
"eslintConfig": {
"extends": "airbnb-base",
"env": {
"browser": true
}
}
3.配置webapck.config夜矗,詳情解釋看代碼注釋
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
entry:'./src/index.js',
output:{
filename:'bundle.js',
path:__dirname+'/dist'
},
module:{
rules:[
{
// 匹配以.js結(jié)尾的文件
test:/\.js$/,
// 排除node_modules下的文件,只檢查自己寫的代碼让虐,不檢查第三方的代碼
exclude:/node_modules/,
loader:'eslint-loader',
options:{
//自動修復(fù)eslint錯誤
fix:true
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
}
js兼容性處理
1.安裝babel-loader @babel/core @babel/preset-env core-js
yarn add babel-loader @babel/core @babel/preset-env core-js -D
2.配置webpack.config紊撕,詳情解釋看代碼注釋
module: {
rules: [
/*
js兼容性處理:babel-loader @babel/core
1. 基本js兼容性處理 --> @babel/preset-env
問題:只能轉(zhuǎn)換基本語法,如promise高級語法不能轉(zhuǎn)換
2. 全部js兼容性處理 --> @babel/polyfill
問題:我只要解決部分兼容性問題澄干,但是將所有兼容性代碼全部引入,體積太大了~
3. 需要做兼容性處理的就做:按需加載 --> core-js柠傍,就不需要@babel/polyfill包了
*/
{
// 匹配以.js結(jié)尾的文件
test: /\.js$/,
// 排除node_modules下的文件麸俘,只檢查自己寫的代碼,不檢查第三方的代碼
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 預(yù)設(shè):指示babel做怎么樣的兼容性處理
presets: [
[
'@babel/preset-env',
{
// 按需加載
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3
},
// 指定兼容性做到哪個版本瀏覽器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
}
]
}
js和html壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
//生產(chǎn)環(huán)境下js代碼自動壓縮
mode:'production',
entry:'./src/index.js',
output:{
filename:'bundle.js',
path:__dirname+'/dist'
},
module:{
rules:[
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// 壓縮html代碼
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注釋
removeComments: true
}
})
]
}
生產(chǎn)環(huán)境配置
css和less有公共的loader代碼惧笛,可以抽離公共loader代碼从媚,以對象擴展的方式引入;正常來講患整,一個文件只能被一個loader處理拜效,當(dāng)一個文件要被多個loader處理,那么一定要指定loader執(zhí)行的先后順序:先執(zhí)行eslint 在執(zhí)行babel各谚;
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 抽離css插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 壓縮css插件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 復(fù)用loader
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
// 還需要在package.json中定義browserslist
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()]
}
}
];
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
},
module: {
rules: [
{
// 處理css
test: /\.css$/,
use: [...commonCssLoader]
},
{
//處理less
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
/*
正常來講紧憾,一個文件只能被一個loader處理。
當(dāng)一個文件要被多個loader處理昌渤,那么一定要指定loader執(zhí)行的先后順序:
先執(zhí)行eslint 在執(zhí)行babel
*/
{
// 在package.json中eslintConfig --> airbnb
test: /\.js$/,
exclude: /node_modules/,
// 優(yōu)先執(zhí)行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: {version: 3},
targets: {
chrome: '60',
firefox: '50'
}
}
]
]
}
},
{
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false
}
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
outputPath: 'media'
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeComments: true
}
}),
new MiniCssExtractPlugin({
filename: 'css/bundle.css'
}),
new OptimizeCssAssetsWebpackPlugin()
]
}
webpack優(yōu)化環(huán)境配置
HMR
作用:一個模塊發(fā)生變化赴穗,只會重新打包這一個模塊(而不是打包所有模塊) 極大提升構(gòu)建速度;
樣式文件:可以使用HMR功能:因為style-loader內(nèi)部實現(xiàn)了;
js文件:默認不能使用HMR功能 --> 需要修改js代碼,添加支持HMR功能的代碼; 注意:HMR功能對js的處理膀息,只能處理非入口js文件的其他文件;
html文件: 默認不能使用HMR功能.同時會導(dǎo)致問題:html文件不能熱更新了~ (不用做HMR功能);解決:修改entry入口般眉,將html文件引入;
devServer: {
contentBase: __dirname+'/dist',
compress: true,
port: 3000,
open: true,
// 模塊熱替換
// hot: true
}
source-map
source-map: 一種 提供源代碼到構(gòu)建后代碼映射 技術(shù) (如果構(gòu)建后代碼出錯了,通過映射可以追蹤源代碼錯誤)
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置
inline-source-map:內(nèi)聯(lián)
只生成一個內(nèi)聯(lián)source-map,錯誤代碼準確信息 和 源代碼的錯誤位置
hidden-source-map:外部
錯誤代碼錯誤原因潜支,但是沒有錯誤位置,不能追蹤源代碼錯誤甸赃,只能提示到構(gòu)建后代碼的錯誤位置
eval-source-map:內(nèi)聯(lián)
每一個文件都生成對應(yīng)的source-map,都在eval, 錯誤代碼準確信息 和 源代碼的錯誤位置
nosources-source-map:外部
錯誤代碼準確信息, 但是沒有任何源代碼信息
cheap-source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置 ,只能精確的行
cheap-module-source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置 ,module會將loader的source map加入
內(nèi)聯(lián) 和 外部的區(qū)別:
- 外部生成了文件冗酿,內(nèi)聯(lián)沒有
- 內(nèi)聯(lián)構(gòu)建速度更快
開發(fā)環(huán)境:速度快埠对,調(diào)試更友好
速度快(eval>inline>cheap>...)
eval-cheap-souce-map
eval-source-map
調(diào)試更友好
souce-map
cheap-module-souce-map
cheap-souce-map
綜合推薦:eval-source-map / eval-cheap-module-souce-map
生產(chǎn)環(huán)境:源代碼要不要隱藏? 調(diào)試要不要更友好
內(nèi)聯(lián)會讓代碼體積變大,所以在生產(chǎn)環(huán)境不用內(nèi)聯(lián)
綜合推薦:source-map / cheap-module-souce-map
// 開發(fā)模式
mode: 'development',
devtool:'eval-source-map'
//生產(chǎn)模式
mode: 'production',
devtool:'source-map'
oneOf
在不使用oneOf之前裁替,一個文件被一個loader匹配到后還會繼續(xù)向下匹配其它匹配不了的loader鸠窗,這樣性能不好,使用oneOf后當(dāng)一個文件被一個loader匹配到后就不會向下繼續(xù)匹配了胯究;但是使用oneOf只會匹配一個loader稍计,所以如果設(shè)置了一個文件兩個loader的話需要分開寫,不能寫在同一個oneOf里面裕循。
module: {
rules: [
{
// 在package.json中eslintConfig --> airbnb
test: /\.js$/,
exclude: /node_modules/,
// 優(yōu)先執(zhí)行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true
}
},
{
// 以下loader只會匹配一個
// 注意:不能有兩個配置處理同一種類型文件
oneOf: [
{
// 處理css
test: /\.css$/,
// 配置多個loader使用use
use: [...commonCssLoader]
},
{
//處理less
test: /\.less$/,
use: [...commonCssLoader, 'less-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
// 配置單個loader使用loader
loader: 'babel-loader',
// 排除node_modules下的js
exclude: /node_modules/,
// 只匹配src下的js
include: __dirname + '/src',
// 優(yōu)先執(zhí)行
enforce: 'pre',
// 延后執(zhí)行
enforce: 'post',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: { version: 3 },
targets: {
chrome: '60',
firefox: '50'
}
}
]
}
]
}
緩存
當(dāng)已經(jīng)加載了js或css等其它后臣嚣,再次使用的時候不需要再次進行請求了净刮,而是使用緩存后的文件;
hash: 每次wepack構(gòu)建時會生成一個唯一的hash值硅则。
1.問題: 因為js和css同時使用一個hash值淹父。
2.如果重新打包,會導(dǎo)致所有緩存失效怎虫。(可能我卻只改動一個文件)
chunkhash:根據(jù)chunk生成的hash值暑认。如果打包來源于同一個chunk,那么hash值就一樣大审。
1.問題: js和css的hash值還是一樣的蘸际。
2.因為css是在js中被引入的,所以同屬于一個chunk徒扶。
contenthash:根據(jù)文件的內(nèi)容生成hash值粮彤。不同文件hash值一定不一樣。
1.讓代碼上線運行緩存更好使用
/*
緩存:
babel緩存
cacheDirectory: true
--> 讓第二次打包構(gòu)建速度更快
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
],
// 開啟babel緩存
// 第二次構(gòu)建時姜骡,會讀取之前的緩存
cacheDirectory:true
}
}
tree shaking
tree shaking:去除無用代碼
前提:1. 必須使用ES6模塊化 2. 開啟production環(huán)境
作用: 減少代碼體積
sideEffects配置
"sideEffects": false :所有代碼都都可以進行tree shaking
副作用:可能會把css / @babel/polyfill 文件干掉导坟;
"sideEffects": [".css", ".less"]跳過css、less文件(如果壓過沒有使用css也會打包進去)
code split
[name]:取入口文件的名稱圈澈;
optimization:
- 可以將node_modules中代碼單獨打包一個chunk最終輸出
- 自動分析多入口chunk中惫周,有沒有公共的文件。如果有會打包成單獨一個chunk
懶加載
當(dāng)一個index.js中引入了其它js文件康栈,進入index.js時不希望立馬加載其它js闯两,用到其它js時再加載;
//當(dāng)點擊按鈕時再加載utils.js文件
document.querySelector('#btn').onclick = function(){
// 懶加載~:當(dāng)文件需要使用時才加載~
// 預(yù)加載 prefetch:會在使用之前谅将,提前加載js文件 webpackPrefetch: true
// 正常加載可以認為是并行加載(同一時間加載多個文件)
// 預(yù)加載 prefetch:等其他資源加載完畢漾狼,瀏覽器空閑了,再偷偷加載資源
// 慎用預(yù)加載饥臂,兼容性問題逊躁,移動端和低版本瀏覽器不支持
import(/* webpackChunkName: 'test' */'./utils').then(({getName})=>{
console.log(getName())
})
}
PWA
1.安裝workbox-webpack-plugin
yarn add workbox-webpack-plugin -D
2.plugins數(shù)組中加載插件
plugins: [
...
new WorkboxWebpackPlugin.GenerateSW({
/*
1. 幫助serviceworker快速啟動
2. 刪除舊的 serviceworker
生成一個 serviceworker 配置文件~
*/
clientsClaim: true,
skipWaiting: true
})
]
/*
1. eslint不認識 window、navigator全局變量
解決:需要修改package.json中eslintConfig配置
"env": {
"browser": true // 支持瀏覽器端全局變量
}
2. sw代碼必須運行在服務(wù)器上
--> nodejs
-->
npm i serve -g
serve -s dist 啟動服務(wù)器隅熙,將dist目錄下所有資源作為靜態(tài)資源暴露出去
*/
// 注冊serviceWorker
// 處理兼容性問題
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/service-worker.js')
.then(() => {
console.log('sw注冊成功了~');
})
.catch(() => {
console.log('sw注冊失敗了~');
});
});
}
多進程打包
webpack是單線程模型的稽煤,也就是說Webpack一個時刻只能處理一個任務(wù),不能同時處理多個任務(wù)囚戚。使用thread-loader進行多進程打包酵熙。
1.安裝thread-loader
注意:把這個 thread-loader 放置在其他 loader 之前,options中放一些屬性值驰坊;進程啟動大概為600ms匾二,進程通信也有開銷;只有工作消耗時間比較長,才需要多進程打包;
yarn add thread-loader -D
2.配置js loader
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader:'thread-loader',
options:{
workers:2//設(shè)置進程數(shù)量
}
},
{
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
]
}
}
]
}
externals
當(dāng)html中引入了cdn第三方庫,js中也Import導(dǎo)入了同個第三方庫技扼,我們就可以使用externals來配置打包;
//html中引入jquery的cdn
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
//js中導(dǎo)入了jquery
import $ from 'jquery'
//webpack.config配置移除jquery打包進去
// 移除某些包被打包進來
externals:{
jquery:'jQuery'
}
dll
使用dll技術(shù)悴务,對某些庫(第三方庫:jquery、react譬猫、vue...)進行單獨打包讯檐,然后再主項目中進行打包時直接引用就可以了,從而加快了打包速度染服。
1.新建webpack.dll.js文件
2.配置webpack.dll.js
const webpack = require('webpack')
module.exports = {
//需要打包的第三方庫
entry:{
jquery:['jquery'],
// vue:['vue']
},
output:{
filename:'[name].js',
path:__dirname+'/dll',
library:'[name]_[hash:10]'// 打包的庫里面向外暴露出去的內(nèi)容叫什么名字
},
plugins:[
// 打包生成一個 manifest.json --> 提供和jquery映射
new webpack.DllPlugin({
name:'[name]_[hash:10]',//映射庫暴露出的名稱
path:__dirname+'/dll/manifest.json'//文件地址
})
],
mode: 'production'
}
3.配置好webpack.dll.js后運行webpack --config webpack.dll.js命令行别洪,項目下會生成dll文件夾,dll文件夾下會有第三方庫的js和manifest.json文件肌索;
4.安裝add-asset-html-webpack-plugin插件
yarn add add-asset-html-webpack-plugin -D
5.配置webpack.config
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exports = {
mode:'production',//開發(fā)環(huán)境 development:開發(fā)環(huán)境 production:生成環(huán)境
plugins:[
// 告訴webpack哪些庫不參與打包蕉拢,同時使用時的名稱也得變~
new webpack.DllReferencePlugin({
manifest:__dirname+'/dll/manifest.json'
}),
// 將某個文件打包輸出去特碳,并在html中自動引入該資源
new AddAssetHtmlWebpackPlugin({
filepath:__dirname+'/dll/jquery.js'
})
],
}
optimization
- 安裝 terser-webpack-plugin插件
const TerserWebpackPlugin = require('terser-webpack-plugin')
optimization: {
splitChunks: {
chunks: 'all'
// 默認值诚亚,可以不寫~
/* minSize: 30 * 1024, // 分割的chunk最小為30kb
maxSiza: 0, // 最大沒有限制
minChunks: 1, // 要提取的chunk最少被引用1次
maxAsyncRequests: 5, // 按需加載時并行加載的文件的最大數(shù)量
maxInitialRequests: 3, // 入口js文件最大并行請求數(shù)量
automaticNameDelimiter: '~', // 名稱連接符
name: true, // 可以使用命名規(guī)則
cacheGroups: {
// 分割chunk的組
// node_modules文件會被打包到 vendors 組的chunk中。--> vendors~xxx.js
// 滿足上面的公共規(guī)則午乓,如:大小超過30kb站宗,至少被引用一次。
vendors: {
test: /[\\/]node_modules[\\/]/,
// 優(yōu)先級
priority: -10
},
default: {
// 要提取的chunk最少被引用2次
minChunks: 2,
// 優(yōu)先級
priority: -20,
// 如果當(dāng)前要打包的模塊益愈,和之前已經(jīng)被提取的模塊是同一個梢灭,就會復(fù)用,而不是重新打包模塊
reuseExistingChunk: true
}
}*/
},
// 將當(dāng)前模塊的記錄其他模塊的hash單獨打包為一個文件 runtime
// 解決:修改a文件導(dǎo)致b文件的contenthash變化
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`
},
minimizer: [
// 配置生產(chǎn)環(huán)境的壓縮方案:js和css
new TerserWebpackPlugin({
// 開啟緩存
cache: true,
// 開啟多進程打包
parallel: true,
// 啟動source-map
sourceMap: true
})
]
}
常用輔助工具
resolve
resolve: {
// 配置解析模塊路徑別名: 優(yōu)點簡寫路徑 缺點路徑?jīng)]有提示
alias: {
$css: __dirname + '/src/css'
},
// 配置省略文件路徑的后綴名只會匹配到一個蒸其, 一般js和css文件名相同敏释,所以不建議匹配css文
extensions:['.js', '.json', '.jsx', '.css']
}
import {addNum} from './add'//省略的后綴
watch監(jiān)控
//自帶功能 不需要安裝
//監(jiān)控 實時打包
watch:true,
//監(jiān)控的配置項
watchOptions:{
poll:1000,//每秒詢問1000次
aggregateTimeout:500,//防抖 停留500毫秒后再打包
ignored:/node_modules/ //不需要監(jiān)控的文件
}
清除dist文件
- 每次打包先清除dist目錄下的文件
- 安裝clean-webpack-plugin -D
//清除文件
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
plugins:[
...
new CleanWebpackPlugin()
]
copy文件到dist
- 打包時可以把一些文件夾的內(nèi)容拷貝到dist文件夾
- 安裝 copy-webpack-plugin -D
//copy文件插件
const CopyWebpackPlugin = require('copy-webpack-plugin')
plugins:[
...
new CopyWebpackPlugin([
//把doc文件復(fù)制到dist文件夾中
{from:'./doc',to:'./'}
])
]
BannerPlugin聲明
- webpack自帶的插件
- 在打包后的Js文件頭加上注釋聲明
//webpack
const webpack = require('webpack')
plugins:[
...
new webpack.BannerPlugin('杭州柯林電氣股份有限公司版權(quán)所有')
]
定義全局變量
//使用webpack自帶插件DefinePlugin
new webpack.DefinePlugin({
DEV:'false',
FLAGE:JSON.stringify('pjs')//如果想存字符串類型 需要使用JSON.stringify()
})
if(DEV){
console.log("正式環(huán)境")
}else{
console.log("測試環(huán)境")
}
webpack-merge
- 合并配置文件
- 分別創(chuàng)建開發(fā)和生產(chǎn)兩個文件
- 安裝 webpack-merge -D
//webpack.pro.js
let {smart} = require('webpack-merge')
let base = require('./webpack.config.js')
module.exports = smart(base,{
mode:'production'
})
//webpack.dev.js
let {smart} = require('webpack-merge')
let base = require('./webpack.config.js')
module.exports = smart(base,{
mode:'development'
})