module:{
rules:[
{
test:/\.js$/,
use:['babel-loader?cacheDirectory'],
+ include:path.resolve(__dirname,'src'),
+ exclude:/node_modules/
}
]
}
複製代碼
resolve: {
modules: [path.resolve(__dirname, 'node_modules')]
},
複製代碼
mainFields
用於配置第三方模塊使用那個入口文件 isomorphic-fetchcss
resolve.alias
配置項經過別名來把原導入路徑映射成一個新的導入路徑 此優化方法會影響使用Tree-Shaking
去除無效代碼node
alias: {
'react': path.resolve(__dirname, './node_modules/react/cjs/eact.production.min.js')
}
複製代碼
在導入語句沒帶文件後綴時,Webpack會自動帶上後綴後去嘗試詢問文件是否存在 默認後綴是 extensions: ['.js', '.json']
react
resolve: {
+ extensions: ['js']
},
複製代碼
module.noParse 配置項可讓 Webpack 忽略對部分沒采用模塊化的文件的遞歸解析處理webpack
module: {
+ noParse: [/react\.min\.js/]
}
複製代碼
被忽略掉的文件裏不該該包含 import 、 require 、 define 等模塊化語句git
.dll 爲後綴的文件稱爲動態連接庫,在一個動態連接庫中能夠包含給其餘模塊調用的函數和數據github
module.exports = {
entry: {
react: ['react'] //react模塊打包到一個動態鏈接庫
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].dll.js', //輸出動態鏈接庫的文件名稱
library: '_dll_[name]' //全局變量名稱
},
plugins: [
new webpack.DllPlugin({
name: '_dll_[name]', //和output.library中一致,值就是輸出的manifest.json中的 name值
path: path.join(__dirname, 'dist', '[name].manifest.json')
})
]
}
複製代碼
webpack --config webpack.dll.config.js --mode production
複製代碼
plugins: [
+ new webpack.DllReferencePlugin({
+ manifest: require(path.join(__dirname, 'dist', 'react.manifest.json')),
+ })
],
複製代碼
webpack --config webpack.config.js --mode development
複製代碼
HappyPack就能讓Webpack把任務分解給多個子進程去併發的執行,子進程處理完後再把結果發送給主進程。 happypackweb
npm i happypack@next -D
複製代碼
module: {
rules: [{
test: /\.js$/,
//把對.js文件的處理轉交給id爲babel的HappyPack實例
+ use: 'happypack/loader?id=babel',
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/
}, {
//把對.css文件的處理轉交給id爲css的HappyPack實例
test: /\.css$/,
+ use: 'happypack/loader?id=css',
include: path.resolve(__dirname, 'src')
}],
noParse: [/react\.min\.js/]
},
複製代碼
plugins: [
//用惟一的標識符id來表明當前的HappyPack是用來處理一類特定文件
new HappyPack({
id: 'babel',
//如何處理.js文件,和rules裏的配置相同
loaders: [{
loader: 'babel-loader',
query: {
presets: [
"env", "react"
]
}
}]
}),
new HappyPack({
id: 'css',
loaders: ['style-loader', 'css-loader'],
threads: 4, //表明開啓幾個子進程去處理這一類型的文件
verbose: true //是否容許輸出日子
})
],
複製代碼
ParallelUglifyPlugin
能夠把對JS文件的串行壓縮變爲開啓多個子進程並行執行express
npm i -D webpack-parallel-uglify-plugin
複製代碼
new ParallelUglifyPlugin({
workerCount: 3, //開啓幾個子進程去併發的執行壓縮。默認是當前運行電腦的 CPU 核數減去1
uglifyJS: {
output: {
beautify: false, //不須要格式化
comments: false, //不保留註釋
},
compress: {
warnings: false, // 在UglifyJs刪除沒有用到的代碼時不輸出警告
drop_console: true, // 刪除全部的 `console` 語句,能夠兼容ie瀏覽器
collapse_vars: true, // 內嵌定義了可是隻用到一次的變量
reduce_vars: true, // 提取出出現屢次可是沒有定義成變量去引用的靜態值
}
},
})
複製代碼
咱們能夠監聽到本地源碼文件發生變化時,自動從新構建出可運行的代碼後再刷新瀏覽器npm
+ watch: true, //只有在開啓監聽模式時,watchOptions纔有意義
+ watchOptions: {
+ ignored: /node_modules/,
+ aggregateTimeout: 300, //監聽到變化發生後等300ms再去執行動做,防止文件更新太快致使編譯頻率過高
+ poll: 1000 //經過不停的詢問文件是否改變來判斷文件是否發生變化,默認每秒詢問1000次
+ }
複製代碼
aggregateTimeout
配置devServer: {
contentBase: './dist',
+ inline: true
},
複製代碼
webpack負責監聽文件變化,webpack-dev-server負責刷新瀏覽器 這些文件會被打包到chunk中,它們會代理客戶端向服務器發起WebSocket鏈接json
+ [19] (webpack)-dev-server/client/overlay.js 3.58 KiB {0} [built]
+ [21] (webpack)-dev-server/client/socket.js 1.05 KiB {0} [built]
+ [22] ./node_modules/loglevel/lib/loglevel.js 7.68 KiB {0} [built]
+ [24] ./node_modules/strip-ansi/index.js 161 bytes {0} [built]
+ [31] ./node_modules/url/url.js 22.8 KiB {0} [built]
+ [32] (webpack)-dev-server/client?http://localhost:8080 7.75 KiB {0} [built]
+ [33] multi (webpack)-dev-server/client?http://localhost:8080 ./src/index.js 40 bytes {0} [built]
複製代碼
模塊熱替換(Hot Module Replacement)的技術可在不刷新整個網頁的狀況下只更新指定的模塊 原理是當一個源碼發生變化時,只從新編譯發生變化的模塊,再用新輸出的模塊替換掉瀏覽器中對應的老模塊
devServer: {
+ hot:true
}
複製代碼
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[0] multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server ./src/index.js 52 bytes {main} [built]
[./node_modules/webpack/hot/dev-server.js] (webpack)/hot/dev-server.js 1.66 KiB {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 77 bytes {main} [built]
複製代碼
if (module.hot) {
module.hot.accept('./index.js', function () {
console.log('accept index.js');
});
}
複製代碼
優化模塊熱替換瀏覽器日誌
plugins: [
+ new webpack.NamedModulesPlugin(),
+ new webpack.HotModuleReplacementPlugin(),
]
複製代碼
在開發網頁的時候,通常都會有多套運行環境,例如:
if(process.env.NODE_ENV == 'production'){
console.log('生產環境');
}else{
console.log('開發環境');
}
複製代碼
當你使用process模塊的時候,webpack會把process模塊打包進來
+ new webpack.DefinePlugin({
+ 'process.env': {
+ NODE_ENV:JSON.stringify('production')
+ }
+ }),
複製代碼
定義環境變量的值時用 JSON.stringify 包裹字符串的緣由是環境變量的值須要是一個由雙引號包裹的字符串,而 JSON.stringify('production')的值正好等於'"production"'
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
})
複製代碼
CDN 又叫內容分發網絡,經過把資源部署到世界各地,用戶在訪問時按照就近原則從離用戶最近的服務器獲取資源,從而加速資源的獲取速度。
output: {
path: path.resolve(__dirname, 'dist'),
+ filename: '[name]_[hash:8].js',
+ publicPath: 'http://img.zhufengpeixun.cn'
},
複製代碼
Tree Shaking
能夠用來剔除JavaScript
中用不上的死代碼。它依賴靜態的ES6
模塊化語法,例如經過import
和export
導入導出。
使用Tree
{
loader: 'babel-loader',
query: {
presets: [
[
+ "env", {
+ modules: false //含義是關閉 Babel 的模塊轉換功能,保留本來的 ES6 模塊化語法
+ }
],
"react"
]
}
}
複製代碼
webpack --display-used-exports
複製代碼
+ const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
plugins: [
+ new UglifyJSPlugin()
]
複製代碼
webpack --display-used-exports --optimize-minimize
webpack --mode production
複製代碼
大網站有多個頁面,每一個頁面因爲採用相同技術棧和樣式代碼,會包含不少公共代碼,若是都包含進來會有問題
如何使用 common-chunk-and-vendor-chunk
entry: {
pageA: './src/pageA',
pageB: './src/pageB'
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
maxInitialRequests: 5, // The default limit is too small to showcase the effect
minSize: 0 // This is example is too small to create commons chunks
},
vendor: {
test: /node_modules/,
chunks: "initial",
name: "vendor",
priority: 10,
enforce: true
}
}
}
},
複製代碼
Scope Hoisting 可讓 Webpack 打包出來的代碼文件更小、運行的更快, 它又譯做 "做用域提高",是在 Webpack3 中新推出的功能。
export default 'Hello';
複製代碼
import str from './hello.js';
console.log(str);
複製代碼
var util = ('Hello');
console.log(util);
複製代碼
函數由兩個變成了一個,hello.js 中定義的內容被直接注入到了 main.js 中
const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');
module.exports = {
resolve: {
// 針對 Npm 中的第三方模塊優先採用 jsnext:main 中指向的 ES6 模塊化語法的文件
mainFields: ['jsnext:main', 'browser', 'main']
},
plugins: [
// 開啓 Scope Hoisting
new ModuleConcatenationPlugin(),
],
};
複製代碼
--display-optimization-bailout
複製代碼
代碼分離是 webpack 中最引人注目的特性之一。此特性可以把代碼分離到不一樣的 bundle 中,而後能夠按需加載或並行加載這些文件。 有三種經常使用的代碼分離方法:
`entry: {
index: './src/index.js',
another: './src/another-module.js'
}
複製代碼
splitChunks能夠將公共的依賴模塊提提取到一個新生成的 chunk. common-chunk-and-vendor-chunk
optimization: {
splitChunks: {
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2
},
vendor: {
test: /node_modules/,
chunks: "initial",
name: "vendor",
}
}
複製代碼
用戶當前須要用什麼功能就只加載這個功能對應的代碼,也就是所謂的按需加載 在給單頁應用作按需加載優化時,通常採用如下原則:
document
.getElementById('clickMe')
.addEventListener('click', () => {
import (/*webpackChunkName:"alert"*/
'./alert').then(alert => {
console.log(alert);
alert.default('hello');
});
});
複製代碼
loaders: [
{
loader: 'babel-loader',
query: {
presets: ["env", "stage-0", "react"]
}
}
]
複製代碼
webpack-dev-middleware 插件對更改的文件進行監控,編譯,通常和 webpack-hot-middleware 配合使用,實現熱加載功能 webpack-dev-middleware webpack-hot-middleware
const path = require("path")
const express = require("express")
const webpack = require("webpack")
const webpackDevMiddleware = require("webpack-dev-middleware")
const webpackConfig = require('./webpack.config.js')
const app = express(),
DIST_DIR = path.join(__dirname, "dist"),// 設置靜態訪問文件路徑
PORT = 9090, // 設置啓動端口
complier = webpack(webpackConfig)
app.use(webpackDevMiddleware(complier, {
//綁定中間件的公共路徑,與webpack配置的路徑相同
publicPath: webpackConfig.output.publicPath,
quiet: true //向控制檯顯示內容
}))
// 這個方法和下邊註釋的方法做用同樣,就是設置訪問靜態文件的路徑
app.use(express.static(DIST_DIR))
app.listen(PORT,function(){
console.log("成功啓動:localhost:"+ PORT)
})
複製代碼
webpack --profile --json > stats.json
複製代碼
Webpack 官方提供了一個可視化分析工具 Webpack Analyse
當用 Webpack 去構建一個能夠被其餘模塊導入使用的庫時須要用到它們。
output.libraryTarget 是字符串的枚舉類型,支持如下配置。
編寫的庫將經過 var 被賦值給經過 library 指定名稱的變量。
假如配置了 output.library='LibraryName',則輸出和使用的代碼以下:
// Webpack 輸出的代碼
var LibraryName = lib_code;
// 使用庫的方法
LibraryName.doSomething();
假如 output.library 爲空,則將直接輸出:
複製代碼
lib_code 其中 lib_code 代指導出庫的代碼內容,是有返回值的一個自執行函數。
編寫的庫將經過 CommonJS 規範導出。
假如配置了 output.library='LibraryName',則輸出和使用的代碼以下:
// Webpack 輸出的代碼
exports['LibraryName'] = lib_code;
// 使用庫的方法
require('library-name-in-npm')['LibraryName'].doSomething();
其中 library-name-in-npm 是指模塊發佈到 Npm 代碼倉庫時的名稱。
複製代碼
編寫的庫將經過 CommonJS2 規範導出,輸出和使用的代碼以下:
// Webpack 輸出的代碼
module.exports = lib_code;
// 使用庫的方法
require('library-name-in-npm').doSomething();
CommonJS2 和 CommonJS 規範很類似,差異在於 CommonJS 只能用 exports 導出,而 CommonJS2 在 CommonJS 的基礎上增長了 module.exports 的導出方式。
在 output.libraryTarget 爲 commonjs2 時,配置 output.library 將沒有意義。
複製代碼
編寫的庫將經過 this 被賦值給經過 library 指定的名稱,輸出和使用的代碼以下:
// Webpack 輸出的代碼
this['LibraryName'] = lib_code;
// 使用庫的方法
this.LibraryName.doSomething();
複製代碼
編寫的庫將經過 window 被賦值給經過 library 指定的名稱,即把庫掛載到 window 上,輸出和使用的代碼以下:
// Webpack 輸出的代碼
window['LibraryName'] = lib_code;
// 使用庫的方法
window.LibraryName.doSomething();
複製代碼
編寫的庫將經過 global 被賦值給經過 library 指定的名稱,即把庫掛載到 global 上,輸出和使用的代碼以下:
// Webpack 輸出的代碼
global['LibraryName'] = lib_code;
// 使用庫的方法
global.LibraryName.doSomething();複製代碼