原始碼地址:https://gitee.com/cyp926/webpack-project.git
"webpack": "^5.46.0",
"webpack-cli": "^4.7.2",
目錄
1、webpack介紹,
2、webpack中的常用術語chunk
3、五個核心模組
4、打包html
5、開發伺服器devserver,
6、打包css
6.1、打包sass及less,
6.2、抽離css檔案,
6.3、css3相容處理(編譯成各個瀏覽器支援的---字首--),
6.4、壓縮css,
6.5、css去掉無用的代嗎,
7、webpack打包資源,
8、背景圖打包,
9、eslint程式碼規範,
10、js相容處理,
11、樹搖tree-shaking,
12、entry多入口實現分割,
13、optimization配置實現分割,
14、路徑別名與匯入字尾省略
一、webpack
1.1 webpack是什麼
webpack是一種前端資源構建工具,一個靜態模組打包器.在webpack看來,前端的所有資原始檔(js/json/css/image/less/sass...)都會作為模組處理。它將根據模組的依賴關係進行靜態分析,打包生成對應的靜態資源
配置檔案: webpack.config.js
1.2 五個核心內容
- entry:入口。webpack是基於模組的,使用webpack首先需要指定模組解析入口(entry),webpack從入口開始根據模組間依賴關係遞迴解析和處理所有資原始檔。
- output:輸出。原始碼經過webpack處理之後的最終產物。
- loader:模組轉換器。本質就是一個函式,在該函式中對接收到的內容進行轉換,返回轉換後的結果。因為 Webpack 只認識 JavaScript,所以 Loader 就成了翻譯官,對其他型別的資源進行轉譯的預處理工作。
- plugin:擴充套件外掛。基於事件流框架 Tapable,外掛可以擴充套件 Webpack 的功能,在 Webpack 執行的生命週期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。
- mode 模式。通過選擇 development 或 production 之中的一個,來設定 mode 引數,你可以啟用相應模式下的 webpack 內建的優化
1.3 下載webpack的外掛
npm init -y
npm i -D webpack webpack-cli
1.4 基本使用
const path = require('path')
module.exports = {
// https://webpack.docschina.org/configuration/mode/
// 打包模式 development | production
mode: 'development',
// 專案入口
entry: './src/index.js',
// 專案出口
output: {
path: path.resolve(path.dirname(__dirname), 'dist'),
// js/打包的位置, [name]預設的名稱為main ,-[hash:8] 拼接hash
filename: 'js/[name]-[hash:8].js'
}
}
執行打包命令列
- npx webpack
- npx webpack --mode development (不寫配置情況下)
- npx webpack 需要打包的檔案 -o 打包的檔案位置與名稱 --mode development (不寫配置情況下)
快捷配置
我們可以直接在package.json中配置:"build":"webpack"
1.5 打包html
- 安裝:html-webpack-plugin
1)引入
const HtmlWebpackPlugin = require('html-webpack-plugin')
2)打包壓縮html(打包多個,就例項化new多個)
plugins: [
new HtmlWebpackPlugin({
title: '歡迎來到Webpack',打包設定標題 (可選項)
template:'./src/index.html', //打包的檔案
filename:'demo.html', //打包後的名稱 (可選項)
chunks:[], //指定html中使用的js檔案 (可選項)
minify:{ //壓縮 (可選項)
// 移除空格
collapseWhitespace:true,
// 移除註釋
removeComments:true,
}
}),
]
3)模板中使用定義的title
<title><%= htmlWebpackPlugin.options.title %></title>
1.6 開發伺服器 devServer
- npm i -D webpack-dev-server@3 (注意這裡我們用到的是3版本的)
- 命令 npx webpack serve
// 在webpack5 需要加上這個選項才會自動重新整理頁面
target:"web"
配置devServer
devServer:{
contentBase: path.resolve(__dirname, '../dist'),// 執行程式碼目錄(可選)
port:3001, //埠號
compress:true,//自動更新 (可選)
open:true//自動開啟瀏覽器 (可選)
watchOptions: { ignored: /node_modules/}, // 忽略檔案 (可選)
host: 'localhost', // 域名(可選) 預設就是localhost
clientLogLevel: 'none', // 不要顯示啟動伺服器的日誌資訊
overlay: false, // 如果出錯,不要全屏提示
// 伺服器代理 --> 解決開發環境跨域問題
proxy: {
// 一旦devServer伺服器接受到 /api開頭的請求,就會把請求轉發到另一個伺服器
'/api': {
target: 'http://localhost:3000',
// 傳送請求時,請求路徑重寫: 將/api 去除
pathRewrite: {
'^/api': ''
}
}
}
}
package.json中的scripts中配置命令
"serve": "webpack-dev-server --config ./config/webpack.config.js"
1.7 打包css,sass等樣式
1.7.1 打包css
webpack預設只支援js的打包,不支援其它型別,為了讓它支援樣式的打包就需要載入一些loader
- npm i -D css-loader style-loader
/*
一個用 loader:css-loader
一個以上 use:[]
從右往左
*/
module:{
rules:[
{
test: /\.css$/,
use: ['style-loader','css-loader']
}
]
}
1.7.2 打包less或者sass
- less npm i -D less-loader
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}
- sass npm i -D node-sass sass-loader
{
test: /\.sass$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
1.7.3 提取抽離css為單獨檔案
- npm i -D mini-css-extract-plugin
const miniCssExtractPlugin = require('mini-css-extract-plugin')
module:{
rules:[
{
test: /\.css$/,
use: [
miniCssExtractPlugin.loader, //寫在第一行
'css-loader']
},
{
test: /\.css$/,
use: [
miniCssExtractPlugin.loader, //寫在第一行
'css-loader',
'sass-loader'
]
},
]
},
plugins:[
new miniCssExtractPlugin({filename:'demo.css'})
]
1.7.4css3相容處理(變異成各個瀏覽器支援的---字首--)
- npm i -D postcss-loader postcss-preset-env
- package.json配置相容瀏覽器
"browserslist": [
">0.2%",
"last 2 version",
"not dead"
]
- 新建檔案postcss.config.js
module.exports={
plugins:[
require('postcss-preset-env')()
]
}
- 引入loader
{
test: /\.css$/,
use: [
miniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
1.7.5 壓縮css
- npm i -D optimize-css-assets-webpack-plugin
plugins:[
new optimizeCssAssetsWebpackPlugin()
]
1.7.6 css去掉無用的代嗎
- npm i -D purgecss-webpack-plugin
new PurgecssWebpackPlugin({
paths:glob.sync(pattern:`${PATH.src}/**/*`,options:{nodir:true})
})
1.8 webpack打包資源
- npm i -D url-loader file-loader html-loader
1.8.1 背景圖打包
module: {
rules: [
{
test: /\.(png|jpeg|jpg|gif)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath: 'imgs/',
name:'[name][hash].[ext]',//命名hash+名稱
limit:1024*8,//限制8k一下轉base64
}
},
// 也可以這麼寫圖片處理
{
test: /\.(png|jpeg|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
// 圖片小於8kb,就會被base64處理
// 優點: 減少請求數量(減輕伺服器壓力)
// 缺點:圖片體積會更大(檔案請求速度更慢)
limit: 8 * 1024,
name: 'static/imgs/[name].[ext]',
publicPath: '/dist'
}
}
]
},
]
}
1.8.2 html圖 html-loader
module: {
rules: [
{
test: /\.(html)$/,
loader: 'html-loader',
}
]
}
1.8.3 其他檔案打包
像專案中字型資源是不需要進行打包處理的,可以直接的通過複製方式給打包到目標目錄中
module: {
rules: [
{
// exclude 排查資源
exclude:/\.(js|json|html|css|less|scss|png|jpg)$/,
loader:'file-loader',
options:{
outputPath: 'font/', //打包位置
publicPath:'./font', //尋找位置
name:'[name][hasg].[ext]',//命名hash+名稱
}
}
]
}
- 也可以這樣處理靜態資源
- npm i -D copy-webpack-plugin
const CopyPlugin = require('copy-webpack-plugin')
plugins: [
new CopyPlugin({
patterns: [
{
// 來源
from: path.resolve(__dirname, '../src/iconfont/'),
// 目標
to: path.resolve(__dirname, '../dist/iconfont')
},
{
// 來源
from: path.resolve(__dirname, '../src/iconfont/'),
// 目標
to: path.resolve(__dirname, '../dist/iconfont')
}
]
})
]
1.9 eslint程式碼規範(airbnb)
- npm i -D eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import
- package.json
"eslintConfig":{
"extends":"airbnb-base"
}
- webpack.config.js
{
test: /\.js$/,
//只檢查自己寫的程式碼,不檢查第三方的
exclude:/node_modules/,
loader:'eslint-loader'
},
1.10 js相容處理
webpack在不需要引入任何loader可以對於js進行打包處理,但是它不會對於js相容性進行任務的處理,而我們編寫的專案是需要在不同的瀏覽器中執行的,此時就需要對於js的相容性在打包過程中進行對應的處理。使用babel來完成對應的js相容處理
- npm i -D babel-loader @babel/core @babel/preset-env core-js@3
module: {
rules: [
// js相容處理
{
test: /\.js$/,
// 排除
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需載入 inital enter uage
useBuiltIns: 'usage',
// 指定core-js版本
corejs: 3,
// 相容性做到哪個版本的瀏覽器
targets: {
chrome: '80',
firefox: '50',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
}
]
}
環境優化
開發環境
- 打包構建速度
- 優化程式碼除錯
生產優化(樹搖)
- 程式碼執行效能
HMR模組熱替換
devServer:{
port:3001,
compress:true,//自動更新
open:true,//自動開啟瀏覽器
hot:true//HMR模組熱替換
}
樹搖去掉沒用到的js程式碼
- tree-shaking webpack自帶
- es6 匯出
- 必須是 production
可以:在package.json檔案中添加了 "sideEffects": false 表示所有程式碼都沒有副作用(所有程式碼都可以進行tree shaking)
問題:可能會把 css的@babel/polyfill (副作用)檔案刪除掉
解決:"sideEffects":["*.css"]
css去掉無用的代嗎
- npm i -D purgecss-webpack-plugin
new PurgecssWebpackPlugin({
paths:glob.sync(pattern:`${PATH.src}/**/*`,options:{nodir:true})
})
程式碼分割
entry多入口實現分割
entry: {
main: './src/js/index.js',
print: './src/js/print.js'
},
output: {
filename: "js/[name]-[contentHash].js",
path: path.resolve(__dirname, "dist")
}
optimization配置實現分割
- 過大的js檔案拆分成多個,實現並行載入,提高載入速度(把工具庫jq,lodash和業務邏輯拆分開)
可以將node_modules中程式碼單獨打包一個chunk最終輸出
chunks: 表示顯示塊的範圍,有三個可選值:initial(初始塊 同步)、async(按需載入塊)、all(全部塊),預設為all;
optimization: {
splitChunks: {
chunks: 'all'
}
},
路徑別名與匯入字尾省略
// 解析模組的規則
resolve: {
// 配置解析模組路徑別名:優點簡寫路徑,缺點路徑沒有提示
alias: {
// 定義一個@變數,可在import引入時使用
'@': path.resolve(__dirname, '../src')
'$css': path.resolve(__dirname, '../src/css')
},
// 配置省略檔案路徑的字尾名稱 import '@/index'
// 如果省略,建議檔名稱不要重名了
extensions: ['.js', '.json', '.vue']
}
二 程式碼
相關程式碼
webpack.config.js
// 採用commonjs
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const miniCssExtractPlugin = require('mini-css-extract-plugin')
const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
module.exports = {
mode: 'production', //生產:development,開發:production
/*
1、entry:
1、單入口,字串表示-----打包一個chunk,生成一個build
entry:'./src/index.js',
2、多入口,陣列------打包成一個chunk,生成一個build
entry:['./src/index.js','./src/cc.js'],
3、物件的寫法 -----有幾個檔案生成幾個chunk,生成幾個build
entry:{
one:'./src/one.js',
two:'./src/two.js'
}
*/
entry: './src/index.js',
output: {
filename: '[name].js',
// **物件多入口寫法entry: filename:'[name].js',
path: path.resolve(__dirname, 'dist'),
},
// loader 處理非js資源 如html,css,img
module: {
rules: [
/*
一個用 loader:css-loader
一個以上 use:[]
從右往左
{
test: /\.css$/,
use: [
'style-loader',
'css-loader']
},
*/
{
test: /\.css$/,
use: [
miniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
},
{
test: /\.sass$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(png|jpg|jpeg)$/,
loader: 'url-loader',
options: {
publicPath:'./images/',
outputPath: 'imgs/',
name:'[name][hasg].[ext]',//命名hash+名稱
limit:1024*8,//限制8k一下轉base64
}
},
{
test: /\.(html)$/,
loader: 'html-loader',
},
{
// exclude 排查資源
exclude:/\.(js|json|html|css|less|scss|png|jpg)$/,
loader:'file-loader',
options:{
outputPath: 'font/', //大包位置
publicPath:'./font', //尋找位置
name:'[name][hasg].[ext]',//命名hash+名稱
}
},
// eslint 只檢查js
{
test: /\.js$/,
//只檢查自己寫的程式碼,不檢查第三方的
exclude:/node_modules/,
loader:'eslint-loader',
options:{
fix:true,//自動修復
}
},
]
},
// plugin外掛,執行範圍更廣的任務 打包到開發壓縮
plugins: [
// 打包壓縮html(打包多個就例項化new多個)
new htmlWebpackPlugin({
template: './src/index.html', //打包的檔案
filename: 'demo.html', //打包後的名稱
chunks: [], //指定使用的js檔案
minify: { //壓縮
// 移除空格
collapseWhitespace: true,
// 移除註釋
removeComments: true,
}
}),
new miniCssExtractPlugin({ filename: 'demo.css' }),
new optimizeCssAssetsWebpackPlugin()
],
// 在webpack5 需要加上這個選項才會自動重新整理頁面
target:"web",
devServer:{
port:3001,
compress:true,//自動更新
open:true,//自動開啟瀏覽器
hot:true//HMR模組熱替換
}
}
postcss.config.js
module.exports={
plugins:[
require('postcss-preset-env')()
]
}
相關依賴檔案
package.json
{
"name": "webpack5s",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev":"webpack serve --mode development --port 3000",
"build":"webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^6.2.0",
"eslint": "^7.31.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.23.4",
"file-loader": "^6.2.0",
"html-loader": "^2.1.2",
"html-webpack-plugin": "^5.3.2",
"less": "^4.1.1",
"less-loader": "^10.0.1",
"mini-css-extract-plugin": "^2.1.0",
"optimize-css-assets-webpack-plugin": "^6.0.1",
"post-loader": "^2.0.0",
"postcss-loader": "^6.1.1",
"postcss-preset-env": "^6.7.0",
"style-loader": "^3.2.1",
"url-loader": "^4.1.1",
"webpack": "^5.46.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
},
"browserslist": [
">0.2%",
"last 2 version",
"not dead"
],
"eslintConfig": {
"extends": "airbnb-base"
}
}