webpack基本配置
vue-cli create-react-app
只需要簡單地配置就可以使用jsx和typescript等一些前端新語法
配置webpack.config.js文件
- entry(項目入口)
字符串芥备,如entry:"./src/index.js"
數(shù)組形式: 如entry:[react, react-dom],可以把數(shù)組中的多個文件打包轉(zhuǎn)換為一個chunk
對象形式荚板,如果需要配置的是多頁的應(yīng)用殴蹄,或者抽離出指定模塊作為指定公共代碼,需要采用這種形式屋灌,屬性名是占位符[name]的值
entry: {
main:'./src/index2.js',
second: './src/index2.js',
vendor:['react', 'react-dom']
}
- output(出口文件)
會告訴webpack在哪里輸出所創(chuàng)建的bundle.js以及如何命名
out:{
path:path.join(__dirname, './dist'),
name: 'js/bundle-[name]-[hash].js,
chunkFilename: 'js/[name].chunk.js',
publicPath:'/dist/'
}
- module(模塊的處理)
webpack只能處理js文件,所以要對傳入的模塊做一些預(yù)處理应狱,用webpack的“l(fā)oader”’去識別新的用法
loader的作用和基本用法
webpack中共郭,loader的配置主要在module.rules中進(jìn)行,這是一個數(shù)組疾呻,每一個rule做了兩件事
識別文件類型除嘹,來確定具體處理該數(shù)據(jù)的loader(Rule.test屬性)
使用相關(guān)的loader對文件進(jìn)行相關(guān)的操作轉(zhuǎn)換(Rule.use屬性)
比如我們想要處理react中的jsx語法
module: {
rules:[{
test: /(\.jsx|\.js)/, //表示匹配規(guī)則,是一個正則表達(dá)式
use:{ //表示針對匹配文件將使用處理的loader
loader: "babel-loader",
options: {
presets: ["es2015", "react"]
}
}
}]
}
常用的loade
module.rules識別各種新語法
轉(zhuǎn)換編譯:script-loader, babel-loader,ts-loader,coffee-loader
處理樣式:style-loader,css-loader,less-loader,sass-loader,postcss-loader
處理文件:raw--loader,url-loader,file-loader
處理數(shù)據(jù):csv-loader,xml-loader
處理模板語言:html-loader,pug-loader,jade-loader,markdown-loader
清理和測試:mocha-loader,eslint-loader
- plugin(loader不能做的處理都能交給plugin來做)
const CleanWebpackPlugin = require("clean-webpack-plugin")
{
...
plugin:[
new webpack.DefinePlugin({
"process.env" : {
NODE_ENV: JSON.stringify("production")
}
}),
new CleanWebpackPlugin(["js"], {
root: __dirname + "/stu/",
verbose: true,
dry: false
})
]
}
常見的plugins:
const HtmlWebpackPlugin = require('html-webpack-plugin')
HtmlWebpackPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
CleanWebpackPlugin
一些輔助開發(fā)的相關(guān)屬性
devtool:打包后的代碼和原始代碼存在較大的差異岸蜗,此選項控制是否生成以及如何生成sourcemap
devserver:通過配置devserver選項尉咕,可以開啟一個本地服務(wù)器
watch:啟用watch模式后,webpack將持續(xù)監(jiān)聽熱河已經(jīng)解析文件的更改璃岳,開發(fā)是開啟會很方便
watchoption:用來定制watch模式的選項
performance:打包后命令行如何展示性能提示年缎,如果超過某個大小是警告還是報錯
- 對于webpack配置悔捶,要區(qū)分開發(fā)環(huán)境還是產(chǎn)環(huán)境
為了避免重復(fù)應(yīng)該提取公共代碼
-所以一般有這么幾個文件
webpack.config.js
webpacl.dev.js
webpack.prod.js
webpack.common.js
1、webpack.base.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'index.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
'useBuiltIns': 'entry'
}]
],
plugins: ['@babel/plugin-transform-runtime']
}
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new CopyWebpackPlugin([{
from: 'static',
to: 'static'
}, ])
],
stats: {
children: false
}
}
2单芜、webpack.config.js
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const devConfig = require('./webpack.dev.config')
const proConfig = require('./webpack.pro.config')
module.exports = (env, argv) => {
let config = argv.mode === 'development' ? devConfig : proConfig;
return merge(baseConfig, config);
};
3蜕该、webpack.dev.config.js
module.exports = {
devtool: 'cheap-module-eval-source-map'
}
4、webpack.pro.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
}
基本配置
拆分配置和merge
處理樣式
啟動本地服務(wù)
處理圖片
處理ES6
模塊化
- 拆分配置和merge
webpack-merge,用于將配置文件進(jìn)行合并
npm install webpack-merge
配置(手動指定config)
package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --open --config ./build/dev.config.js"
},
- 處理樣式
樣式預(yù)處理洲鸠,指的是在開發(fā)中使用到的一些預(yù)編譯語言堂淡,如SCSS. LESS等,在項目打包過程中再將這些預(yù)編譯語言轉(zhuǎn)換為CSS
在module.rules
{
test: /\.css$/,
// loader 的執(zhí)行順序是:從后往前
use: ['style-loader', 'css-loader', 'postcss-loader'] // 加了 postcss
},{
test: /\.less$/,
// 增加 'less-loader' 坛怪,注意順序
use: ['style-loader', 'css-loader', 'less-loader']
}
- 啟動本地服務(wù)
安裝
npm install --save-dev webpack-dev-server
運行
npx webpack-dev-server
devServer: {
port: 8080,
progress: true, // 顯示打包的進(jìn)度條
contentBase: distPath, // 根目錄
open: true, // 自動打開瀏覽器
compress: true, // 啟動 gzip 壓縮
// 設(shè)置代理
proxy: {
// 將本地 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 將本地 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
pathRewrite: {
'/api2': ''
}
}
}
}
為了方便淤齐,我們通常會在package.json文件中寫入一項命令配置本地服務(wù)啟動。
"scripts": {
"dev": "webpack-dev-server",
}
通過命令npm run dev就可以掛載我們指定的目錄袜匿,從而啟動本地服務(wù)了更啄。
- 處理圖片
安裝依賴
npm i -D file-loader
在module.rules
{
test: /\.(png|svg|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name:'assets/[name].[ext]',
}
}
},
- 處理ES6
使用babel處理es6語法
安裝
npm install –save-dev babel-loader @babel/core
webpack.cofig.js配置
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules,
//node_modules的js文件不用ES6轉(zhuǎn)化為ES5
loader: "babel-loader"
}
]
}
webpack配置多入口
const path = require('path');
module.exports={
//入口文件的配置項
entry:{
entry:'./src/entry.js',
//這里我們又引入了一個入口文件
entry2:'./src/entry2.js'
},
//出口文件的配置項
output:{
//輸出的路徑,用了Node語法
path:path.resolve(__dirname,'dist'),
//輸出的文件名稱
filename:'[name].js'
},
//模塊:例如解讀CSS,圖片如何轉(zhuǎn)換居灯,壓縮
module:{},
//插件祭务,用于生產(chǎn)模版和各項功能
plugins:[],
//配置webpack開發(fā)服務(wù)功能
devServer:{}
}
webpack抽離壓縮css文件
需要安裝以下插件
mini-css-extract-plugin //把css抽離成單獨的文件
optimize-css-assets-webpack-plugin //把抽離出來的css代碼壓縮
terser-webpack-plugin //壓縮js代碼
uglifyjs-webpack-plugin作用: 壓縮is代碼,不支持壓縮es6
terser-webpack-plugin作用:壓縮is代碼怪嫌,支持壓縮es6
需要安裝的loader
MiniCssExtractPlugin.loader 把css抽離成單獨的文件
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserJSPlugin = require('terser-webpack-plugin');
const Webpackbar = require('webpackbar');
module.exports = {
// production模式自動壓縮html,js,css,不用額外使用terser-webpack-plugin來壓縮js
// 但是如果要分離css,不管是dev還是prod都需要使用mini-css-extract-plugin
// 但是如果要壓縮分離出來的css,不管是dev還是prod都需要使用optimize-css-assets-webpack-plugin
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
filename: '[name]_[hash:8].js',
path: path.resolve(__dirname,'../build'),
publicPath: './'
},
plugins:[
// 打包之后自動生成index.html文件
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html'
}),
// 打包之前自動刪上一次的打包結(jié)果
new CleanWebpackPlugin(),
// 打包時候的進(jìn)度條
new Webpackbar({color: 'purple'}),
// 抽離css
new MiniCssExtractPlugin({
filename: "css/[name]_[hash:8].css",
chunkFilename: "[id].css"
}),
// 壓縮css
new OptimizeCssAssetsPlugin(),
// 壓縮js
new TerserJSPlugin(),
],
module: {
rules:[
{
test:/\.css$/,
use: [
// 這里一定要使用MiniCssExtractPlugin.loader才能達(dá)到抽離css的效果
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'postcss-loader',
'less-loader'
]
}
]
}
}
webpac抽離公共代碼和第三方代碼
CDN內(nèi)容分發(fā)網(wǎng)絡(luò)
項目中分別有a.js, b.js, page1.js, page2.js這四個JS文件义锥, page1.js 和 page2.js中同時都引用了a.js, b.js, 這時候想把a.js, b.js抽離出來合并成一個公共的js岩灭,然后在page1, page2中自動引入這個公共的js拌倍,怎么配置如下:
optimization(優(yōu)化),與module噪径,output(出口)柱恤,plugins(插件)同級
optimization下面minimizer是壓縮css,splitChunks的common配置
optimization下面vendor配置抽離第三方代碼
module.exports = {
//...
//優(yōu)化項配置
optimization: {
// 分割代碼塊
splitChunks: {
cacheGroups: {
//公用模塊抽離
common: {
chunks: 'initial',
minSize: 0, //大于0個字節(jié)
minChunks: 2, //在分割之前,這個代碼塊最小應(yīng)該被引用的次數(shù)
},
//第三方庫抽離
vendor: {
priority: 1, //權(quán)重
test: /node_modules/,
chunks: 'initial',
minSize: 0, //大于0個字節(jié)
minChunks: 2, //在分割之前找爱,這個代碼塊最小應(yīng)該被引用的次數(shù)
}
}
}
}
}
webpack實現(xiàn)異步加載JS
module chunk bundle 的區(qū)別
module -各個源碼文件梗顺,webapck中一切皆模塊
chunk -多個模塊組件的,如entry import() splitChunk
bundle最終的輸出文件
webpack優(yōu)化構(gòu)建速度
優(yōu)化babel-loder
InnorePlugin
noParse
happyPack
ParallelUglifyPlugin
自動刷新
happyPack
- happyPack多線程打包
- JS單線程车摄,開啟多線程打包
- 提高構(gòu)建速度寺谤,特別是多核CPU
- ParallelUglifyPlugin多進(jìn)程壓縮JS
- webapck內(nèi)置Uglify工具壓縮js
- js單線程,開啟多進(jìn)程壓縮更快
- 和happyPack同理
- 關(guān)于開啟多進(jìn)程
項目較大吮播,打包較慢变屁,開啟多進(jìn)程能提高速度
項目較小,開啟多進(jìn)程會降低速度(進(jìn)程開銷)
按需使用
webpack配置熱更新
自動刷新
watchOptions: {
ignored: /node_modules/, // 忽略哪些
// 監(jiān)聽到變化發(fā)生后會等300ms再去執(zhí)行動作薄料,防止文件更新太快導(dǎo)致重新編譯頻率太高
// 默認(rèn)為 300ms
aggregateTimeout: 300,
// 判斷文件是否發(fā)生變化是通過不停的去詢問系統(tǒng)指定文件有沒有變化實現(xiàn)的
// 默認(rèn)每隔1000毫秒詢問一次
poll: 1000
}
- 熱更新
自動刷新:整個網(wǎng)頁全部刷新敞贡,速度較慢
自動刷新:整個網(wǎng)頁全部刷新,狀態(tài)會丟失
熱更新:新代碼生效摄职,網(wǎng)頁不刷新誊役,狀態(tài)不丟失
const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');
plugins: [
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('development')
}),
new HotModuleReplacementPlugin()
],
devServer: {
port: 8080,
progress: true, // 顯示打包的進(jìn)度條
contentBase: distPath, // 根目錄
open: true, // 自動打開瀏覽器
compress: true, // 啟動 gzip 壓縮
hot: true,
// 設(shè)置代理
proxy: {
// 將本地 /api/xxx 代理到 localhost:3000/api/xxx
'/api': 'http://localhost:3000',
// 將本地 /api2/xxx 代理到 localhost:3000/xxx
'/api2': {
target: 'http://localhost:3000',
pathRewrite: {
'/api2': ''
}
}
}
},
何時使用DllPlugin
前端框架如Vue React获列,體積大,構(gòu)建慢
較穩(wěn)定蛔垢,不常升級版本
同一個版本只構(gòu)建一次即可击孩,不用每次都重新構(gòu)建
webpack已內(nèi)置DllPlugin支持
DllPlugin-打包出dll文件
DllReferencePlugin
webpack優(yōu)化構(gòu)建速度
webpack優(yōu)化構(gòu)建速度(可用于生產(chǎn)環(huán)境)
優(yōu)化babel-loader
IgnorePlugin
noParse
happyPack
ParellelUqlifyPlugin
webpack優(yōu)化構(gòu)建速度(不用于生產(chǎn)環(huán)境)
自動刷新
熱更新
DllPlugin
webpack性能優(yōu)化-產(chǎn)出代碼
體積更小
合理分包,不重復(fù)加載
速度更快鹏漆,內(nèi)存使用更少
{
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
// 小于 5kb 的圖片用 base64 格式產(chǎn)出
// 否則巩梢,依然延用 file-loader 的形式,產(chǎn)出 url 格式
limit: 5 * 1024,
// 打包到 img 目錄下
outputPath: '/img1/',
// 設(shè)置圖片的 cdn 地址(也可以統(tǒng)一在外面的 output 中設(shè)置艺玲,那將作用于所有靜態(tài)資源)
// publicPath: 'http://cdn.abc.com'
}
}
},
webapck性能優(yōu)化-產(chǎn)出代碼
小圖片base64 編碼
bundle加hash
懶加載
使用prodction
Scope Hosting
提取公共代碼
IngorePlugin
使用CDN加速
Tree-Shaking
自動開啟代碼壓縮
Vue React等會自動刪掉調(diào)試代碼括蝠,(如開發(fā)環(huán)境的warning)
啟動Tree-Shaking